当前位置: 首页 > news >正文

【ESP32 idf Uart串口通信】

目录

  • ESP32 的 UART
    • 简介
    • 配置步骤
    • 配置
      • 配置通信
      • 配置引脚
      • 安装驱动程序
      • 发送数据
      • 接收数据
  • 整体代码测试

ESP32 的 UART

简介

通用异步接收器/发送器 (UART) 属于一种硬件功能,通过使用 RS232、RS422、RS485 等常见异步串行通信接口来处理通信时序要求和数据帧。UART 是实现不同设备之间全双工或半双工数据交换的一种常用且经济的方式。

ESP32 芯片有 3 个 UART 控制器(也称为端口),每个控制器都有一组相同的寄存器以简化编程并提高灵活性。

每个 UART 控制器可以独立配置波特率、数据位长度、位顺序、停止位位数、奇偶校验位等参数。所有具备完整功能的 UART 控制器都能与不同制造商的 UART 设备兼容,并且支持红外数据协会 (IrDA) 定义的标准协议。

配置步骤

在这里插入图片描述
在这里插入图片描述

配置

配置通信

首先先配置通信的参数。

有两种配置方法,一种是一次性全部配完,另一种是分开一个个配置。

我们先看一次性配置。
首先引入头文件#include <driver/uart.h>
在这里插入图片描述

typedef struct {int 				  baud_rate;      //波特率uart_word_length_t    data_bits;      //数据位uart_parity_t 		  parity;         //奇偶校验方式uart_stop_bits_t 	  stop_bits;      //停止位数uart_hw_flowcontrol_t flow_ctrl;    //硬件流控方式uint8_t 			  rx_flow_ctrl_thresh;        //硬件流控阈值union {uart_sclk_t 	source_clk;     //时钟源//deprecated vt. 强烈反对, 抨击; 对...表示不赞成;//下面带有__attribute__((deprecated))的use_ref_tick意味着某代码已过时,不推荐再使用。bool use_ref_tick  __attribute__((deprecated)); //已过时,请改用source_clk选择时钟源。};
} uart_config_t;

第一个是波特率,直接传入数字即可。

第二个数据位,可选的有UART_DATA_5_BITSUART_DATA_6_BITSUART_DATA_7_BITSUART_DATA_8_BITS

第三个是校验位,一般就是上面示例中的无校验

第四个是停止位,可选的有UART_STOP_BITS_1(1 个停止位)、UART_STOP_BITS_1_5(1.5 个停止位,仅适用于 5 数据位)和 UART_STOP_BITS_2(2 个停止位)。

第五个是硬件流控制,一般不使用,选择UART_HW_FLOWCTRL_DISABLE(禁用流控制)即可。

第六个是RTS的阈值 按照官方给的配置为122即可,不配置就行。

#define Baud_Rate (9600)//波特率
#define Uart_Num UART_NUM_2   //串口通信x  即UART1,UART2...uart_config_t uart_config_InitStructure={.baud_rate=Baud_Rate,//波特率.data_bits=UART_DATA_8_BITS,//数据位 8位.flow_ctrl=UART_HW_FLOWCTRL_DISABLE, //流控制 失能.parity=UART_PARITY_DISABLE,//奇偶校验位 无校验.stop_bits=UART_STOP_BITS_1,//停止位 1位.rx_flow_ctrl_thresh=122,.source_clk = UART_SCLK_DEFAULT//配置时钟,默认时钟};uart_param_config(Uart_Num,&uart_config_InitStructure);//设置UsartNumx  x 为 0 1 2 以及把上面的参数配置进来

在这里插入图片描述

配置引脚

分配引脚的方法是调用函数uart_set_pin()
在这里插入图片描述
在这里插入图片描述
一般来说我们最后两个参数是不需要的,给-1就行。

#define Uart_Num UART_NUM_2   //串口通信x  即UART1,UART2...
#define Uart_Tx_Pin_Num GPIO_NUM_17 //tx引脚
#define Uart_Rx_Pin_Num GPIO_NUM_16//rx引脚uart_set_pin(Uart_Num,Uart_Tx_Pin_Num,Uart_Rx_Pin_Num,-1,-1);             //设置引脚,tx为17,rx为16

安装驱动程序

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#define Uart_Num UART_NUM_2   //串口通信x  即UART1,UART2...
#define Uart_RxBuffer_Size (1024)//接收缓存区大小
#define Uart_TxBuffer_Size (1024)//发送缓冲区大小uart_driver_install(Uart_Num,Uart_RxBuffer_Size,Uart_TxBuffer_Size,0,NULL,0);//安装uart

发送数据

在这里插入图片描述

#define Uart_Num UART_NUM_2   //串口通信x  即UART1,UART2...
/*** @description: 串口发送一个字节* @param {uint8_t} byte 要发送的字节* @return {*}*/
void Uart_SendByte(uint8_t byte)
{uart_write_bytes(Uart_Num,&byte,sizeof(byte));
}

接收数据

这个就比较麻烦,stm32接收数据时可以用中断,但这个没提供相关中断函数,但可以用freertos的轮询查询
在这里插入图片描述
读取使用uart_read_bytes()函数
在这里插入图片描述

