上一篇我们分享了Grbl串口的serial.c源码,接下来我们将通过动手编写几个例子来深入了解Arduino底层关于串口寄存器的用法。
开始之前介绍一下与串口相关的寄存器:
UCSRnA and UCSRnB and UCSRnC: USART Control and Status Register n A 串口控制与状态寄存器
UDRn: USART I/O Data Register n 串口IO数据寄存器
UBRRnL and UBRRnH – USART Baud Rate Registers 串口波特率寄存器
首先我们需要设置串口的波特率,这里以115200为例。为什么要用这个波特率呢?因为性能,现在电脑性能很好了,没必要再使用9600这么小的波特率,为什么不用更大的250000波特率?因为这个波特率不是标准值,在linux或mac上出问题的概率比较大。
我们查看atmega328p芯片文档,来说明如何通过寄存器设置波特率:
可以看出,要设置成115200的波特率,需要配置UBRRn的值为16,当晶振频率为16MHz时,并且U2Xn的值设置为1,这也是Grbl中的默认配置,为什么要让U2Xn的值设置为1呢?因为误差更小,从上图表中可以看到,U2Xn=0时误差为-3.5%,U2Xn=1时误差为2.1%。
接下来是计算UBRRn的值,官方给出的计算公式为:ubrrn = fosc/(8*baud)-1。16000000/(8*115200)-1 = 16.36111111111111取整后得到16,这也是表中16这个值的来源。
接下来要设置UBRRn寄存器,由于ubrrn的值有可能大于256,所以需要两个8为的寄存器存放,这两个寄存器名称分别为UBRR0H和UBRR0L,我们通过把ubrrn右移8位得到高位,然后再把值分别存入这两个寄存器:
UBRR0H=ubrrn>>8;
UBRR0L=ubrrn;
这样波特率就设置好了。
接下来是开启串口的发送功能:这个功能是UCSR0B寄存器控制的,控制位是TXN0。配置方法如下:
UCSR0B |= (1<<TXN0);
然后是向串口发送数据:这涉及到两个寄存器,一个是数据的状态寄存器UCSR0A,一个是数据寄存器UDR0。在UCSR0A中判断数据是否为空,如果为空的话说明串口发送空闲,可以发送数据,否则一直等到已有数据发送完。实现方法如下:
int i = 0;
for (;;)
{
i = 0;
while (data[i]!=0)
{
while(!(UCSR0A&(1<<UDRE0))); // 数据寄存器是否为空才写入
UDR0 = data[i];
i++;
}
}
完整代码如下:
把代码上传到arduino开发板上,打开串口监视器,波特率设为115200,8位,无奇偶校验,1停止位。这时候能看到串口输出的hello world信息。
下一篇我们将分享通过中断设置串口的读取和写入。