STM32串口详解

2023-05-16

实验一:简单的利用串口接收中断回调函数实现数据的返回

 

关于串口调试助手,还应知道:

  • 发送英文字符需要用一个字符即8位,发送汉字需要两个字符即16位,如上图,发送汉字“姜”实际是发送“BD AA”而发送英文字符X实际是发送“58”,本质上没有太大区别;
  • 勾选了下方“发送新行”后,XCOM就会再你输入的需要发送的数据后自动加上一个回车(0X0D+0X0A),如果不勾选则我们在手动输入完“宋S”后还需敲一个回车键只有这样点击发送后,调试助手上方窗体才能将其显示,这是因为我们在程序的串口中断中自定义了一个数据接收协议,即只有当接受的数据以回车结尾(0X0D+0X0A),串口才认可数据接受完毕

这里可以看出下列代码中的 0D回车,0A换行 是用来判断结束位的

if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D))

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>//meset()函数调用
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
#define RXBUFFERSIZE  256     //最大接收字节数
char RxBuffer[RXBUFFERSIZE];   //接收数据
uint8_t aRxBuffer;			//接收中断缓冲
uint8_t Uart1_Rx_Cnt = 0;		//接收缓冲计数
/* USER CODE END PV */
  /* USER CODE BEGIN 2 */
    HAL_UART_Receive_IT(&huart1,&aRxBuffer,1);   //中断接收一个字符
  /* USER CODE END 2 */
