【问题标题】:Avr Problem: in spi, spdr register is 8 bit but my number is 16 bit [closed]Avr 问题:在 spi 中,spdr 寄存器是 8 位,但我的号码是 16 位 [关闭]
【发布时间】:2019-08-15 08:12:58
【问题描述】:

我在主机和从机中都使用 atmega16。 我想将通过键盘输入的 100-999 之间的数字发送给从站。 数字是 16 位,但 spdr 寄存器是 8 位,所以我先发送 lsb 然后发送 msb 位。这很好用,我正确地发送了我的号码。

但我的问题是在奴隶方面: 我在从机端启用了中断间谍,因此从主机接收到的每个 spdr 都作为中断并进入 ISR 功能。但是因为我的数字是16位的,所以我想把每个16位或两个字节作为一个中断。我该怎么办?

【问题讨论】:

  • 理想情况下,您应该在从设备端获得两个中断 - 每个字节一个。为什么不将它们保存到缓冲区并增加计数以查看有多少来了?
  • 在从机端,我 while() 我有一个可以运行的函数,我想在收到两个字节时执行一个 ISR 函数。不是在收到一个字节时。当我在 avr spi interupt 中自动启用 spi 中的中断时,当接收到一个字节时,它会进入 ISR。我想做一些事情,当收到两个字节时它会进入 ISR。
  • 根据您使用的特定微控制器,您可能可以在 SPI 外设配置中设置 16 位的传输大小,不确定您使用的是否允许这样做。另一种选择是使用 DMA(再次,如果可能的话在您的设备上)将字节从 SPI DR 复制到缓冲区,并对其进行编程以在收到两个字节后发出中断。不过,我仍然不明白是什么阻止了您分别处理两个 SPI RX 中断!
  • 另外,请尝试更好地构建您的问题,并尽可能提供代码和更好的上下文,以便人们容易理解您的问题。
  • 主端发送一个16位的数字。例如 999,我在 atmega32 中的 spdr 寄存器是 8 位的,所以我将我的 16 位数字分成两个 8 位包并分两步发送。在master方面没问题。在从机端,while(1) 中的 i 函数按段(数字)函数显示 7segnent 中的数字。我希望 segment() 总是这样做,但是当一个 16 位数字接收它时它会改变。所以我启用了中断并编写了一个 ISR 函数。但是每个 8 位都进入 ISR。我可以使用 for(i=0,i

标签: c avr spi atmelstudio atmega16


【解决方案1】:

您知道您的消息长度(16 位或 2 字节)。只需创建一个环形缓冲区来存储两个字节并填充环形缓冲区。也许您可以添加第三个字节作为开始或结束字节或其他内容,但这取决于您。另外,如果您的传输结束,您会设置一个标志。

所以您的代码可以如下所示。请注意,此代码只是 ISR 和 XMega 作为 SPI 从机,但它应该有助于理解该过程。

#define SPI_BUFFER_SIZE                     2
uint8_t SPI_RxSlaveBuffer[SPI_BUFFER_SIZE];

typedef struct 
{
    uint8_t* RxBuffer;
    uint8_t BytesProcessed;
    uint8_t Status;
} SPI_Buffer_t;

static SPI_Buffer_t SlaveBuffer;

int main()
{
   // Some code
   SlaveBuffer.RxBuffer = SPI_RxSlaveBuffer;
   // Some other code
}

ISR(SPIC_INT_vect)
{
    SlaveBuffer.RxBuffer[SlaveBuffer.BytesProcessed++] = SPIC.DATA;

    if(SlaveBuffer.BytesProcessed >= SPI_BUFFER_SIZE - 1)
    {
        SlaveBuffer.BytesProcessed = 0x00;
        SlaveBuffer.Status = 0x01;
    }
}

您还可以检查SS 引脚的状态并在主控器断言该引脚时重置计数器(以防主控器已中止传输或其他情况) - 例如通过轮询SS引脚或将SS 引脚的信号连接到中断引脚以产生额外的 I/O 中断。

【讨论】:

  • 您似乎没有为uint8_t* RxBuffer 分配内存。为什么不使用数组呢?
  • 我在我的代码中分配了内存,但在这个例子中只是缺少它。我已经添加它以避免误解。这个例子是我一个更大的代码的一部分,我用一个函数来设置缓冲区的地址来交换缓冲区。
  • SS 的后沿使用中断的想法很好,应该详细说明。它为 OP 提供每次传输的单个中断。
  • 但是您不能在 OP 正在使用的 ATmega16 上使用后沿中断,因为该引脚不是中断引脚。您可以在查看数据表时看到它。它是一个旧的 MCU,因此并非每个引脚都可以与中断一起使用。该微控制器只有三个用于外部中断的引脚。所以你只有 SPI 中断和SS pin 的轮询:(
  • @thebusybee 您可以使用一个中断引脚作为非硬件SS 引脚并在从机上启动基于非中断的接收。因此,您不使用 SPI 中断,只使用一个 GPIO 中断并在 GPIO ISR 中处理整个 SPI 通信。但此解决方案将阻止所有其他中断,直到 SPI 通信完成。但这也是一个解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-14
  • 2016-10-12
  • 2021-07-21
  • 2011-01-15
  • 1970-01-01
  • 2017-07-12
相关资源
最近更新 更多