#define Uart_RxBuffer_Size (1024)//接收缓存区大小
#define Uart_task_size (1024)//任务栈大小
xTaskCreatePinnedToCore(Uart_ReceiveData_Task, "Uart_ReceiveData_Task", Uart_task_size*2, NULL, configMAX_PRIORITIES-1, &Uart_RxData_Task_Handel, 1);//创建接收任务
/*** @description: 串口接收数据* @return {*}*/
void Uart_ReceiveData_Task()
{uint8_t* receiveDataBuffer = (uint8_t*) malloc(Uart_RxBuffer_Size + 1);//创建接收空间int receiveSize;//用于判断发是否接收到了数据while(1){receiveSize =uart_read_bytes(Uart_Num,receiveDataBuffer,Uart_RxBuffer_Size,(10/portTICK_PERIOD_MS));//接收数据,10ms超时if(receiveSize>0)//接收到了数据{receiveDataBuffer[receiveSize]=0;//将数据的最后一位置0 表示结束}}free(receiveDataBuffer);//释放缓冲区vTaskDelete(Uart_RxData_Task_Handel);//删除任务
}

整体代码测试

main.c

/** @Author: i want to 舞动乾坤* @Date: 2024-07-24 12:23:38* @LastEditors: i want to 舞动乾坤* @LastEditTime: 2024-07-24 13:03:01* @FilePath: \uart_serial\main\main.c* @Description: * * Copyright (c) 2024 by i want to 舞动乾坤, All Rights Reserved. */
#include <stdio.h>
#include "myUart.h"
void app_main(void)
{Uart_Init();Uart_Printf("你好,世界\r\n");Uart_SendNumber(12345,5);Uart_SendString("\r\n");Uart_SendString("hahahaha\r\n");}

myUart.c

