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

AVR如何配置UART和发送数据

[复制链接]
931|6
手机看帖
扫描二维码
随时随地手机跟帖
gejigeji521|  楼主 | 2024-3-25 20:31 | 显示全部楼层 |阅读模式
xplained 迷你开发板支持虚拟 com 端口,这意味着我们不需要外部硬件即可通过 UART 与计算机通信。我们可以简单地使用用于编程/调试的 USB 从计算机发送和接收数据。
下图显示了当 USB 连接到电路板时在计算机上检测到虚拟 com 端口。
5037966016e61c7401.png
如上图所示,mEDBG 虚拟 COM 端口连接到 COM11。
如果您仍想使用任何 USB 到 UART 转换器,则其连接如下所示。
9917166016e7e62887.png
MCU的TX引脚连接到模块的RX引脚,MCU的RX引脚连接到模块的TX引脚。UART 连接始终在十字架中建立。另请注意,引脚 PB2 是 TX 引脚,我们将它设置为输出,引脚 PB3 是 RX 引脚,我们将它设置为输入。


使用特权

评论回复
gejigeji521|  楼主 | 2024-3-25 20:35 | 显示全部楼层
配置 UART,从 USART 控制 B 寄存器开始。
7514966016ea0daf8a.png
该寄存器的位 6 和 7 用于启用/禁用 UART 的发射器和接收器。我们将启用这些位,以便启用发射器和接收器。此外,位 [2:1] 将接收器设置为不同的可用模式。我们将这些位保留为 0 以将接收器设置为正常模式。

该寄存器位的复位保持其默认状态,即 diabled。

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

下一个寄存器是 USART 控制 C 寄存器。
4900266016ec52ce17.png
这里我们设置常用的UART配置,它由8个数据位和1个停止位组成,没有奇偶校验。UART 模式设置为异步模式。
寄存器的最终值为 0x03。
USART0.CTRLC = 0x03;  // Asynch mode, no parity, 1 stop bit, 8 data bits

下一个寄存器是波特寄存器。这是一个 16 位寄存器,该寄存器中的值决定了 UART 的波特率。下图显示了计算所需波特率的波特寄存器值的公式.
1581466016ef5cddc9.png
我们的时钟配置为使用20MHz内部振荡器,预分频器为4。这会将时钟降低到 5MHz。CPU 和外设 (CLK_PER) 使用相同的时钟。如下图所示。
1717466016f055b5ae.png
对于5MHz的外设时钟和115200的所需波特率,波特寄存器值计算如下所示。
5015466016f1bb3f65.png
参数 S 是每位的样本数,对于异步正常模式,它的值为 16。
我们不能在 16 位寄存器中输入十进制值,因此我们将输入值 174。
USART0.BAUD = 174;

我们将使用 STATUS 寄存器来监控数据传输是否已完成。
1411266016f474c96a.png
此寄存器 (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.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
       
}



使用特权

评论回复
gejigeji521|  楼主 | 2024-3-25 20:36 | 显示全部楼层
传输数据
传输单个字节
TXDATAL(低字节)和 TXDATAH(高字节)寄存器用于传输数据。
174766016f98822e9.png
只有当我们在配置中使用 9 个数据位时,才使用 TXDATAH 寄存器。但是我们已将 UART 配置为使用 8 个数据位,因此我们将只使用 TXDATAL。
void uartsendByte (uint8_t data)
{
  USART0.TXDATAL = data;
  while(((USART0.STATUS)&(1<<6)) == 0);  // wait for the TXCIF bit to set
  USART0_STATUS |= (1<<6);        // clear TXCIF flag
}

要传输一个字节的数据,我们只需将数据复制到 TXDATAL 寄存器中,然后等待状态寄存器中的 TXCIF 位设置。该位将确认数据已传输,然后我们可以将新数据加载到寄存器中。

使用特权

评论回复
gejigeji521|  楼主 | 2024-3-25 20:37 | 显示全部楼层
传输字符串
要传输整个字符串,请调用字节传输函数的次数与字符串的长度一样多。
void uartSendStr (char *str)
{
        while (*str)
        {
                uartsendByte(*str++);
        }
}


使用特权

评论回复
gejigeji521|  楼主 | 2024-3-25 20:37 | 显示全部楼层
char data[] = "hello world from AVR\r\n";

int main(void)
{
  clkInit();
  uartInit();
  while(1)
  {
      uartSendStr(data);
      _delay_ms(1000);
  }
}


在 main 函数中,我们将首先初始化时钟,然后初始化 UART。在 while 循环中,我们将每 1 秒发送一次字符串。
585826601701ac6265.png
您可以看到终端上正在接收字符串。另请注意,终端配置了我们为 UART 设置的相同设置,即 115200 波特率,具有 8 个数据位、1 个停止位和无奇偶校验。

使用特权

评论回复
21mengnan| | 2024-3-25 21:46 | 显示全部楼层
讲的很不错,从寄存器计算到配置。

使用特权

评论回复
我喜欢打游戏| | 2024-3-26 14:08 | 显示全部楼层
代码很详细,原理也清楚

使用特权

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

本版积分规则

166

主题

2141

帖子

8

粉丝