/*
串口接收中断回调函数
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
	{
		if (Uart1_Rx_Cnt >= 255)
		{
			memset(RxBuffer,0x00,sizeof(RxBuffer));//对数组进行清零操作
			HAL_UART_Transmit(&huart1,(uint8_t *)"数据溢出",4,0xffff);//
		}
		else
		{
			RxBuffer[Uart1_Rx_Cnt++]=aRxBuffer;   //接收数据转存
			if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位 0D回车,0A换行 
					{
						HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
						
						while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
						
						Uart1_Rx_Cnt = 0;
						memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组
					}

		
		}
		    HAL_UART_Receive_IT(&huart1,&aRxBuffer,1);	//使得程序可以重新触发接收中断	+

} 

上述代码实现的是 发送数据被返回

实验二:

1、串口发送/接收函数

  • HAL_UART_Transmit();串口发送数据,使用超时管理机制 
  • HAL_UART_Receive();串口接收数据,使用超时管理机制
  • HAL_UART_Transmit_IT();串口中断模式发送  
  • HAL_UART_Receive_IT();串口中断模式接收
  • HAL_UART_Transmit_DMA();串口DMA模式发送
  • HAL_UART_Transmit_DMA();串口DMA模式接收

2、串口中断函数

  • HAL_UART_IRQHandler(UART_HandleTypeDef *huart);  //串口中断处理函数
  • HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);  //串口发送中断回调函数
  • HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);  //串口发送一半中断回调函数(用的较少)
  • HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);  //串口接收中断回调函数
  • HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//串口接收一半回调函数(用的较少)
  • HAL_UART_ErrorCallback();串口接收错误函数

3串口查询函数

  HAL_UART_GetState();  判断UART的接收是否结束,或者发送数据是否忙碌

UART几个标志位

TXE、TC、RXNE、ORE。

TXE:发送数据寄存器为空 (Transmit data register empty)

  • 0:数据未传输到移位寄存器
  • 1:数据传输到移位寄存器

TC:发送完成 (Transmission complete)

  • 0:传送未完成
  • 1:传送已完成

RXNE:读取数据寄存器不为空 (Read data register not empty)

  • 0:未接收到数据
  • 1:已准备好读取接收到的数据

ORE:上溢错误 (Overrun error)

  • 0:无上溢错误
  • 1:检测到上溢错误

UART接收丢失数据

UART接收丢失数据与软件和硬件都有可能有关系,下面说几个常见丢失数据的原因及解决办法。

1.接收溢出丢失数据

指未及时取走数据导致溢出错误而丢失数据,通常是发生在大量数据、以查询方式接收数据的情况下。在MCU启动过程中、接收数据过多处理不及时、复杂系统响应不及时等情况都会出现数据丢失的情况。

解决办法:

  • 及时清除溢出错误标志
  • 利用通信协议过滤因数据丢失导致的问题

2.接收中断丢失数据

使用UART中断接收数据相比查询接收数据的方式更常见,中断方式比查询方式响应更及时,但不合理处理同样也会存在数据丢失的情况。

在数据量大时,UART接收中断函数耗时、优先级低等情况下容易丢失数据。

解决办法:

  • 中断函数里减少不必要的耗时
  • 合理分配中断优先级
  • 使能中断前清除标志位

3.时钟误差导致丢失数据

在通信波特率较高的情况下,如果时钟误差加大,很可能导致数据丢失。

解决办法:

  • 使用更高精度晶振
  • 降低通信波特率

UART发送丢失数据

UART发送丢失数据很多工程师都遇到过,通常情况下是传输未完成的原因。

HAL库已经有几年了,但还是有很多工程师都使用标准外设库,这时如果自己封装接口不当,就会存在发送最后一字节数据丢失的问题。

1.UART传输未完成导致数据丢失

如下代码,只考虑非空,但实际传输并未完成。

//往USART1,发送 length长度的数据data
void SendData(u8 *data,u8 length)
{
    u8 i;
    for(i=0;i<length;i++)
    {
        USART_SendData(USART2, data[i]);
        while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)//等得发送完成
        {
        }  
    }
}

但发送非空不代表发送完成,虽然在某些场合更高效,但某些场合就会导致数据丢失。

比如:使用此函数发送之后进入休眠、关闭接收端设备电源等情况下。

解决办法:使用HAL封装的接口,代码包含判断传输完成

/*******************************************************************************
  * @函数名称	SendData1
  * @函数说明   向串口1发送数组信息
  * @输入参数 
			data:要发送的信息的首地址
			len: 发送的长度
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void SendData1(u8 *data,u8 length)
{
    u8 i;
    for(i=0;i<length;i++)
    {
			HAL_UART_Transmit(&huart1,&data[i],length,0xFFFF); //将收到的信息发送出去,HAL封装的接口,代码包含判断传输完成
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32串口详解 的相关文章

  • 处理器指令周期执行时间

    我的猜测是 no operation 内在 ARM 指令应花费 1 168 MHz 来执行 前提是每个NOP在一个时钟周期内执行 我想通过文档验证这一点 有关处理器指令周期执行时间的信息是否有标准位置 我试图确定 STM32f407IGh6
  • GCC - 如何停止链接 malloc?

    我正在努力将我的代码缩减到最小的骨架大小 我使用的是只有 32k 闪存的 STM32F0 需要很大一部分闪存用于数据存储 我的代码已经有大约 20k 闪存大小 其中一些是由于使用了 STM32 HAL 函数 我可以在以后需要时对其进行解释和
  • CMSIS 库是否应该包含在版本控制中? [复制]

    这个问题在这里已经有答案了 通常 我曾经在版本控制中包含芯片供应商 ST 提供的设备特定标头和源以及 CMSIS Core 标头 数量不多 也没有更新的习惯 我使用STM32微控制器 但我不使用立方体框架 or the 标准外设库 最近 我
  • 当数据大小较小时,内存到内存 DMA 传输是否需要权衡?

    我正在学习 STM32 F4 微控制器 我正在尝试找出使用 DMA 的限制 根据我的理解和研究 我知道如果数据量较小 即设备使用DMA生成或消耗少量数据 则开销会增加 因为DMA传输需要DMA控制器执行操作 从而不必要地增加系统成本 我做了
  • 137-基于stm32单片机智能保温杯控制装置Proteus仿真+源程序

    资料编号 137 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DS18B20传感器 电机 制作一个基于stm32单片机智能保温杯控制装置Proteus仿真 2 通过DS18b20传感器检测当前保温杯水的温度 并且
  • 136-基于stm32单片机家庭温湿度防漏水系统设计Proteus仿真+源程序

    资料编号 136 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 蜂鸣器 制作一个基于stm32单片机家庭温湿度防漏水系统设计Proteus仿真 2 通过DHT11传感器检测当前温湿度 并且显示到L
  • 135-基于stm32单片机超声波非接触式感应水龙头控制系统Proteus仿真+源程序

    资料编号 135 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 电机 超声波传感器 制作一个基于stm32单片机超声波非接触式感应水龙头控制系统Proteus仿真 2 通过DHT11传感器检测当前
  • HAL库STM32常用外设教程(二)—— GPIO输入\输出

    HAL库STM32常用外设教程 二 GPIO输入 输出 文章目录 HAL库STM32常用外设教程 二 GPIO输入 输出 前言 一 GPIO功能概述 二 GPIO的HAl库驱动 三 GPIO使用示例 1 示例功能 四 代码讲解 五 总结
  • rt-thread studio中新建5.0不能用

    文章目录 一 版本对比 二 文件和文件夹打斜杠 在使用RT Thread studio创建新工程5 0版本的时候 结果发现新建完成之后程序不能正常运行 但是创建4 10版本的时候却能运行 那肯定是新版本出现了BUG 一 版本对比 首先对比了
  • STM32F4 通过软复位跳转到引导加载程序,无需 BOOT0 和 BOOT1 引脚

    我问这个问题是因为可以在这里找到类似问题的答案 通过应用程序跳转到 STM32 中的引导加载程序 即从用户闪存在引导模式下使用引导 0 和引导 1 引脚 用户 JF002 JF002回答 当我想跳转到引导加载程序时 我在其中一个备份寄存器中
  • 匹配 STM32F0 和 zlib 中的 CRC32

    我正在研究运行 Linux 的计算机和 STM32F0 之间的通信链路 我想对我的数据包使用某种错误检测 并且由于 STM32F0 有 CRC32 硬件 并且我在 Linux 上有带有 CRC32 的 zlib 所以我认为在我的项目中使用
  • STM32超声波——HC_SR04

    文章目录 一 超声波图片 二 时序图 三 超声波流程 四 单位换算 五 取余计算 六 换算距离 七 超声波代码 一 超声波图片 测量距离 2cm 400cm 二 时序图 1 以下时序图要先提供一个至少10us的脉冲触发信号 告诉单片机我准备
  • 硬件基础-电容

    电容 本质 电容两端电压不能激变 所以可以起到稳定电压作用 充放电 电容量的大小 想使电容容量大 使用介电常数高的介质 增大极板间的面积 减小极板间的距离 品牌 国外 村田 muRata 松下 PANASONIC 三星 SAMSUNG 太诱
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • 库函数点亮Led

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 例如 随着人工智能的不断发展 机器学习这门
  • STM32 Nucleo 上的上升沿中断多次触发

    我正在使用 STM32 NUCLEO F401RE 微控制器板 我有一个扬声器 经过编程 当向上 向下推操纵杆时 可以按设定的量改变频率 我的问题是 有时 通常 当向上 向下推动操纵杆时 频率会增加 减少多次 这意味着 ISR 正在执行多次
  • 通过JTAG恢复STM32 MCU磨掉的标记

    我有一块可能带有 STM32 MCU 的板 我想为该板制作定制固件 因为库存板有很多问题 不幸的是 电路板制造商很友善地磨掉了所有标记 有没有办法通过 jtag 获取设备 系列 ID 并将其交叉引用到型号 我能找到的一切都是关于获取芯片的唯
  • HAL_Delay() 陷入无限循环

    我被 HAL Delay 函数困住了 当我调用此函数 HAL Delay 时 控制陷入无限循环 在寻找问题的过程中 我发现了这个 http www openstm32 org forumthread2145 threadId2146 htt

随机推荐

  • Linux:简单三步,教你解决ping:www.baidu.com:未知的名称或者服务

    Linux xff1a 简单三步 xff0c 教你解决ping www baidu com 未知的名称或者服务 1 在VMware Workstation中点开编辑 xff0c 找到虚拟网络编辑器2 直接点击更改设置3 点击还原默认设置 x
  • C++:从结构体开始理解this指针

    C 43 43 xff1a 从结构体开始理解this指针 span class token macro property span class token directive keyword include span span class
  • 原来直接插入排序这么简单(附完整代码)

    原来插入排序这么简单 附完整代码 xff09 基本思想带哨兵位的插入排序二分插入排序完整代码 基本思想 做一件是之前我们总是要先知道我们做这件的核心思想 xff0c 这样会让我们做事的效率得到有效的提高 xff1b 现在我们来看看插入排序算
  • 一张图带你了解c/c++的内存分布

    c c 43 43 的内存分布 对照这些代码查看对应内存分布 xff1a span class token keyword int span globalVar span class token operator 61 span span
  • 用一个例子理解希尔排序

    用一个例子理解希尔排序 思想代码 思想 希尔排序是把序列按下标的一定增量分组 xff0c 对每组使用直接插入排序算法排序 xff1b 随着增量的逐渐减少 xff0c 每组包含的关键词越来越多 xff0c 当增量减至1时 xff0c 整个序列
  • c++ pi

    C 43 43 中表示pi的方法有两种 xff08 1 xff09 math库中利用arctan函数算出 span class token function tan span span class token punctuation spa
  • 【非数值数据的编码】西文字符和汉字的编码表示 汉字国标码、机内码详细理解

    西文字符和汉字的编码表示 西文字符概念ASCII码表特点 西文字符特点西文字符表示 xff08 常用编码为7位ASCII码 xff09 西文字符操作 汉字字符编码形式输入码字符集与汉字内码汉字的区位码汉字的国标码汉字内码 汉字的字模点阵码和
  • 修改centos7系统用户最大线程数和最大文件数限制

    修改centos7系统用户最大线程数和最大文件数限制 需要注意 xff0c 不同版本的Linux系统所对应的修改方法不同 ulimit 的作用 ulimit xff1a 显示 xff08 或设置 xff09 用户可以使用的资源的限制 xff
  • (已全部解决)ubantu18运行vins遇到的问题

    1 sudo rosdep init时报错 xff1a 打开hosts文件 sudo gedit etc hosts 在文件末尾添加 151 101 84 133 raw githubusercontent com 保存后退出再尝试 sud
  • ROS只使用思岚A1激光雷达进行slam建图

    使用思岚A1激光雷达 A1的ros功能包下载地址 xff1a https github com slamtec rplidar ros 因为只有激光雷达 xff0c 需要其做SLAM的话 xff0c 就需要有一个laser scan mat
  • STM32 四轴无人机的设计——基于HCSR04超声波模块的距离检测与警报设计

    1 系列总述 从现在开始将会进入四轴无人机的制作 xff0c 我是第一次制作四旋翼 xff0c 从前没有接触过这个方面 xff0c 手边的参考资料只有一本四轴的设计书和正点原子F405飞控的源码 xff0c 所以代码逻辑设计方面肯定有所欠缺
  • 【C++基础】inline与内联函数

    目录 引入 inline 关键字inline使用限制类中的成员函数与inline 引入 inline 关键字 为了解决一些频繁调用的小函数大量消耗栈空间 xff08 栈内存 xff09 的问题 xff0c 特别的引入了 inline 修饰符
  • 串口通信的基本原理详解

    目录 串口通信 串口通信的两种基本方式 异步数据的数据发送过程 异步通信的数据接收过程 9针串口 xff08 DB9 xff09 TTL与RS232区别 TTL RS232 xff1a 串口通信的数据格式 通讯方式 偶校验与奇校验 停止位
  • jeston nano安装Ubuntu镜像时启动遇到问题

    A start job is running for End user configuration after initial OEM installation 开始我跑了一下午 43 一晚上 xff0c 都没成功 xff0c 第二天 xf
  • cmake 常用变量、常用环境变量、常用语法总结

    一 cmake 变量引用的方式 前面我们已经提到了 使用 进行变量的引用 在 IF 等语句中 是直接使用变量名而不通过 取值 二 cmake 自定义变量的方式 主要有隐式定义和显式定义两种 隐式定义的例子 xff1a PROJECT 指令
  • Java基础篇:Iterator迭代器

    一 什么是Iterator xff1a 迭代器 Iterator 是一个对象 xff0c 它的工作是遍历并目标序列中的对象 xff0c 它提供了一种访问一个容器 container 对象中的各个元素的方法 xff0c 把访问逻辑从不同类型的
  • 2022-2-19 ros环境变量

    学习时间及标题 xff1a 2022 2 19 ros环境变量 学习内容 xff1a 1 添加环境变量 xff1a source span class token operator span span class token operato
  • EGO-Planner: An ESDF-free Gradient-based Local Planner for Quadrotors(论文学习)

    EGO规划器 xff1a 一种基于ESDF自由梯度的四转子局部规划器 摘要 ESDF地图被广泛运用在局部地图的梯度方向和大小估计之中 xff0c 但是由于我们在进行轨迹优化的过程中 xff0c 只用到了ESDF地图中很小的一部分 xff0c
  • cmake "undefined reference to"

    main函数在调用其他 c或 cpp文件的函数时 xff0c 有以下几种情况 函数名写错 没有将其他 c或 cpp文件链接到main o xff0c 导致main函数在执行时找不到需要调用的函数 的解决方法 修改CMakeLists txt
  • STM32串口详解

    实验一 xff1a 简单的利用串口接收中断回调函数实现数据的返回 关于串口调试助手 xff0c 还应知道 xff1a 发送英文字符需要用一个字符即8位 xff0c 发送汉字需要两个字符即16位 xff0c 如上图 xff0c 发送汉字 姜