[PIC®/AVR®/dsPIC®产品] AVR使用中断接收串口消息

[复制链接]
18541|6
 楼主| zhuomuniao110 发表于 2024-3-25 21:25 | 显示全部楼层 |阅读模式
USART 控制 A 寄存器
CTRLA 寄存器用于启用/禁用不同的中断。我们将只使用中断来接收数据,因此请设置此寄存器的位 7。
  1. USART0.CTRLA = (1<<7);  // Enable RXCIE interrupt
USART 控制 B 寄存器

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

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

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

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

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

  10. }









本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| zhuomuniao110 发表于 2024-3-25 21:26 | 显示全部楼层
接收数据
由于我们使用 interrupt 接收数据,因此我们不需要为其编写单独的函数。让我们看看主要功能。
  1. char RxData[10];
  2. int indx = 0;

  3. int main(void)
  4. {
  5.   clkInit();
  6.   uartInit();
  7.   sei();
  8.   while(1)
  9.   {

  10.   }
  11. }

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

 楼主| 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 | 显示全部楼层
中断接收,效率高
您需要登录后才可以回帖 登录 | 注册

本版积分规则

233

主题

3529

帖子

11

粉丝
快速回复 在线客服 返回列表 返回顶部