最后还是简单写一个解析函数,测试目的,就没有管代码规范了,就是上电把 ID 读出来,先来看一下效果,下面再放一下测试代码:

ESP32 arduino UDP 串口 esp32串口2_#include


上述示例把 Enocean 模块的ID 读取出来,做到这一步,基本上 ESP32 -C3 和 Enocean 的通信没什么大问题了,如果需要想 在 STM32上面那样有完整的驱动,还是得一点一点的打磨移植一下,后续应该会有机会使用 ESP32 -C3 做些项目,到时候会花时间完善一下驱动。

下面把最后测试的示例代码放上(代码是以测试为目的,没有把读取ID的部分代码写成函数,有点不太规范):

/\* UART asynchronous example, that uses separate RX and TX tasks

 This example code is in the Public Domain (or CC0 licensed, at your option.)

 Unless required by applicable law or agreed to in writing, this
 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 CONDITIONS OF ANY KIND, either express or implied.
\*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp\_system.h"
#include "esp\_log.h"
#include "driver/uart.h"
#include "string.h"
#include "driver/gpio.h"
#include "Datadef.h"

#define proccrc8(u8CRC, u8Data) (u8CRC8Table[u8CRC^u8Data])

const uint8 u8CRC8Table[256] = { 
							0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 
							0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 
							0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 
							0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 
							0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 
							0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 
							0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 
							0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 
							0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 
							0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 
							0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 
							0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, 
							0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 
							0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 
							0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 
							0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 
							0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 
							0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 
							0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 
							0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, 
							0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 
							0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 
							0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 
							0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, 
							0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 
							0x76, 0x71, 0x78, 0x7f, 0x6A, 0x6d, 0x64, 0x63, 
							0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 
							0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 
							0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 
							0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8D, 0x84, 0x83, 
							0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 
							0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 
						};

static const int RX_BUF_SIZE = 200;
static const uint8\_t CO_RD_VERSION[] = {0x55,0x00,0x01,0x00,0x05,0x70,0x03,0x09};
static STATES_GET_PACKET  u8state = GET_SYNC_STATE;
u32 u32MyId = 0;
uint8 Read_pt = 0;
// uint8\_t data[RX\_BUF\_SIZE] = {0};
// uint8\_t Enocean\_Data = 0; //数据长度记录 
// uint8\_t EnoceanState; //接收完成标志

#define TXD\_PIN (GPIO\_NUM\_4)
#define RXD\_PIN (GPIO\_NUM\_5)

