ESP32在Arduino环境下的串口数据帧接收
测试平台
ESP32-WROOM
测试语言
Arduino @ PlatformIO
注意事项
需要添加Queue的库函数 作者: SMFSW
PlatformIO环境配置文件 - platformio.ini
[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
monitor_speed = 115200
upload_speed = 921600
lib_deps = smfsw/Queue@^1.11
代码实现
- CPP主文件
/*
1. 使用串口中断接收串口数据;
2. 使用队列暂存串口接收的数据;
3. 对队列中的数据进行帧格式扫描,筛选完整数据帧。
4. 测试平台:ESP32-WROOM @ PlatformIO
5. 编程环境:Arduino
*/
// 需要添加Queue的库函数 author: SMFSW
//
#include <Arduino.h>
#include <Ticker.h>
#include <cppQueue.h>
#include "CRC16.h"
#define MAX_LENGTH 200 // queue FIFO length is set to 200
#define FRAME_LENGTH 50
#define HEADER_FRAME_LEN_LENGTH 3
#define FRAME_HEADER 0XAA
const uint8_t frame_Header[2] = {0XAA, 0XAA};
uint8_t frame_Recv_Dat[FRAME_LENGTH];
cppQueue Serialqueue(sizeof(uint8_t), MAX_LENGTH, FIFO, true);
void SerialRecvEvent();
void SerialRecvFrameEvent(cppQueue& uint8queue);
void LED_Blink();
void DetectFrame();
Ticker LEDTask;
Ticker SerialFrameDetection;
void setup() {
Serial.begin(115200);
Serial.setRxTimeout(1);
Serial.onReceive(SerialRecvEvent);
delay(5);
pinMode(2, OUTPUT);
digitalWrite(2, HIGH);
LEDTask.attach(1, LED_Blink);
SerialFrameDetection.attach_ms(2, DetectFrame);
}
void loop() {
delay(5);
}
void LED_Blink(){
digitalWrite(2,!digitalRead(2));
}
void SerialRecvEvent(){
if(Serial.available() > 0){
uint8_t len = Serial.available();
for(uint8_t i = 0; i < len; i++){
uint8_t recvbyte = Serial.read();
Serialqueue.push(&recvbyte);
}
}
}
void DetectFrame(){
SerialRecvFrameEvent(Serialqueue);
}
void SerialRecvFrameEvent(cppQueue& uint8queue){
uint8_t qbyte;
uint8_t temp_Recv_Dat[FRAME_LENGTH];
uint8_t crc16modbussum[2];
if(uint8queue.getCount() >= HEADER_FRAME_LEN_LENGTH){ // if queue records is longer than header length then read out
uint8_t header_chk_flag = false; // create header check flag
uint8_t CRC_16_chk_flag = false; // create crc16 check flag
uint8queue.pop(&qbyte); // pop one record
if(qbyte == FRAME_HEADER){ // check the pop record is header or not
uint8_t header2;
uint8queue.peekIdx(&header2, 0); //peek the next record in the queue
if(header2 == FRAME_HEADER){ // double bytes header checks pass
header_chk_flag = true;
uint8queue.pop(&header2);
// save headers to receive cache
temp_Recv_Dat[0] = qbyte;
temp_Recv_Dat[1] = header2;
uint8queue.pop((temp_Recv_Dat + 2)); // read out the frame length from queue
#ifdef DEBUG
Serial.println("frame len is: " + String(temp_Recv_Dat[2]));
#endif
// waiting the frame tail
//header and frame length byte is 3 bytes
uint8_t waitingcount = 0;
if((uint8queue.getCount() < (temp_Recv_Dat[2] - HEADER_FRAME_LEN_LENGTH))||(waitingcount < 5)){
delayMicroseconds(10);
waitingcount++;
#ifdef DEBUG
Serial.println("queue count left is: " + String(uint8queue.getCount()));
#endif
}
else{
header_chk_flag = false;
}
//read out the left part of this frame ,header and the frame length has been read out
for(uint8_t i = HEADER_FRAME_LEN_LENGTH; i < temp_Recv_Dat[2]; i++){
uint8queue.pop((temp_Recv_Dat + i));
}
//check CRC result
CRC_16_chk_flag = update_crc(crc16modbussum, temp_Recv_Dat, temp_Recv_Dat[2]);
#ifdef DEBUG
Serial.println("CRC_16_chk_flag: " + String(CRC_16_chk_flag));
Serial.print("0X" + String(crc16modbussum[0],HEX) + ",");
Serial.println("0X" + String(crc16modbussum[1],HEX));
//print out the received frame
for(uint8_t i = 0; i < temp_Recv_Dat[2]; i++){
Serial.print("0X" + String(temp_Recv_Dat[i], HEX) + ", ");
}
Serial.println();
#endif
}
else{
header_chk_flag = false;
}
}
else{
header_chk_flag = false;
}
if(CRC_16_chk_flag == true && header_chk_flag == true){
memcpy(frame_Recv_Dat, temp_Recv_Dat, temp_Recv_Dat[2]);
// #ifdef DEBUG
Serial.println("received data frame: ");
for(uint8_t i = 0; i < frame_Recv_Dat[2]; i++){
Serial.print("0X" + String(frame_Recv_Dat[i], HEX) + ", ");
}
Serial.println();
// #endif
}
}
}
- CRC16 校验CPP文件
/*standard CRC check cpp files*/
//CRC-16-modbus (LSB-MSB)
//calculation tools online:https://www.23bei.com/tool-59.html
//mode: CRC-16(Modbus)
// remodified at 20231221 suitable for queue data frame
#include "CRC16.h"
/*--------------------------------------------------------------------*/
/**
* function: Modbus CRC16(LSB-MSB) calculation
* update in 2022/03/17
* input paramenter:
* data_blk_ptr: inital address of waiting calculation data,
* usDataLen: length of data frame
* output parameter:
* crc_sum: CRC16-modbus results' inital address
* returned value:
* true: check pass
* false: check fail
*/
uint8_t update_crc(uint8_t* crc_sum, uint8_t *data_blk_ptr, uint8_t data_blk_size)
{
unsigned int i;
unsigned short crc = 0xFFFF;
unsigned short crcl;
uint8_t oriCRC16[2];
oriCRC16[0] = data_blk_ptr[data_blk_size - 2];
oriCRC16[1] = data_blk_ptr[data_blk_size - 1];
data_blk_size = data_blk_size - 2; // remove origin crc16 results addresss
while(data_blk_size--){
crc ^= *data_blk_ptr++;
for (i = 0; i < 8; ++i){
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
}
crcl = crc;
crc_sum[1] = (unsigned char)(crc>>8);
crc_sum[0] = (unsigned char)(crcl);
if((oriCRC16[0] == crc_sum[0]) &&((oriCRC16[1] == crc_sum[1])))
return true;
else
return false;
}
/*----------------------End of file----------------------------------*/
- CRC16 校验头文件
#ifndef _CRC_16_H_
#define _CRC_16_H_
#include <arduino.h>
// remodified at 20231221 suitable for queue data frame
uint8_t update_crc(uint8_t* crc_sum, uint8_t *data_blk_ptr, uint8_t data_blk_size);
#endif
标签:Arduino,data,ESP32,uint8,Dat,crc,串口,Recv,frame
From: https://www.cnblogs.com/Mech-Snake/p/17919745.html