昨天說到上下位機通訊的概念,以及假設了應用情境,並且根據期望長出最終應用上的程式碼,今天將會說明 CircusUart Library 各個 API 以及使用方式。
在一開始需要先建立 CircusUart 物件,並且在 Constructor 中帶入需要發送的 Serial Object Reference,並且需要自行在 Setup 方法中初始化並設定 Baudrate。
CircusUart uart(Serial);
void setup()
{
Serial.begin(57600);
}
CircusUart 使用非同步的方式接收並處理資料,使用者需要先在初始化時設定好需要接收的命令以及分隔符號,例如,當接收到溫度資料時判斷溫度是否大於 30 度,若大於 30 度則開啟風扇,設定需使用 on 方法,參數分別為:收到的命令開頭標記(Temp)、資料中間的分隔字元(:)、收到此筆資料要呼叫的方法,例如:
void setup()
{
Serial.begin(57600);
uart.on("Temp", ':', [](const char *temp) {
if(atoi(temp) > 30) {
digitalWrite(FAN_PIN, HIGH);
}
});
}
並且需要再 Arduinio Loop 方法內不斷輪詢檢查是否有資料進來
void loop()
{
uart.loop();
}
假設另一端每秒發送溫度資料,發送使用 send 方法,參數分別為:開頭標記(Temp)、資料中間的分隔字元(:)、要發送的資料內容(30.5)。
void loop()
{
static uint32_t timer = 0;
if (millis() > timer) {
timer = millis() + 1000;
uart.send("Temp", ':', "30.5");
}
}
使用起來就是這麼簡單~這樣我們只需要預先設定好雙方的資料標籤以及分隔字元,就可以很方便的將上下位機串連起來通訊了。
CircusUart.h 內部定義了 命令處理程序的最大數量(CIRCUS_HANDLER_MAX),此數值代表可註冊的命令數量,預設為16組,越多越佔記憶體,需要根據開發板適時調整;接收資料 Buffer長度(CIRCUS_RX_BUFF)預設為 32 Byte,若需傳輸的資料更長則需要調整此數值。
#define CIRCUS_HANDLER_MAX 16
#define CIRCUS_RX_BUFF 32
CircusUart Class Method 與 Member
class CircusUart : public Print {
private:
Stream &stream;
uint8_t receive(void);
handler_t handlers[CIRCUS_HANDLER_MAX];
uint8_t handler_idx;
char rec_buff[CIRCUS_RX_BUFF];
public:
CircusUart(Stream &stream);
~CircusUart();
void loop();
uint16_t send(const char *cmd, const char separator = '\0', const char *param = NULL);
void on(const char *cmd, const char separator, Func func);
size_t write(uint8_t);
size_t write(const char *buffer, size_t size);
};
我們將 CircusUart Class 繼承自 Arduino 內建 Print,所以一般 Serial 物件可以呼叫的方法 CircusUart 也能使用,如果使用的開發板核心有完整支援 C 語言 Stdio 則可以很方便的使用像是 printf 這類指令,讓發送資料更方便,例如:
uart.printf("Temp:%d", 30.5);
CircusUart.cpp 為每個方法的實作,內容較多就不過多說明,有興趣可以自行參考,目前CircusUart Library 只是初階版,只有簡單的傳送與接收,未來還會繼續加入其他常用功能,像是優先權,超時處理,使用 FreeRTOS 等等,讓我們使用 UART 通訊能更加方便且提高穩定性與效率,讓我們一起讓程式碼變得跟 Python 一樣簡潔吧~~。