ESP32-C3入门教程 基础篇(三、UART模块 — 与Enocean无线模块串口通信)

简介: 测试第三课,ESP32-C3的串口通信测试老样子,使用Enocean无线模块和ESP32-C3进行串口通信。
测试第三课,ESP32-C3的串口通信测试
老样子,使用Enocean无线模块和ESP32-C3进行串口通信

前言

接下来的ESP32-C3 功能测试都是基于自己设计的开发板:

自己画一块ESP32-C3 的开发板(第一次使用立创EDA)(PCB到手)

开发环境是乐鑫官方的 ESP-IDF, 基于VScode插件搭建好的:

ESP32-C3 VScode开发环境搭建(基于乐鑫官方ESP-IDF——Windows和Ubuntu双环境)

1、UART示例测试

在开发板上面,我们使用了串口0烧录,串口1连接 Enocean 无线通讯模块,所以我们使用UART1测试,引脚为GPIO4、GPIO5:
在这里插入图片描述
在做UART测试之前,还是先得看一下官方的介绍,因为UART的示例比较多:
在这里插入图片描述
通过官方的示例说明,我们选择带串口收发的例子uart_async_rxtxtasks
在这里插入图片描述

1.1 UART 基础测试

根据上面选择的官方的示例新建的工程,是有收也有发。

因为这里是基础测试,需要做的只是把程序中定义的两个引脚通过飞线短接起来,便可以观察到示例的现象:
在这里插入图片描述
在这里插入图片描述
然后工程直接编译烧录,就可以,效果如下:
在这里插入图片描述

1.2 与Enocean无线模块串口通信测试

上面的例子只是串口自己接受发送的简单示例,在实际应用中通常是和其他的传感器,模块进行通信,数据交互,那么这里我就使用自己常用的 Enocean 无线模块,来做一次测试,首先当然得对示例代码进行一定的修改。

在开发板上只需要把预留好的跳帽,连接好即可。

涉及到串口的使用,所以建议在看这个例子前面对 下面 ESP32-C3 UART 相关知识先了解一下。

先测试接收,把发送任务去掉,接收函数稍微修改一下:
在这里插入图片描述
测试结果如下:
(一个无线开关的报文 21 bytes,预留的读取时间为 6ms ,即便这样,也可能在 6ms 内读取到了2个开关的报文,但是不会有错误,这个后期在数据处理的时候需要注意一下)
在这里插入图片描述
然后继续测试一下给 无线模块发送消息,对发送任务稍作修改:
在这里插入图片描述

接收函数不变,测试结果如下:
在这里插入图片描述

最后还是简单写一个解析函数,测试目的,就没有管代码规范了,就是上电把 ID 读出来,先来看一下效果,下面再放一下测试代码:
在这里插入图片描述
上述示例把 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结构体可以统一设置:

在这里插入图片描述
例如示例中:
在这里插入图片描述
当然,出了使用结构体设置串口的参数,也可以使用函数单独对某一个参数进行设置:
在这里插入图片描述

  1. 设置收发引脚,使用uart_set_pin函数设置:

在这里插入图片描述
后两个参数是硬件流控,如果不需要,则可以设置为UART_PIN_NO_CHANGE,例如示例中:
在这里插入图片描述

  1. 设置串口,使用uart_driver_install函数进行 install: 在这里插入图片描述参数分别为:串口号,接收缓冲区,发送缓冲区,队列长度(消息长度),中断回调函数(没有写NULL),中断标志位。

在示例中使用:
在这里插入图片描述

  1. 完成前面3步就完成了UART的基本配置,接下来就可以进行收发了,

使用uart write bytes()Tx FIFO buffer里面写数据,就可以发送数据;
在这里插入图片描述
使用uart read bytes()Rx FIFO buffer里读数据,就是接收数据;
在这里插入图片描述
其他的工作由 FSM(UART controller’s finite state machine)完成 。

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

在这里插入图片描述
在上面的例子中,我们只测试了基本的收发,好像没有使用到和中断相关的函数。这个后期如果有需要再来更新。

对于 ESP32-C3 UART 其他的一些功能,比如 485 接口发送等,具体在官方文档有详细的说明,我们在需要使用的时候可以先看文档,然后找到对应的例程,进行更改,和本博文的收发示例一样,学习一定得多动手尝试。

