基于ESP32的uart通讯
本文源码地址为:http://download.csdn.net/download/noticeable/9961054
ESP32上有三个UART通讯接口,设备号,从0~2,即UART0,UART1,UART2。支持异步通讯,ESP32开发板上micro USB 连接的即使UART0接口,通常使用该串口作为日志输出,用于调试,另外两个串口作为工作串口,可用来输出和接收数据。
对于uart通讯,主要可以分为以下几个部分:
PART1:
定义引脚
#ifndef size_t
#define size_t unsigned int
#endif
#define BUF_SIZE (1024)
#define ECHO_TEST_TXD (4)
#define ECHO_TEST_RXD (5)
#define ECHO_TEST_RTS (18)
#define ECHO_TEST_CTS (19)
9 QueueHandle_t uart0_queue;
定义引脚,这里TXD、RXD是串口输出通常用到数据写出和读入的引脚,关于RTS和CTS引脚 (注意:由于UART0已经的引脚配置已经固定默认在BootLoader中了,不能更改,所以不能配置引脚也无需定义)
RTS(Request To Send 请求发送):用于传输PC机发往串口Modem等设备的信号,该信号表示PC机是否允许Modem发数据。
CTS:Clear to send,在计算机UART引脚中定义表示为允许发送。
在与计算机通讯过程中常与RTS( request to send, 请求发送信号 )一起被提到,是UART通讯过程中flow control的两个引脚,是成对出现的。
下面说一下这两个引脚的作用;
(1) 隐藏终端问题被减轻了,因为长data帧只有在信道预约后才能被发送;
(2)因为rts帧和cts帧较短,涉及rts帧和cts帧的碰撞将仅持续很短的rts帧或cts帧持续期。一旦rts帧和cts帧被正确传输,后续的data帧和ack帧应当能无碰撞的发送。
PART2:编写uart处理任务
void uart_task(void *pvParameters)
{
int uart_num = (int) pvParameters;
uart_event_t event;
size_t buffered_size;
uint8_t* dtmp = (uint8_t*) malloc(BUF_SIZE);
for(;;) {
//Waiting for UART event.
if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
ESP_LOGI(TAG, "uart[%d] event:", uart_num);
switch(event.type) {
//Event of UART receving data
/*We'd better handler data event fast, there would be much more data events than
other types of events. If we take too much time on data event, the queue might
be full.
in this example, we don't process data in event, but read data outside.*/
case UART_DATA:
uart_get_buffered_data_len(uart_num, &buffered_size);
ESP_LOGI(TAG, "data, len: %d; buffered len: %d", event.size, buffered_size);
break;
//Event of HW FIFO overflow detected
case UART_FIFO_OVF:
ESP_LOGI(TAG, "hw fifo overflow\n");
//If fifo overflow happened, you should consider adding flow control for your application.
//We can read data out out the buffer, or directly flush the rx buffer.
uart_flush(uart_num);
break;
//Event of UART ring buffer full
case UART_BUFFER_FULL:
ESP_LOGI(TAG, "ring buffer full\n");
//If buffer full happened, you should consider encreasing your buffer size
//We can read data out out the buffer, or directly flush the rx buffer.
uart_flush(uart_num);
break;
//Event of UART RX break detected
case UART_BREAK:
ESP_LOGI(TAG, "uart rx break\n");
break;
//Event of UART parity check error
case UART_PARITY_ERR:
ESP_LOGI(TAG, "uart parity error\n");
break;
//Event of UART frame error
case UART_FRAME_ERR:
ESP_LOGI(TAG, "uart frame error\n");
break;
//UART_PATTERN_DET
case UART_PATTERN_DET:
ESP_LOGI(TAG, "uart pattern detected\n");
break;
//Others
default:
ESP_LOGI(TAG, "uart event type: %d\n", event.type);
break;
}
}
}
free(dtmp);
dtmp = NULL;
vTaskDelete(NULL);
}
uart_task任务的作用为对接收到的数据进行处理,并将结果通过日志的形式打印到串口调试助手上,最后在任务结束时,将处理任务删除掉。
PART3:
编写uart0 配置函数
void uart_evt_test()
{
int uart_num = UART_NUM_0;
uart_config_t uart_config = {
.baud_rate = ,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.rx_flow_ctrl_thresh = ,
};
//Set UART parameters
uart_param_config(uart_num, &uart_config);
//Set UART log level
esp_log_level_set(TAG, ESP_LOG_INFO);
//Install UART driver, and get the queue.
uart_driver_install(uart_num, BUF_SIZE * , BUF_SIZE * , , &uart0_queue, );
//Set UART pins,(-1: default pin, no change.)
//For UART0, we can just use the default pins.
//uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
//Set uart pattern detect function.
uart_enable_pattern_det_intr(uart_num, '+', , , , );
//Create a task to handler UART event from ISR
xTaskCreate(uart_task, "uart_task", , (void*)uart_num, , NULL);
//process data
uint8_t* data = (uint8_t*) malloc(BUF_SIZE);
do {
int len = uart_read_bytes(uart_num, data, BUF_SIZE, / portTICK_RATE_MS);
if(len > ) {
ESP_LOGI(TAG, "uart read : %d", len);
uart_write_bytes(uart_num, (const char*)data, len);
}
} while();
}
uart_event_test函数,用来对uart进行配置其中
uart_num 设置UART外设号码,可选位UART_NUM_0、UART_NUM_1、UART_NUM_2
baud_rate 设置波特率 可选为:
data_bits 设置数据位宽
parity 是否校验 UART_PARITY_DISABLE禁用UART奇偶校验,UART_PARITY_EVEN启用UART偶校验,UART_PARITY_ODD启用UART奇校验
stop_bits 停止位位数
flow_ctrl UART硬件流控制模式 UART_HW_FLOWCTRL_DISABLE 禁用硬件流控制,UART_HW_FLOWCTRL_RTS启用RX硬件流控制(rts),UART_HW_FLOWCTRL_CTS启用TX硬件流控制,UART_HW_FLOWCTRL_CTS_RTS 启用硬件流控制。
rx_flow_ctrl_thresh 硬件流控制的阈值。
最后调用 uart_param_config(uart_num, &uart_config);对uart参数进行设定
esp_log_level_set(TAG, ESP_LOG_INFO);对esp32的输出日志设置级别,这里将uart example设置为正常的流和事件作为日志输出。
uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 10, &uart0_queue, 0);安装UART驱动程序。UART ISR处理程序将附加到该功能正在运行的同一CPU内核。
uart_enable_pattern_det_intr(uart_num, '+', 3, 10000, 10, 10); UART使能模式检测功能。专为“AT命令”等应用程序而设计。当硬件检测到一系列相同的字符时,中断将被触发。
xTaskCreate(uart_task, "uart_task", 2048, (void*)uart_num, 12, NULL); 调用uart_task 任务,对接收到的数据相关的长度等信息进行打印。
其后的任务即为处理接收到的数据,并将数据打印出来,并等待。
函数的作用是配置了uart0的工作模式,并通过声明了的uart0_queue消息队列接收信息,并在调用uart_driver_install注册串口时将消息队列传递到层,当有串口消息来时,串口消息队列会发送消息到该消息队列,然后通过uart_task接收串口数据,如果检测到入伍中有消息队列则读串口。
可以看出,uart0的通讯方式是有消息来了才接收,所以其为异步通讯方式。
PART4:
编写uart1配置函数
void uart_echo_test()
{
int uart_num = UART_NUM_1;
uart_config_t uart_config = {
.baud_rate = ,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
.rx_flow_ctrl_thresh = ,
};
//Configure UART1 parameters
uart_param_config(uart_num, &uart_config);
//Set UART1 pins(TX: IO4, RX: I05, RTS: IO18, CTS: IO19)
uart_set_pin(uart_num, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS);
//Install UART driver( We don't need an event queue here)
//In this example we don't even use a buffer for sending data.
uart_driver_install(uart_num, BUF_SIZE * , , , NULL, ); uint8_t* data = (uint8_t*) malloc(BUF_SIZE);
while() {
//Read data from UART
int len = uart_read_bytes(uart_num, data, BUF_SIZE, / portTICK_RATE_MS);
//Write data back to UART
uart_write_bytes(uart_num, (const char*) data, len);
}
}
对于uart1,其大致过程与uart0函数是相似的,但是不同点在与其通讯模式与uart0是不同的,第9行可以看出它是通过硬件流进行通讯的。
PART5:
app_main函数
void app_main()
{
//A uart read/write example without event queue;
xTaskCreate(uart_echo_test, "uart_echo_test", , NULL, , NULL); //A uart example with event queue.
uart_evt_test();
}
通过app_main对两个函数进行调用。
实验现象:
由于本人手上没有硬件流相关的串口调试器,所以对于uart1的验证无法进行了,这里只对uart0的结果进行实验。
打开串口调试助手,连接esp32(通过usb直接连接即可),发送数据,可以得到如下结果。说明串口数据发送成功。