void init(void) {
    const uart\_config\_t uart_config = {
        .baud_rate = 57600,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    // We won't use a buffer for sending data.
    uart\_driver\_install(UART_NUM_1, RX_BUF_SIZE \* 2, 0, 0, NULL, 0);
    uart\_param\_config(UART_NUM_1, &uart_config);
    uart\_set\_pin(UART_NUM_1, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}


// int sendData(const char\* logName, const char\* data)
// {
// const int len = strlen(data);
// const int txBytes = uart\_write\_bytes(UART\_NUM\_1, data, len);
// // ESP\_LOGI(logName, "Wrote %d bytes", txBytes);
// return txBytes;
// }

static void tx\_task(void \*arg)
{
    // static const char \*TX\_TASK\_TAG = "TX\_TASK";
    // esp\_log\_level\_set(TX\_TASK\_TAG, ESP\_LOG\_INFO);
    while (1) {
        printf("get my ID when poweron!\r\n");
        // sendData(TX\_TASK\_TAG, "Hello world");
        uart\_write\_bytes(UART_NUM_1, CO_RD_VERSION, sizeof(CO_RD_VERSION));
        // vTaskDelay(2000 / portTICK\_PERIOD\_MS);
        vTaskDelete(NULL);
    }
}

static void rx\_task(void \*arg)
{
    RETURN_TYPE ReturnCode = 0;
    static uint8 u8Count = 0;
    
    uint8 u8CRC = 0;
	// uint8 ERROR\_FLAG = 0;
	uint32 CHIP_ID = 0;

    static const char \*RX_TASK_TAG = "RX\_TASK";
    esp\_log\_level\_set(RX_TASK_TAG, ESP_LOG_INFO);
    uint8\_t\* data = (uint8\_t\*) malloc(RX_BUF_SIZE+1);
    
    while (1) {
        const int rxBytes = uart\_read\_bytes(UART_NUM_1, data, RX_BUF_SIZE, 6 / portTICK_RATE_MS);
        if (rxBytes > 0) { //rxBytes是 uart\_read\_bytes 返回的长度数据, 
            data[rxBytes] = 0; //推测读取的时候使用的是 rxBytes ++ ,所以这最后一个数据是数据后面一个不需要的,所以赋值0
            // ESP\_LOGI(RX\_TASK\_TAG, "Read %d bytes: '%s'", rxBytes, data);
            ESP\_LOGI(RX_TASK_TAG, "Read %d bytes", rxBytes);
            // printf("%x %x %x %x %x %x %x %x %x\r\n",data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8]);
            if((rxBytes >= 38)&&(u32MyId == 0)){
                while(Read_pt != rxBytes){
                    switch(u8state){
				    case GET_SYNC_STATE:               // Waiting for packet sync byte 0x55
                        if (data[Read_pt++] == ESP3_SYNC_CODE){	                          					
                            u8state = GET_HEADER_STATE;
                            u8Count = 0;
                            u8CRC = 0; 
                        }
                        // printf("111\r\n"); 
					break;
       			    case GET_HEADER_STATE:              // Read the header bytes
                        u8CRC = proccrc8(u8CRC,data[Read_pt++]);
                        u8Count++;
                        // printf("222\r\n"); 
                        if(u8Count == ESP3_Header_Bytes){
                            u8state = CHECK_CRC8H_STATE;
                            u8Count = 0;
                        }
					break;
				    case CHECK_CRC8H_STATE:                        
                        if(u8CRC == data[Read_pt++]){
                            u8state = GET_DATA_STATE;
                            ReturnCode = Enocean_OK;
                        }
                        // printf("333\r\n"); 
                        // else
                        // ERROR\_FLAG = 1;
					break;
				    case GET_DATA_STATE:
                        if(ReturnCode == Enocean_OK){
                            Read_pt = 15;                       //ID Info start from the 10th data of the data filed
                            
                            for(u8Count=0;u8Count<4;u8Count++)
                            {
                                CHIP_ID <<= 8;
                                CHIP_ID |= data[Read_pt++];
                            }
                            u32MyId = CHIP_ID;
                            Read_pt = 0;
	                        u8state = GET_SYNC_STATE;
                        }
                        // else
                        // ERROR\_FLAG = 1;
					break;
				    default:break;
		            } 
                    if(u8state == GET_SYNC_STATE)break;//跳出while循环 
                }
            }
            ESP\_LOG\_BUFFER\_HEXDUMP(RX_TASK_TAG, data, rxBytes, ESP_LOG_INFO);
            printf("my ID is :0x %x\r\n",u32MyId);
        }
        vTaskDelay(1);//不加延时不会释放CPU使用权,会导致错误,其他任务的看门口报错
    }
    free(data);  
}

void app\_main(void)
{
    init();
    xTaskCreate(rx_task, "uart\_rx\_task", 1024\*2, NULL, configMAX_PRIORITIES, NULL);
    xTaskCreate(tx_task, "uart\_tx\_task", 1024\*2, NULL, configMAX_PRIORITIES-1, NULL);
}

2、ESP32-C3 UART 基础知识说明

对于ESP32-C3 UART的介绍,同样在乐鑫的官网有很详细的说明,官方链接如下:

乐鑫官方ESP32-C3 UART部分说明

根据官方文档,ESP32-C3 UART使用步骤:

  1. 设置参数,使用uart_config_t结构体可以统一设置:

    例如示例中:

    当然,出了使用结构体设置串口的参数,也可以使用函数单独对某一个参数进行设置:
  2. 设置收发引脚,使用uart_set_pin函数设置:

    后两个参数是硬件流控,如果不需要,则可以设置为UART_PIN_NO_CHANGE,例如示例中:
  3. 设置串口,使用uart_driver_install函数进行 install: 参数分别为:串口号,接收缓冲区,发送缓冲区,队列长度(消息长度),中断回调函数(没有写NULL),中断标志位。
    在示例中使用:
  4. 完成前面3步就完成了UART的基本配置,接下来就可以进行收发了,
    使用uart write bytes()Tx FIFO buffer里面写数据,就可以发送数据;

    使用uart read bytes()Rx FIFO buffer里读数据,就是接收数据;

    其他的工作由 FSM(UART controller’s finite state machine)完成 。

具体的使用可以查看手册上面Running UART Communication章节。