zhuomuniao110 发表于 2024-3-25 21:25

AVR使用中断接收串口消息

USART 控制 A 寄存器
CTRLA 寄存器用于启用/禁用不同的中断。我们将只使用中断来接收数据,因此请设置此寄存器的位 7。
USART0.CTRLA = (1<<7);// Enable RXCIE interrupt
USART 控制 B 寄存器

该寄存器的位 6 和 7 用于启用/禁用 UART 的发射器和接收器。我们将启用这些位,以便启用发射器和接收器。此外,位 将接收器设置为不同的可用模式。我们将这些位保留为 0 以将接收器设置为正常模式。
该寄存器位的复位保持其默认状态,即 diabled。

USART0.CTRLB = (1<<7)|(1<<6);// RX & TX enable, Normal mode, SOF disabled

寄存器是 USART 控制 C 寄存器。

这里我们设置常用的UART配置,它由8个数据位和1个停止位组成,没有奇偶校验。UART 模式设置为异步模式。
寄存器的最终值为 0x03。

<div><div>USART0.CTRLC = 0x03;// Asynch mode, no parity, 1 stop bit, 8 data bits</div></div><div></div>下一个寄存器是波特寄存器。这是一个 16 位寄存器,该寄存器中的值决定了 UART 的波特率。下图显示了计算所需波特率的波特寄存器值的公式。


我们的时钟配置为使用20MHz内部振荡器,预分频器为4。这会将时钟降低到 5MHz。CPU 和外设 (CLK_PER) 使用相同的时钟。如下图所示。

对于5MHz的外设时钟和115200的所需波特率,波特寄存器值计算如下所示。

参数 S 是每位的样本数,对于异步正常模式,它的值为 16。我们不能在 16 位寄存器中输入十进制值,因此我们将输入值 174。

USART0.BAUD = 174;

我们将使用 STATUS 寄存器来监控数据传输是否已完成。

此寄存器 (TXCIF) 的位 6 在 TXDATA 寄存器中的数据移出时设置。在配置过程中,我们将通过将 1 写入其中来清除此位。
USART0.STATUS |= 1<<6; // clear TXCIF flag
现在我们将配置 UART 的引脚。引脚 PB2 是 UART TX 引脚,必须设置为输出,而引脚 PB3 是 UART RX 引脚,必须设置为输入。
PORTB.DIR = 0x04;//0b00000100 -> PB2->OUT, PB3->IN
这样就完成了 UART 配置。以下是包含上述寄存器配置的最终代码。
void uartInit (void)
{
        USART0.CTRLA = (1<<7);// Enable RXCIE interrupt
        USART0.CTRLB = (1<<7)|(1<<6);// RX & TX enable, Normal mode, SOF disabled
        USART0.CTRLC = 0x03;// Asynch mode, no parity, 1 stop bit, 8 data bits
        USART0.BAUD = 174;
        USART0.STATUS |= 1<<6; // clear TXCIF flag
       
        PORTB.DIR = 0x04;// PB2->OUT, PB3->IN

}









zhuomuniao110 发表于 2024-3-25 21:26

接收数据
由于我们使用 interrupt 接收数据,因此我们不需要为其编写单独的函数。让我们看看主要功能。
char RxData;
int indx = 0;

int main(void)
{
clkInit();
uartInit();
sei();
while(1)
{

}
}
在这里,我们将首先定义一个数组来存储接收到的数据,以及一个索引变量来跟踪接收到的数据。
在 main 函数中,我们将首先初始化时钟,然后初始化 UART。然后通过调用函数 sei() 启用全局中断。
在接收缓冲区中接收到数据后,将触发 RXC(接收完成)中断。我们将编写一个中断服务例程 (ISR) 来处理此中断。
ISR (USART0_RXC_vect)
{
        RxData = USART0.RXDATAL;
        if (indx>=10) indx =0;
}

zhuomuniao110 发表于 2024-3-25 21:27

中断是为接收缓冲区接收的每个数据字节设置的。在 ISR 函数中,我们将从 RXDATAL 寄存器复制数据并存储在 RxData 数组中。

然后递增 indx 变量,以便可以将新数据字节存储在新位置。我们的 RxData 缓冲区最多可以存储 10 个字节,因此如果 indx 变量大于或等于 10,我们会将变量重置为 0。这将再次从头开始存储数据。

黑心单片机 发表于 2024-3-26 14:37

为啥缓冲区这么小

小明的同学 发表于 2024-3-26 20:22

时钟系统不是特别复杂。

小明的同学 发表于 2024-3-26 20:23

缓冲区足够用了。

菜鸟的第一步 发表于 2024-3-28 13:02

中断接收,效率高
页: [1]
查看完整版本: AVR使用中断接收串口消息