C Avr问题:在spi中,spdr寄存器是8位,但我的数字是16位

C Avr问题:在spi中,spdr寄存器是8位,但我的数字是16位,c,avr,spi,atmelstudio,atmega16,C,Avr,Spi,Atmelstudio,Atmega16,我和atmega16一起工作,包括主控和从控。 我想将通过键盘输入的100-999之间的数字发送到从机。 数字是16位,但spdr寄存器是8位,所以我先发送lsb,然后发送msb位。这工作得很好,我发送的号码正确 但我的问题是在奴隶方面: 我在从端启用了中断spie,所以从主端接收到的每个spdr都作为一个中断,并进入ISR功能。但是因为我的数字是16位,所以我想把每个16位或两个字节作为一个中断。我该怎么办?您知道您的消息长度(16位或2字节)。只需创建一个环形缓冲区来存储两个字节,然后填充环

我和atmega16一起工作,包括主控和从控。 我想将通过键盘输入的100-999之间的数字发送到从机。 数字是16位,但spdr寄存器是8位,所以我先发送lsb,然后发送msb位。这工作得很好,我发送的号码正确

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

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

因此,您的代码可以如下所示。注意:此代码仅适用于ISR和XMega as 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中断。

理想情况下,从机端应该有两个中断-每个字节一个。为什么不把它们保存到一个缓冲区,然后增加一个计数,看看有多少来了呢?在从机端,我有一个可以操作的函数,当接收到两个字节时,我想做一个ISR函数。当接收到一个字节时不会。当我在avr spi interupt中自动在spi中启用interupt时,当接收到一个字节时,它将转到ISR。我想做一件事,当两个字节的rcived时,它将进入ISR。根据您使用的特定微控制器,您可能能够在SPI外围设备配置中设置16位的传输大小,但不确定您使用的是否允许这样做。另一种选择是使用DMA(同样,如果可能,在您的设备上)将字节从SPI DR复制到缓冲区,并对其进行编程,以便在接收到两个字节后发出中断。我仍然不明白是什么阻止你分别处理两个SPI接收中断!另外,请尝试更好地阐述您的问题,如果可能,请提供代码和更好的上下文,以便人们容易理解您的问题。例如999,我在atmega32中的spdr寄存器是8位的,所以我将我的16位数字分成两个8位包,分两步发送。在主机侧是可以的。在从机端,当(1)在7segnent by segment(数字)功能中显示数字时,i在其中的一个功能。我希望segment()总是这样,但当一个16位的数字收到时,它会改变。所以我启用了中断并编写了一个ISR函数。但每8位都将被传送到ISR。我可以为用户提供服务吗(i=0,i您似乎没有为
uint8\u t*RxBuffer
分配内存。为什么不改为使用数组呢?我在代码中分配内存,但在本例中它只是丢失了。我添加了它以避免误解。本例是我编写的一个更大代码的一部分,我使用一个函数来交换缓冲区。id关于在
SS
后缘使用中断的ea很好,应该详细说明。它为OP提供了每次传输的单个中断。但是您不能在OP使用的
ATmega16
上使用后缘中断,因为该引脚不是中断引脚。您可以在查看数据表时看到它。它是一个旧的MCU,因此不是每个引脚都可以用于中断。此微控制器只有三个引脚用于外部中断。因此您只有SPI中断和
SS
引脚的轮询:(@thebusybee您可以使用一个中断引脚作为非硬件
SS
引脚,并在从机上启动非中断接收。因此,您不使用SPI中断,只使用一个GPIO中断,并在GPIO ISR中处理整个SPI通信。但此解决方案将阻止所有其他中断,直到SPI通信完成。但是这也是一个解决办法。