打印
[PIC®/AVR®/dsPIC®产品]

AVR使用中断接收串口消息

[复制链接]
7655|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
USART 控制 A 寄存器
CTRLA 寄存器用于启用/禁用不同的中断。我们将只使用中断来接收数据,因此请设置此寄存器的位 7。
USART0.CTRLA = (1<<7);  // Enable RXCIE interrupt
USART 控制 B 寄存器

该寄存器的位 6 和 7 用于启用/禁用 UART 的发射器和接收器。我们将启用这些位,以便启用发射器和接收器。此外,位 [2:1] 将接收器设置为不同的可用模式。我们将这些位保留为 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[10];
int indx = 0;

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

  }
}

在这里,我们将首先定义一个数组来存储接收到的数据,以及一个索引变量来跟踪接收到的数据。
在 main 函数中,我们将首先初始化时钟,然后初始化 UART。然后通过调用函数 sei() 启用全局中断。
在接收缓冲区中接收到数据后,将触发 RXC(接收完成)中断。我们将编写一个中断服务例程 (ISR) 来处理此中断。
ISR (USART0_RXC_vect)
{
        RxData[indx++] = 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 | 只看该作者
为啥缓冲区这么小

使用特权

评论回复
5
小明的同学| | 2024-3-26 20:22 | 只看该作者
时钟系统不是特别复杂。

使用特权

评论回复
6
小明的同学| | 2024-3-26 20:23 | 只看该作者
缓冲区足够用了。

使用特权

评论回复
7
菜鸟的第一步| | 2024-3-28 13:02 | 只看该作者
中断接收,效率高

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

188

主题

3241

帖子

10

粉丝