上一篇我們分享了Grbl串口的serial.c源碼,接下來我們將通過動手編寫幾個例子來深入了解Arduino底層關(guān)于串口寄存器的用法。
開始之前介紹一下與串口相關(guān)的寄存器:
UCSRnA and UCSRnB and UCSRnC: USART Control and Status Register n A 串口控制與狀態(tài)寄存器
UDRn: USART I/O Data Register n 串口IO數(shù)據(jù)寄存器
UBRRnL and UBRRnH – USART Baud Rate Registers 串口波特率寄存器
首先我們需要設(shè)置串口的波特率,這里以115200為例。為什么要用這個波特率呢?因為性能,現(xiàn)在電腦性能很好了,沒必要再使用9600這么小的波特率,為什么不用更大的250000波特率?因為這個波特率不是標(biāo)準(zhǔn)值,在linux或mac上出問題的概率比較大。
我們查看atmega328p芯片文檔,來說明如何通過寄存器設(shè)置波特率:

可以看出,要設(shè)置成115200的波特率,需要配置UBRRn的值為16,當(dāng)晶振頻率為16MHz時,并且U2Xn的值設(shè)置為1,這也是Grbl中的默認(rèn)配置,為什么要讓U2Xn的值設(shè)置為1呢?因為誤差更小,從上圖表中可以看到,U2Xn=0時誤差為-3.5%,U2Xn=1時誤差為2.1%。
接下來是計算UBRRn的值,官方給出的計算公式為:ubrrn = fosc/(8*baud)-1。16000000/(8*115200)-1 = 16.36111111111111取整后得到16,這也是表中16這個值的來源。
接下來要設(shè)置UBRRn寄存器,由于ubrrn的值有可能大于256,所以需要兩個8為的寄存器存放,這兩個寄存器名稱分別為UBRR0H和UBRR0L,我們通過把ubrrn右移8位得到高位,然后再把值分別存入這兩個寄存器:
UBRR0H=ubrrn>>8;
UBRR0L=ubrrn;
這樣波特率就設(shè)置好了。
接下來是開啟串口的發(fā)送功能:這個功能是UCSR0B寄存器控制的,控制位是TXN0。配置方法如下:
UCSR0B |= (1<<TXN0);
然后是向串口發(fā)送數(shù)據(jù):這涉及到兩個寄存器,一個是數(shù)據(jù)的狀態(tài)寄存器UCSR0A,一個是數(shù)據(jù)寄存器UDR0。在UCSR0A中判斷數(shù)據(jù)是否為空,如果為空的話說明串口發(fā)送空閑,可以發(fā)送數(shù)據(jù),否則一直等到已有數(shù)據(jù)發(fā)送完。實現(xiàn)方法如下:
int i = 0;
? ? for (;;)
? ? {
? ? ? ? i = 0;
? ? ? ? while (data[i]!=0)
? ? ? ? {
? ? ? ? ? ? while(!(UCSR0A&(1<<UDRE0))); // 數(shù)據(jù)寄存器是否為空才寫入
? ? ? ? ? ? UDR0 = data[i];
? ? ? ? ? ? i++;
? ? ? ? }
? ? }
完整代碼如下:

把代碼上傳到arduino開發(fā)板上,打開串口監(jiān)視器,波特率設(shè)為115200,8位,無奇偶校驗,1停止位。這時候能看到串口輸出的hello world信息。
下一篇我們將分享通過中斷設(shè)置串口的讀取和寫入。