Esp32 C3 Arduino 串口开发(4)-类函数回调

直接使用 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;                   
    }
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值