本文隸屬於AVR單片機教程系列。
上一講中,我們實現了單片機開發板向電腦傳輸數據。在這一講中,我們將通過電腦向單片機發送指令,讓單片機根據指令控制LED。這一次,兩端的TX與RX需要交叉連接,單片機TX連接串口工具RX也是需要的,因為程序會根據指令反饋信息。
為了簡單起見,我們的程序只需要控制4個板載LED。指令包含兩個字節:第一個字節為r、y、g、b中的一個,分別表示紅、黃、綠、藍燈;第二個字節為0或1,表示燈不亮或亮。
然而,a2這樣的指令是沒有意義的,卻是可能出現的。即使用戶已經熟悉了這8條指令,也可能會不小心打錯。我們應當記住,用戶是世界上最愚蠢的人,我們要把他們可能犯的錯誤都想到,然后在程序中合理地處理。比如,對於不合法的指令,程序忽略指令,並返回What?給電腦;對於合法的,則執行並返回Done!。
#include <ee1/led.h>
#include <ee1/uart.h>
int main(void)
{
led_init();
uart_init(UART_DUPLEX);
char temp[3];
while (1)
{
uart_scan_string_n(temp, 2);
bool good = true;
led_t led;
switch (temp[0])
{
case 'r': led = LED_RED ; break;
case 'y': led = LED_YELLOW; break;
case 'g': led = LED_GREEN ; break;
case 'b': led = LED_BLUE ; break;
default: good = false; break;
}
bool on;
switch (temp[1])
{
case '0': on = false; break;
case '1': on = true ; break;
default: good = false; break;
}
if (good)
{
led_set(led, on);
uart_print_string("Done!\n");
}
else
uart_print_string("What?\n");
}
}
while循環的周期是多少呢?沒有delay語句,是不是循環在很快地掃描呢?不是,uart_scan_string_n函數一直等待直到串口接收到了規定量的數據。
實際上,這一系列串口接收的函數的功能非常受限——程序必須等待數據到來,不能錯過它,這與scanf等函數從緩沖區讀取數據不同。當然,單片機系統中的串口輸入(以及輸出)也可以實現緩沖區,並且是一種實用並常用的做法,但這要涉及到中斷,是以后的內容。你可以試着利用數據手冊以及其他資源實現一個帶緩沖的串口輸入輸出。在avr-gcc中,使用中斷要先#include <avr/interrupt.h>,串口接收中斷寫為ISR(USART0_RX_vect) { }。
作業:
-
如果通過串口發送指令
r11g1,只有紅色LED會亮,因為程序對指令的解讀是r1、1g、1,而我只是不小心(故意)多打了一個1,本意是想讓紅色和綠色LED都亮。改進程序解決這個問題。 -
基於
uart_scan_char,實現my_scan_int函數,從串口上讀取十進制整數(注意正負號與溢出等;你可以了解一下atoi)。