相关知识:UART相关API接口
基于ESP32的uart通讯的更多相关文章
- 基于esp32的IIC通讯
本文源码地址在:http://download.csdn.net/download/noticeable/9962029 IIC 通讯应该是当代比较常用的几种通讯方式之一,其无需特殊的IO接口,连线方 ...
- [IOT] 自制蓝牙工牌办公室定位系统 (二)—— 基于ESP32的蓝牙信号扫描系统
前面章节: 自制蓝牙工牌办公室定位系统 (一)-- 阿里物联网平台概览及打通端到云(硬核·干货) 目录: 1.蓝牙广播简介 2.蓝牙扫描简介 3.基于蓝牙广播和蓝牙扫描常见应用 4.ESP32 ...
- .Net开发笔记(十五) 基于“泵”的TCP通讯(接上篇)
上一篇博客中说了基于“泵”的UDP通讯,附上了一个Demo,模拟飞鸽传书的功能,功能不太完善,主要是为了说明“泵”在编程中的应用.本篇文章我再附上一个关于TCP通讯的两个Demo,也都采用了“泵”模式 ...
- Android基于XMPP的即时通讯3-表情发送
这篇博文主要讲表情发送的一些东西. 参考:Android基于XMPP的即时通讯1-基本对话 1.准备好资源文件 采用的是emoji的表情,我打包好了,下载地址:http://files.cnblogs ...
- Android基于XMPP的即时通讯2-文件传输
本文是在上一篇博文Android基于XMPP的即时通讯1-基本对话的基础上,添加新的功能,文件传输 1.初始化文件传输管理类 public static FileTransferManager get ...
- 基于“泵”的TCP通讯(接上篇)
基于“泵”的TCP通讯(接上篇) 上一篇博客中说了基于“泵”的UDP通讯,附上了一个Demo,模拟飞鸽传书的功能,功能不太完善,主要是为了说明“泵”在编程中的应用.本篇文章我再附上一个关于TCP通讯的 ...
- (二): 基于ZeroMQ的实时通讯平台
基于ZeroMQ的实时通讯平台 上篇:C++分布式实时应用框架 (Cpp Distributed Real-time Application Framework)----(一):整体介绍 通讯平台作为 ...
- uart通讯协议
本次设计的源码在http://download.csdn.net/detail/noticeable/9912383 下载 实验目的:通过uart通讯协议的编写,了解FPGA的通讯协议编写的方法. 实 ...
- 基于ZYNQ 的UART中断实验之串口写数据到DDR3中
1.参考 UG585 网络笔记 2.理论知识 参见上一次实验:基于ZYNQ 的UART中断实验 3.实验目的 练习使用UART的中断实验,并将接收到的数据写入到DDR3中. 4.实验过程 建立工程,设 ...
随机推荐
- 【Linux】【Jenkins】配置过程中,立即构建时,maven找不到的问题解决方案
在Linux环境下配置Jenkins执行时,发现不能执行Maven,这个比较搞了. A Maven installation needs to be available for this projec ...
- (14)其他Linux命令
*****拷贝文件cp somefile.1 /home/hadoop/ 以原文件名进行拷贝 cp somefile.1 /home/hadoop/somefile.2 以新文件名进行 ...
- json初接触
<html lang="en"> <head> <meta charset="UTF-8"> <meta name=& ...
- E0264 Unable to execute '"/usr/bin/codesign" ...'
E0264 Unable to execute '"/usr/bin/codesign" ...' http://docwiki.embarcadero.com/RADStudio ...
- 第四篇、Python文件处理
1.文件操作 1) 文件操作流程 a. 打开文件,得到文件句柄并赋值给一个变量 b. 通过句柄对文件进行操作 c. 关闭文件 f=open('a.txt','r',encoding='utf-8') ...
- linux check
建议安装chkrootkit.rkhunter.Lynis.ISPProtect这类安全工具,定期做扫描
- Kb和KB的区别
- Python设计模式 - UML - 包图(Package Diagram)
简介 包图是对各个包及包之间关系的描述,展现系统中模块与模块之间的依赖关系.一个包图可以由任何一种UML图组成,可容纳的元素有类.接口.组件.用例和其他包等.包是UML中非常常用的元素,主要作用是分类 ...
- python爬虫小说代码,可用的
python爬虫小说代码,可用的,以笔趣阁为例子,python3.6以上,可用 作者的QQ:342290433,汉唐自远工程师 import requests import refrom lxml i ...
- CentOS 特殊变量($0、$1、$2、 $?、 $# 、$@、 $*)
名称 说明 $0 脚本名称 $1-9 脚本执行时的参数1到参数9 $? 脚本的返回值 $# 脚本执行时,输入的参数的个数 $@ 输入的参数的具体内容(将输入的参数作为一个多个对象,即是所有参数的一个列 ...