/** @Author: i want to 舞动乾坤* @Date: 2024-07-24 12:27:08* @LastEditors: i want to 舞动乾坤* @LastEditTime: 2024-07-24 13:23:22* @FilePath: \uart_serial\main\myUart.c* @Description: * * Copyright (c) 2024 by i want to 舞动乾坤, All Rights Reserved. */#include <freertos/FreeRTOS.h>
#include <freeRtos/task.h>
#include <driver/uart.h>
#include <driver/gpio.h>
#include <stdio.h>
#include <stdarg.h>
#include "myUart.h"#define Baud_Rate (9600)//波特率
#define Uart_Num UART_NUM_2   //串口通信x  即UART1,UART2...
#define Uart_Tx_Pin_Num GPIO_NUM_17 //tx引脚
#define Uart_Rx_Pin_Num GPIO_NUM_16//rx引脚
#define Uart_RxBuffer_Size (1024)//接收缓存区大小
#define Uart_TxBuffer_Size (1024)//发送缓冲区大小
#define Uart_task_size (1024)//任务栈大小TaskHandle_t Uart_RxData_Task_Handel=NULL;//接收数据的任务句柄
void Uart_ReceiveData_Task();
void Uart_Init()
{uart_config_t uart_config_InitStructure={.baud_rate=Baud_Rate,//波特率.data_bits=UART_DATA_8_BITS,//数据位 8位.flow_ctrl=UART_HW_FLOWCTRL_DISABLE, //流控制 失能.parity=UART_PARITY_DISABLE,//奇偶校验位 无校验.stop_bits=UART_STOP_BITS_1,//停止位 1位.rx_flow_ctrl_thresh=122,.source_clk = UART_SCLK_DEFAULT//配置时钟};uart_param_config(Uart_Num,&uart_config_InitStructure);//设置UsartNumx  x 为 0 1 2uart_set_pin(Uart_Num,Uart_Tx_Pin_Num,Uart_Rx_Pin_Num,-1,-1);             //设置引脚,tx为17,rx为16uart_driver_install(Uart_Num,Uart_RxBuffer_Size,Uart_TxBuffer_Size,0,NULL,0);//安装uartxTaskCreatePinnedToCore(Uart_ReceiveData_Task, "Uart_ReceiveData_Task", Uart_task_size*2, NULL, configMAX_PRIORITIES-1, &Uart_RxData_Task_Handel, 1);//创建接收任务}/*** @description: 串口接收数据* @return {*}*/
void Uart_ReceiveData_Task()
{uint8_t* receiveDataBuffer = (uint8_t*) malloc(Uart_RxBuffer_Size + 1);//创建接收空间int receiveSize;//用于判断发是否接收到了数据while(1){receiveSize =uart_read_bytes(Uart_Num,receiveDataBuffer,Uart_RxBuffer_Size,(10/portTICK_PERIOD_MS));//接收数据,10ms扫描一次if(receiveSize>0)//接收到了数据{receiveDataBuffer[receiveSize]=0;//将数据的最后一位置0 表示结束}}free(receiveDataBuffer);//释放缓冲区vTaskDelete(Uart_RxData_Task_Handel);//删除任务
}/*** @description: 串口发送一个字节* @param {uint8_t} byte 要发送的字节* @return {*}*/
void Uart_SendByte(uint8_t byte)
{uart_write_bytes(Uart_Num,&byte,sizeof(byte));
}/*** @description: 通过USART发送一个数组* @param {uint8_t} *Array  数组的首地址* @param {uint16_t} Length 数组的长度 用于判断数组是否结束* @return {*}*/ 
void Uart_SendArray(uint8_t *Array,uint16_t Length)
{uint16_t i;for(i=0;i<Length;i++){Uart_SendByte(Array[i]);}}/*** @description: 通过USART发送字符串* @param {char} *String 要发送的字符串* @return {*}*/ 
void Uart_SendString(char *String)
{uint8_t i;for(i=0;String[i]!='\0';i++){Uart_SendByte(String[i]);}
}/*** @description: x的y次方函数* @param {uint32_t} x 要转换的数字* @param {uint32_t} y 次方* @return {返回x的y次方}*/ 
uint32_t Uart_Pow(uint32_t x,uint32_t y)
{uint32_t result=1;while(y--){result*=x;}return result;
}/*** @description: 通过USART发送一个数字* @param {uint32_t} Number 要发送的数字* @param {uint8_t} Length  发送数字的长度* @example  12345 分别取出某一位 :万:12345 /10000 %10=1 ; 千:12345 /1000%10=2 ; 百:12345 /100%10=3;  十:12345/10%10=4 ; 个:12345/1%10=5总结下来 取某位 即:数字除以10的x次方%10 * @return {*}*/ 
void Uart_SendNumber(uint32_t Number,uint8_t Length)
{uint8_t i;for(i=0;i<Length;i++){Uart_SendByte(Number / Uart_Pow(10, Length - i - 1) % 10 + '0') ;//+'0'是数字ASCII表对应数字0的基地址(偏移量)}}int fputc(int ch ,FILE *f)
{Uart_SendByte(ch);return ch;
}/*** @description: 重定向到Uart上,使用Uart可输出至串口* @param {char} *format* @return {*}*/
void Uart_Printf(char *format, ...)//可变参数
{char String[100];va_list arg;va_start(arg,format);vsprintf(String,format,arg);va_end(arg);Uart_SendString(String);
}

myUart.h

/** @Author: i want to 舞动乾坤* @Date: 2024-07-24 12:27:21* @LastEditors: i want to 舞动乾坤* @LastEditTime: 2024-07-24 12:51:08* @FilePath: \uart_serial\main\myUart.h* @Description: * * Copyright (c) 2024 by i want to 舞动乾坤, All Rights Reserved. */
#ifndef _MYUART__H
#define _MYUART__H
void Uart_Init();
void Uart_SendByte(uint8_t byte);
void Uart_SendString(char *String);void Uart_SendNumber(uint32_t Number,uint8_t Length);
void Uart_Printf(char *format, ...);//可变参数#endif

效果:
在这里插入图片描述
参考大佬文章
1.【快速上手ESP32(基于ESP-IDF&VSCode)】05-UART串口通信
2. ESP32 之 ESP-IDF 教学(九)—— 串口通信(UART)

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 遇到not allow unquoted fieldName怎么办
  • Leetcode 721.账户合并(hash+dfs)☆
  • [MySQL]02 存储引擎与索引,锁机制,SQL优化
  • Python:Flask自定义URL路由参数过滤器
  • 电缆故障精准定位系统
  • 在CentOS中配置三个节点之间相互SSH免密登陆
  • 极狐GitLab如何启用和配置PlantUML?
  • 【Django】在vscode中运行调试Django项目(命令及图形方式)
  • 观成科技:活跃窃密木马TriStealer加密通信分析
  • setsockopt选项对tcp速度
  • HTTP 协议浅析
  • k8s 公共服务
  • 问题处理--No such file or directory
  • Springboot+Maven多模块项目开发
  • 构建稳固与安全的网络环境:从微软蓝屏事件看软件更新流程与应急响应
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • CentOS 7 修改主机名
  • Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!
  • jdbc就是这么简单
  • Logstash 参考指南(目录)
  • Python爬虫--- 1.3 BS4库的解析器
  • 阿里云ubuntu14.04 Nginx反向代理Nodejs
  • 动态规划入门(以爬楼梯为例)
  • 对象管理器(defineProperty)学习笔记
  • 基于遗传算法的优化问题求解
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • Java性能优化之JVM GC(垃圾回收机制)
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (3)(3.5) 遥测无线电区域条例
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (八)c52学习之旅-中断实验
  • (纯JS)图片裁剪
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • (状压dp)uva 10817 Headmaster's Headache
  • .NET COER+CONSUL微服务项目在CENTOS环境下的部署实践
  • .NET 命令行参数包含应用程序路径吗?
  • .net 受管制代码
  • .NET8使用VS2022打包Docker镜像
  • .NET程序员迈向卓越的必由之路
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • .NET正则基础之——正则委托
  • @RestController注解的使用
  • [ 常用工具篇 ] AntSword 蚁剑安装及使用详解
  • [ 数据结构 - C++]红黑树RBTree