【问题标题】:Why should I use & in this syntax? Problem with SPI register为什么我应该在这种语法中使用 & ? SPI寄存器的问题
【发布时间】:2020-12-07 21:58:36
【问题描述】:

我正在为 LPC2109/2 和 MCP4921 之间的 SPI 通信编写程序。这是一个任务 关于学业。我的导师问我一个问题,为什么在这一行中需要“&”?在这一行中,我们等待 SPI 传输结束。哪个答案应该是正确的?

    #define SPI_SPIF_bm  (1<<7)
    ...
    while((S0SPSR & SPI_SPIF_bm) == 0){}
  1. 我们使用“&”作为逻辑与,例如:(0000 & 1000) 给我们 0000 而不是 (0000 | 1000) 给我们 1000。
  2. 我可以只使用这行代码:while((S0SPSR) == 0){}吗?在我看来 - 不。我们需要将寄存器S0SPSR 中的值与位SPIF SPI_SPIF_bm 进行比较。

可能有不同的解决方案吗?

附件
LPC2129/01用户手册:https://www.nxp.com/docs/en/user-guide/UM10114.pdf

【问题讨论】:

  • 您是在问位掩码是什么意思还是寄存器的作用是什么?

标签: embedded spi


【解决方案1】:

LPC2109/2 的 SPI 外设根据发生的实际事件设置不同的位 S0SPSR,这可能取决于外部环境。例如,如果 SPI 线上发生写入冲突,它会设置 WCOL 位而不是 SPIF

如果您使用while((S0SPSR) == 0){},它会一直等待,直到交易成功或发生错误,因为如果S0SPSR 的任何位被设置,它将退出循环。

while((S0SPSR &amp; SPI_SPIF_bm) == 0){} 只检查事务是否成功完成。检查错误位也是一个好习惯,因为如果出现错误,您将永远停留在此循环中,因为永远不会设置 SPIF

对于一个强大的解决方案,我会选择这样的:

while(S0SPSR == 0) {}

if (S0SPSR & SPI_SPIF_bm) { /* SPI_SPIF_bm remains set until data register has not been accessed */
     /* Success, read the data register, return data, etc. */
} else {
     /* Handle error */
}

如果您对特定类型的错误感兴趣,则需要在每个周期将S0SPSR 存储在一个变量中,因为这些位在读取S0SPSR 时会被清除。如果在合理的时间段内没有设置任何标志,您还应该向循环添加一个计数器或更复杂的超时解决方案以退出。

您可能认为这些错误永远不会发生,因为您有一个简单的电路,但它们确实会在现实生活中发生,因此值得进行适当的错误处理。

【讨论】:

  • 感谢您的快速响应!检查错误代码的建议是个好主意。我会试试的:)
  • 一般来说,这是草率的编码。你应该有volatile uint32_t s0spsr=0; while(s0spsr==0) { s0spsr = S0SPSR;} ... if(s0spsr &amp; mask) { ...。这是为了避免不必要地多次读取寄存器。这在 SPI 的情况下尤其成问题,其中有时会通过读取标志来清除标志,然后读取数据寄存器。
猜你喜欢
  • 2021-11-13
  • 2020-07-15
  • 1970-01-01
  • 2019-01-23
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 2020-06-19
  • 2018-09-02
相关资源
最近更新 更多