直接使用 IDF 的SDK的事件机制,进行调用,实际上为内部维护创建线程,和 串口工作模式 (三)实现功能相同,这是IDFsdk 后期进行封装测试的,很少有介绍使用的,这里全部测试成功,类似于windows的串口编程了。这种方式,优势明显,serial和serlia1互不影响,在不同的线程内独立运行,实时性较高。这个事件测试了接收和错误处理,包括重启复位处理程序。这个使用了回调类函数的方式。当然也可以回调普通函数,函数原型要和内部定义相同。下一节将进行讲解
#include <inttypes.h>
#include <functional>
#include "HardwareSerial.h"
#include "esp_adc_cal.h"
#include "esp_task_wdt.h" //设置看门狗用
#include "soc/rtc_wdt.h"
#include "esp_err.h"
#include "esp_system.h"
#define TWDT_TIMEOUT_S 5
#define TASK_RESET_PERIOD_MS 1000
#define MAIN_DELAY_MS 10000
#define BTN_STOP_ALARM 0
#define LED_D4 12
#define LED_D5 13
#define TXD1 0
#define RXD1 1
#define ToggleOutput(out) do { digitalWrite(out, !digitalRead(out)); } while(0)
#define ToggleOutBlink(out,interval) do {static uint32_t estp=0;if( (millis()-estp)>=interval ){ estp=millis();digitalWrite(out, !digitalRead(out));} } while(0)
#define MaxUartErrorCount 20
#define MaxUartRxBufferSize 512
#define Uart0BaudRate 9600
#define Uart1BaudRate 115200
volatile uint16_t SerialErrCount;
volatile uint16_t Serial1ErrCount;
String comdata = "";//声明字符串变量
String comdata1 = "";//声明字符串变量
class TonReceiver1 {
public:
static void OnRxdata(void);
private:
};
class TonReceiver {
public:
static void OnRxdata(void);
private:
};
class TUartHWserial_error {
public:
static void OnReceiveErrorCbdata(hardwareSerial_error_t hwerr);
};
class TUartHWserial1_error {
public:
static void OnReceiveErrorCbdata(hardwareSerial_error_t hwerr);
};
void loop() {
// read from port 0, send to port 1:
if (Serial.available()) {
int inByte = Serial.read();
Serial1.print(inByte, DEC);
}
// read from port 1, send to port 0:
if (Serial1.available()) {
int inByte = Serial1.read();
Serial.print(inByte, DEC);
}
}
void Serial1Initialize(void){
Serial1.begin(Uart1BaudRate,SERIAL_8N1,RXD1,TXD1);//begin(speed,config,rxpin,txpin,bool invert,uint32_t TimeOutms);
Serial1.setRxBufferSize(MaxUartRxBufferSize);
Serial1.onReceive(TonReceiver1::OnRxdata);//调用onRXchar事件
Serial1.onReceiveError(TUartHWserial1_error::OnReceiveErrorCbdata);//调用错误事件
while(Serial1.read()>= 0){}//clear serialport
}
void SerialInitialize(void){
Serial.begin(Uart0BaudRate);
Serial.setRxBufferSize(MaxUartRxBufferSize);
Serial.onReceive(TonReceiver::OnRxdata);//调用onRXchar事件
Serial.onReceiveError(TUartHWserial_error::OnReceiveErrorCbdata);//调用错误事件
while(Serial.read()>= 0){}//clear serialport
}
void setup() {
Serial1Initialize();
SerialInitialize();
// Serial.setTxBufferSize(256);
// Serial1.setTxBufferSize(256);
while(Serial.read()>= 0){}//clear serialport
pinMode(LED_D4, OUTPUT);
pinMode(LED_D5, OUTPUT); //
digitalWrite(LED_D4, LOW);
digitalWrite(LED_D5, LOW);
esp_task_wdt_init(TWDT_TIMEOUT_S, false);//uint32_t timeout:TWDT计时溢出的周期,单位秒。
}
void loop() {
esp_task_wdt_reset();
vTaskDelay(pdMS_TO_TICKS(TASK_RESET_PERIOD_MS));//1000 ms 喂狗一次
// ToggleOutBlink(LED_D5,1000);
}
//implementation
void TonReceiver::OnRxdata(void) {
//Serial.println("Got Data on UART...");
while(1){
if(Serial.available()) // if there is data on the line
{
SerialErrCount=0;
comdata += char(Serial.read());// read string until we see a newline character
comdata.toUpperCase();
if(comdata == "ON")
{
comdata ="";
digitalWrite(LED_D4, HIGH);
Serial.println("I turned it ON!"); // Reply text to send to Serial Monitor
}
else
if(comdata == "OFF")
{
comdata ="";
digitalWrite(LED_D4, LOW);
Serial.println("I turned it OFF"); // Reply text to send to Serial Monitor
}
else {
vTaskDelay(1 / portTICK_PERIOD_MS);
if(comdata.length()>=34){
Serial.println(comdata+"\n"); // Reply text to send to Serial Monitor
//Serial.flush(); //等待串口发送完毕???
comdata ="";
while(Serial.read()>= 0){}//clear serialport
ToggleOutput(LED_D4);
}
}
}else break; // 收到事件后处理完毕自动跳出循环 测试 OK!
//vTaskDelay(1); //必须放一个以便响应其它人物的消息循环,否则将死锁。
}
}
void TonReceiver1::OnRxdata(void) {
//Serial1.println("Got Data on UART...");
while(1){
if(Serial1.available()) // if there is data on the line 是非阻塞的
{
Serial1ErrCount=0;
comdata1 += char(Serial1.read()); // read string until we see a newline character
comdata1.toUpperCase();
if(comdata1 == "ON")
{
//comdata1 ="";
digitalWrite(LED_D4, HIGH);
Serial1.println("I turned it ON!"); // Reply text to send to Serial Monitor
}
else
if(comdata1 == "OFF")
{
//comdata1 ="";
digitalWrite(LED_D4, LOW);
Serial1.println("I turned it OFF"); // Reply text to send to Serial Monitor
}
else {
vTaskDelay(1 / portTICK_PERIOD_MS);
if(comdata1.length()>=24){
Serial1.println(comdata1+"\n"); // Reply text to send to Serial Monitor
//Serial1.flush();//等待串口发送完毕???
comdata1 ="";
while(Serial1.read()>= 0){}//clear serialport
ToggleOutput(LED_D5);
}
}
}else break; //收到事件后处理完毕自动跳出循环 测试 OK!
//vTaskDelay(1); //必须放一个以便响应其它人物的消息循环,否则将死锁。
}
}
void TUartHWserial_error::OnReceiveErrorCbdata(hardwareSerial_error_t hwerr) {
while(1){
switch(hwerr) {
case UART_BREAK_ERROR:Serial.println("UART_BREAK_ERROR");
SerialErrCount++; //Serial1.eventQueueReset();
if(SerialErrCount>=MaxUartErrorCount)
esp_restart();
break;
case UART_BUFFER_FULL_ERROR:Serial.println("UART_BUFFER_FULL_ERROR");
SerialErrCount++; //Serial1.eventQueueReset();
if(SerialErrCount>=MaxUartErrorCount)
esp_restart();
break;
case UART_FIFO_OVF_ERROR:Serial.println("UART_FIFO_OVF_ERROR");
SerialErrCount++; //Serial1.eventQueueReset();
if(SerialErrCount>=MaxUartErrorCount)
esp_restart();
break;
case UART_FRAME_ERROR:Serial.println("UART_FRAME_ERROR");
SerialErrCount++; //Serial1.eventQueueReset();
if(SerialErrCount>=MaxUartErrorCount)
esp_restart();
break;
case UART_PARITY_ERROR:Serial.println("UART_PARITY_ERROR");
SerialErrCount++; //Serial1.eventQueueReset();
if(SerialErrCount>=MaxUartErrorCount)
esp_restart();
break;
default:vTaskDelay(1); //必须放一个以便响应其它人物的消息循环,否则将死锁。
break;
}
}
}
void TUartHWserial1_error::OnReceiveErrorCbdata(hardwareSerial_error_t hwerr) {
while(1){
switch(hwerr) {
case UART_BREAK_ERROR:Serial1.println("UART_BREAK_ERROR");
Serial1ErrCount++; //Serial1.eventQueueReset();
if(Serial1ErrCount>=MaxUartErrorCount)
esp_restart();
break;
case UART_BUFFER_FULL_ERROR: Serial1.println("UART_BUFFER_FULL_ERROR");
Serial1ErrCount++; //Serial1.eventQueueReset();
if(Serial1ErrCount>=MaxUartErrorCount)
esp_restart();
break;
case UART_FIFO_OVF_ERROR:Serial1.println("UART_FIFO_OVF_ERROR");
Serial1ErrCount++; //Serial1.eventQueueReset();
if(Serial1ErrCount>=MaxUartErrorCount)
esp_restart();
break;
case UART_FRAME_ERROR: Serial1.println("UART_FRAME_ERROR");
Serial1ErrCount++; //Serial1.eventQueueReset();
if(Serial1ErrCount>=MaxUartErrorCount)
esp_restart();
break;
case UART_PARITY_ERROR:Serial1.println("UART_PARITY_ERROR");
Serial1ErrCount++; //Serial1.eventQueueReset();
if(Serial1ErrCount>=MaxUartErrorCount)
esp_restart();
break;
default:vTaskDelay(1); //必须放一个以便响应其它人物的消息循环,否则将死锁。
break;
}
}
}