相关文章
|
消息中间件 Ubuntu 测试技术
ESP32-C3入门教程 基础篇(二、GPIO中断、按键驱动测试)
测试第二课,主要了解GPIO中断使用,和测试按键驱动
2098 0
ESP32-C3入门教程 基础篇(二、GPIO中断、按键驱动测试)
|
传感器 编解码 Ubuntu
ESP32-C3入门教程 基础篇(七、LEDC — LED PWM 控制器)
测试第7课,补一补基本的PWM控制器的测试。 说明一下,ESP32-C3没有MCPWM硬件,所以测试只有LEDPWM, 如果想用ESP32-C3控制电机,可以考虑使用 RMT,后期有机会测试一下。
1740 0
ESP32-C3入门教程 基础篇(七、LEDC — LED PWM 控制器)
|
算法 Ubuntu 物联网
ESP32-C3入门教程 网络 篇(二、 Wi-Fi 配网 — Smart_config方式 和 BlueIF方式)
经过上一篇的WiFI入门篇,我们知道了WiFi初始化方式 和学会了WiFi的几种工作方式, 在实际应用中,环境复杂多变,在固件中输入SSID 的方式太不通用了, 所以肯定是需要学习一下如何在不同的环境中联网,就是所谓的配网。 ESP32-C3的配网方式有多种,本文主要说明测试 Smart方式 和 BlueIF方式。
3782 0
ESP32-C3入门教程 网络 篇(二、 Wi-Fi 配网 — Smart_config方式 和 BlueIF方式)
|
传感器 Ubuntu 物联网
ESP32-C3 学习测试 蓝牙 篇(一、认识 ESP-IDF 的蓝牙框架、简单的了解蓝牙协议栈)
在我们前面 ESP32-C3 的教程中,从基本的外设,到wifi,到最后使用MQTT连接云平台完成了一个 简单的项目,我们已经掌握了ESP32-C3 的大部分功能了。 但是作为一款蓝牙芯片,蓝牙的使用是必不可少的,今天我们就开始对 ESP32-C3 蓝牙的使用进行学习测试。 蓝牙部分已经不敢叫教学了,为了搞清楚ESP-IDF的那些示例程序到底是关于什么内容, 因为自己也是边学习边测试花了大量时间补充蓝牙的基本知识,希望小伙伴指出不足之处! ...更新说明,ESP32-C3只支持BLE
5111 2
ESP32-C3 学习测试 蓝牙 篇(一、认识 ESP-IDF 的蓝牙框架、简单的了解蓝牙协议栈)
|
消息中间件 传感器 Ubuntu
ESP32-C3入门教程 基础篇(六、TIMG 硬件定时器 与 软件定时器)
到了测试第6课,还没有玩过ESP32-C3的基本定时器,虽然FreeRTOS,可以使用软件定时器 但是软件定时器毕竟也有不适用的时候,这个在我FreeRTOS博文中有单独说明。 所以硬件定时器也得熟悉,同时附带简单用一下软件定时器。
1460 0
ESP32-C3入门教程 基础篇(六、TIMG 硬件定时器 与 软件定时器)
|
传感器 缓存 Ubuntu
ESP32-C3入门教程 基础篇(四、I2C总线 — 与SHT21温湿度传感器通讯)
测试第四课,了解ESP32-C3的 I2C 总线使用,与SHT21 温湿度传感器通讯 这一课把基础介绍放在前面,先看基本流程,再去修改代码
1569 0
ESP32-C3入门教程 基础篇(四、I2C总线 — 与SHT21温湿度传感器通讯)
|
传感器 算法 测试技术
ESP32-C3 应用 篇(实例一、通过MQTT协议连接ONENET上报传感器数据,云平台下发灯光调色)
ESP32-C3学到现在,我们已经掌握了从基本外设到网络服务端的相关知识, 这篇文章就是做一个简单的应用,使用开发板连接ONENET云平台, 使用MQTT协议,上报温湿度和光照数据,平台下发命令控制全彩灯颜色切换。
2322 0
ESP32-C3 应用 篇(实例一、通过MQTT协议连接ONENET上报传感器数据,云平台下发灯光调色)
|
IDE Shell 开发工具
【树莓派 Pico 基于MicroPython编程Thonny开发】
【树莓派 Pico 基于MicroPython编程Thonny开发】
1326 0
|
监控 IDE 开发工具
【esp32c3配置arduino IDE教程】
设计用户操作界面,该设备具备简单易用的操作界面,外加显示屏SSD1306和旋转编码器进行显示和控制,用户后期可进行二次开发WiFi或蓝牙连接电脑或手机监控。
4696 0
|
传感器 Ubuntu API
ESP-IDF 蓝牙开发 之GATT 数据通信 — 发送自定义数据
本来计划直接做一个蓝牙的小应用,首先得实现一下自己想要数据的传输,虽然我们前面已经测试过示例的读写了,但是还是发现一些问题,如何传输自己想要的数据呢?
2099 0
ESP-IDF 蓝牙开发 之GATT 数据通信 — 发送自定义数据

热门文章

最新文章