本文源码地址为: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通讯的更多相关文章

  1. 基于esp32的IIC通讯

    本文源码地址在:http://download.csdn.net/download/noticeable/9962029 IIC 通讯应该是当代比较常用的几种通讯方式之一,其无需特殊的IO接口,连线方 ...

  2. [IOT] 自制蓝牙工牌办公室定位系统 (二)—— 基于ESP32的蓝牙信号扫描系统

      前面章节: 自制蓝牙工牌办公室定位系统 (一)-- 阿里物联网平台概览及打通端到云(硬核·干货)   目录: 1.蓝牙广播简介 2.蓝牙扫描简介 3.基于蓝牙广播和蓝牙扫描常见应用 4.ESP32 ...

  3. .Net开发笔记(十五) 基于“泵”的TCP通讯(接上篇)

    上一篇博客中说了基于“泵”的UDP通讯,附上了一个Demo,模拟飞鸽传书的功能,功能不太完善,主要是为了说明“泵”在编程中的应用.本篇文章我再附上一个关于TCP通讯的两个Demo,也都采用了“泵”模式 ...

  4. Android基于XMPP的即时通讯3-表情发送

    这篇博文主要讲表情发送的一些东西. 参考:Android基于XMPP的即时通讯1-基本对话 1.准备好资源文件 采用的是emoji的表情,我打包好了,下载地址:http://files.cnblogs ...

  5. Android基于XMPP的即时通讯2-文件传输

    本文是在上一篇博文Android基于XMPP的即时通讯1-基本对话的基础上,添加新的功能,文件传输 1.初始化文件传输管理类 public static FileTransferManager get ...

  6. 基于“泵”的TCP通讯(接上篇)

    基于“泵”的TCP通讯(接上篇) 上一篇博客中说了基于“泵”的UDP通讯,附上了一个Demo,模拟飞鸽传书的功能,功能不太完善,主要是为了说明“泵”在编程中的应用.本篇文章我再附上一个关于TCP通讯的 ...

  7. (二): 基于ZeroMQ的实时通讯平台

    基于ZeroMQ的实时通讯平台 上篇:C++分布式实时应用框架 (Cpp Distributed Real-time Application Framework)----(一):整体介绍 通讯平台作为 ...

  8. uart通讯协议

    本次设计的源码在http://download.csdn.net/detail/noticeable/9912383 下载 实验目的:通过uart通讯协议的编写,了解FPGA的通讯协议编写的方法. 实 ...

  9. 基于ZYNQ 的UART中断实验之串口写数据到DDR3中

    1.参考 UG585 网络笔记 2.理论知识 参见上一次实验:基于ZYNQ 的UART中断实验 3.实验目的 练习使用UART的中断实验,并将接收到的数据写入到DDR3中. 4.实验过程 建立工程,设 ...

随机推荐

  1. android 开发 View _14 MotionEvent和事件处理详解,与实践自定义滑动条View

    转载https://blog.csdn.net/huaxun66/article/details/52352469 MotionEvent MotionEvent对象是与用户触摸相关的时间序列,该序列 ...

  2. OpenStack Trove组件WSGI和RPC调用流程(参考调用的整个过程)

    参考博文:https://blog.csdn.net/bill_xiang_/article/details/72909927

  3. HDFS 常用命令行:

    1. 查看各库的存储大小 hdfs dfs -du -h /user/hive/warehouse 2. 删除HDFS 文件 hdfs dfs -rmr 绝对路径名 例如:hdfs dfs -rmr ...

  4. 01 Python初识

    基础: 1.后缀名是py       ATT: 单个文件执行,后缀无所谓 2.两种执行方式 终端 python+文件路径 解释器内部: 直接执行 3.解释器路径: #/usr/bin/env pyth ...

  5. PHPsocket、CURL、File_get_contents采集

    1.socket采集.采用最底层的,它只是建立一个长连接,然后我们自己构造http协议字符串去发送请求.例如想获取这个页面内容(http://tv.youku.com/?spm=a2hww.20023 ...

  6. git 提交小备注

    总结: ·  git add -A  提交所有变化 ·  git add -u  提交被修改(modified)和被删除(deleted)文件,不包括新文件(new) ·  git add .  提交 ...

  7. 记一个jquery 无缝轮播的制作方法

    接触前端也很久了,今天才发现,要做好一个轮播,其实有很多东西需要考虑进去,否则做出来的轮播效果并不好,下面我就来做一个轮播,是依赖jquery来写的 1.要做轮播,首先需要的是HTML的内容,css的 ...

  8. ReactiveX 学习笔记(21)使用 Rx.NET + ReactiveUI 进行 GUI 编程

    课题 程序界面由3个文本编辑框和1个文本标签组成. 要求文本标签实时显示3个文本编辑框所输入的数字之和. 文本编辑框输入的不是合法数字时,将其值视为0. 3个文本编辑框的初值分别为1,2,3. 创建工 ...

  9. TXLSReadWriteII2 读取数据

    TXLSReadWriteII2 按行读取数据(写得复杂了点,实际项目中的,可以自己简化) procedure TformMain.LoadGeneralObject(_type, _col, _ro ...

  10. 自定义模块和grains

    一.自定义模块 saltstack有很多模块,模块的源码文件是在salt项目的:salt/modules.py; salt linux-node2-computer sys.doc   查看有哪些mo ...