STM32串口通讯(RS232、RS485、TTL)详解

前言

STM32串口(Serial Communication Interface)是STM32微控制器中用于串行通信的接口,通常指的是USART(通用同步异步收发器)或UART(通用异步收发传输器)。这些接口允许STM32微控制器与其他设备(如计算机、其他微控制器、传感器等)进行串行数据交换。

串行通信一般是以帧格式传输数据,数据一帧一帧的被传输,每帧包含有起始信号、数据信息、校验信息、停止信号。

一、物理层

1.RS232和RS485的区别

我们常用RS232和RS485这两种串行通信接口标准,它们各自具有不同的特点和适用场景。

通信接口电平信号传输距离受干扰传输单位
RS232“1”为-3V至-15V,“0”为+3V至+15V一般10米以内容易一主一从
RS485

“1”以两线间的电压差+2V至+6V表示

“0”以两线间的电压差-6V至-2V表示

最多可达3000米不易一主多从

通过上面的表格可以看出两种通信接口的不同,单片机上的UART/USART口都是TTL电平信号,想要通过RS485或者RS232传输数据,需要在它们之间电平转换芯片,我们一般用RS232作打印日常的调试信息,RS485在工业上面用的比较多,因为比较稳定不易受干扰。

2.TTL电平

TTL全称为Transistor-Transistor Logic,即晶体管-晶体管逻辑电平。逻辑“1”通常对应的电压范围在2.4V到5V之间,而逻辑“0”对应的电压范围在0V到0.8V之间。我们一般会用到USB TO TTL这种小模块,来连接单片机的UART口来打印调试信息。

二、串口通讯协议

1.连接方式

典型的UART/USART通信使用3根线完成,分别是发送线(TX)、接收线(RX)和地线(GND)。在通信时,必须将双方的TX和RX交叉连接,并将GND相连才可正常通信。

2.协议构成

(1)起始位(Start Bit):

起始位始终是一个逻辑0(低电平),它标志着数据开始传输。对于接收方,当检测到从高到低的跳变时,就知道新的数据字符即将开始。

(2)数据位(Data Bits):

数据位是实际要传输的信息。STM32 UART支持5至9位的数据位,但最常用的配置是8位数据位。数据位是从最低位(LSB)到最高位(MSB)依次传输的

(3)校验位(Parity Bit):

  • 校验位是可选的,用于增加数据传输的可靠性。STM32 UART支持奇校验、偶校验和无校验模式。
    • 奇校验:数据中1的个数加上校验位中1的个数应为奇数。
    • 偶校验:数据中1的个数加上校验位中1的个数应为偶数。
    • 无校验:没有校验位。

(4)停止位(Stop Bit):

停止位标志着数据字符的结束。STM32 UART支持1位、1.5位或2位的停止位。停止位始终是高电平。停止位的作用是允许接收器有足够的时间来处理数据,并准备接收下一个字符。

(5)波特率(Baud Rate):

波特率定义了每秒传输的位数。例如,9600波特意味着每秒传输9600个位。STM32 UART可以配置为支持广泛的波特率范围。

3.工作原理

在闲置状态下,UART的引脚一直被拉高,引脚如果被拉低,它标志着数据开始传输,然后开始依次传输数据位,一般我们都用8位数据位,然后根据配置发送奇偶校验位,最后拉高电平,停止数据传输,数据传输的速率是根据波特率得出的,如果发送和接收两端使用了不同的波特率,那么得到的就会是一堆乱码

三、应用程序

1.初始化串口

//bound:波特率
void uart_init()
{	//UART 初始化设置UART1_Handler.Instance=USART1;					    //USART1UART1_Handler.Init.BaudRate=115200;				    //波特率UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式UART1_Handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位UART1_Handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控UART1_Handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式HAL_UART_Init(&UART1_Handler);					    //HAL_UART_Init()会使能UART1//HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量(使用回调函数处理中断需要调用该函数)}

由上面代码得知,我们配置了USART1,波特率为115200,数据位为8,一个停止位,没有奇偶校验,可以同时收发。

2.使能GPIO口

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{//GPIO端口设置GPIO_InitTypeDef GPIO_Initure;if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化{__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA时钟__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1时钟GPIO_Initure.Pin=GPIO_PIN_9;			//PA9GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//复用推挽输出GPIO_Initure.Pull=GPIO_PULLUP;			//上拉GPIO_Initure.Speed=GPIO_SPEED_FAST;		//高速GPIO_Initure.Alternate=GPIO_AF7_USART1;	//复用为USART1HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9GPIO_Initure.Pin=GPIO_PIN_10;			//PA10HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10__HAL_UART_DISABLE_IT(huart,UART_IT_TC);
#if EN_USART1_RX__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE);		//开启接收中断HAL_NVIC_EnableIRQ(USART1_IRQn);				//使能USART1中断通道HAL_NVIC_SetPriority(USART1_IRQn,3,3);			//抢占优先级3,子优先级3
#endif	}}

第一段代码调用Hal库的HAL_UART_Init(&UART1_Handler)函数以后,我们需要在HAL_UART_MspInit将对应的TX和RX两个口使能才能使串口正常使用。

3.串口发送数据

HAL_UART_Transmit(&UART1_Handler,(uint8_t*)USART_RX_BUF,len,1000);

用HAL_UART_Transmit这个函数可以通过UART1发出信息,USART_RX_BUF是我们要发出的内容,len是内容数组的大小。

4.串口接收数据

//串口1中断服务程序
void USART1_IRQHandler(void)                	
{ u8 Res;
#if SYSTEM_SUPPORT_OS	 	//使用OSOSIntEnter();    
#endifif((__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_RXNE)!=RESET)){HAL_UART_Receive(&UART1_Handler,&Res,1,1000); if(USART_RX_CNT<USART_REC_LEN){USART_RX_BUF[USART_RX_CNT]=Res;USART_RX_CNT++;			 									     }    		 }HAL_UART_IRQHandler(&UART1_Handler);	
#if SYSTEM_SUPPORT_OS	 	//使用OSOSIntExit();  											 
#endif
} 
#endif	

接收数据是在串口的中断里面进行的,每来8bit数据,都会进入一次串口中断,USART_RX_BUF就是我们接收到数据的内容,USART_RX_CNT就是内容数组的大小,注意本代码并未对其优化,按常理来说,还应当对其加一个定时器,按传输速率计算多长时间没传来下一个数据,就算本次数据传输完成了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/43308.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跟我从零开始学STL(STL代码基础01)---string容器

引言 小伙伴们大家好&#xff0c;又到了新的篇章了&#xff0c;感谢大家的支持&#xff01;今天我们要学一个新的篇章&#xff0c;STL。在编程领域&#xff0c;STL&#xff08;Standard Template Library&#xff0c;标准模板库&#xff09;是C语言中非常重要的一部分。它为我们…

zabbix 学习笔记

文章目录 Zabbix 安装Ubuntu 18.04.1 server 安装Zabbix 4.0Centos7 安装Zabbix3.4Centos7 安装zabbix4.2Centos7.1908安装zabbix 基于ngixDebian11安装zabbix6.0LTS 基于PostgreSQL和NGINXAlmaLinux9.2使用国内清华源在线安装zabbix6.0.18LTS 基于MySQL和NGINXUbunut22.04使用…

crewAI中通过Ollama调用本地模型的两种方式

0 背景 crewAI中默认使用的gpt4的模型&#xff0c; 在环境中配置OPENAI_API_KEY即可使用。 但openai的api毕竟是要花钱的&#xff0c; 况且现在对大陆地区做了封禁&#xff0c; 使用起来不是那么方便。 而Ollama可以方便的运行本地的大模型&#xff0c; 既不用花钱&#xff0c…

图文讲解IDEA如何导入JDBC驱动包

前言 学习JDBC编程,势必要学会如何导入驱动包,这里笔者用图文的方式来介绍 视频版本在这里 50秒教你怎么导入驱动包然后进行JDBC编程的学习_哔哩哔哩_bilibili 忘记录音频了,大伙凑合着看 下载驱动包 https://mvnrepository.com/artifact/mysql/mysql-connector-java 去中…

GB28181设备如何添加

简介 此篇描述视频网关&#xff08;中间件&#xff09;接入大华、海康、ONVIF设备&#xff08;NVR、摄像头&#xff09;、GB28181设备步骤和流程。 阅读本文档之前建议先阅览视频网关&#xff08;中间件&#xff09;用户使用手册。 接入方式和说明 视频网关&#xff08;中间…

Flutter——最详细(GestureDetector)使用教程

背景 组件手势检测&#xff0c;单击、双击、长按、松开、移动、横向拖动、竖向拖动等事件 属性作用onTap单击onDoubleTap双击onLongPress长按onPanUpdate拖动实时更新onHorizontalDragDown横向点击onVerticalDragDown竖向点击 GestureDetector(onTap: () > setState(() >…

论文学习_Getafix: learning to fix bugs automatically

1. 引言 研究背景:现代生产代码库极其复杂并且不断更新。静态分析器可以帮助开发人员发现代码中的潜在问题(在本文的其余部分中称为错误),这对于在这些大型代码库中保持高代码质量是必要的。虽然通过静态分析尽早发现错误是有帮助的,但修复这些错误的问题在实践中仍然主要…

ZP-UHZ系列顶装式磁翻板液位计

一、用途及特点 ZP-UHZ系列磁浮子液位计是一种能就地指示或远传显示与控制的物位仪表&#xff0c;它广泛用于石油、化工、轻工、电力、核工业以及食品、医药等工业中&#xff0c;对各种塔、罐、槽、箱等容器中介质的液位进行指示和控制。 ZP-UHZ系列磁浮子液位计的指示部分及发…

jmeter-beanshell学习7-props获取全局变量和设置全局变量

继续写点不痛不痒的小东西。第一篇写了vars设置变量&#xff0c;但是vars只能作用在同一个线程组。跨线程组情况比较少&#xff0c;要是用到跨线程组&#xff0c;有个pros&#xff0c;用法和vars一样。 在setup线程组设置变量a&#xff0c;执行的时候&#xff0c;jmeter会先执行…

第二证券:转股溢价率是什么意思?高好还是低好?

转股溢价率是指可转债在商场上的交易价格相对于其转股价值的溢价份额&#xff0c;能够用来衡量投资者为取得将债券转换为股票权力而付出的额定金额&#xff0c;是可转债的重要指标。 转股溢价率的核算公式为&#xff1a;溢价率&#xff1d;&#xff08;转债价格-转股价值&…

MySql性能调优01-[数据结构和索引]

数据结构和索引 什么是索引索引的种类常见索引数据结构和区别二叉树 红黑树 什么是索引 索引的种类 在Mysql中索引是在存储引擎层实现的&#xff0c;而不是在服务层实现的 按数据结构分&#xff1a;Btree索引、Hash索引、Full-text索引按存储结构分&#xff1a;聚簇索引、非聚…

【Python百日进阶-Web开发-Peewee】Day296 - 查询示例(五)聚合2、递归

文章目录 14.6.13 列出每个指定设施的预订总小时数 List the total hours booked per named facility14.6.14 列出每位会员在 2012 年 9 月 1 日之后的首次预订 List each member’s first booking after September 1st 201214.6.15 生成成员名称列表,每行包含成员总数 Produc…

闲话银行家舍入法,以及在程序中如何实现

前言 相信对于四舍五入的舍入法&#xff0c;大家都耳熟能详&#xff0c;但对于银行家舍入法&#xff0c;可能就会比较少接触了&#xff01; 可是在金融界&#xff0c;银行家舍入法可是大名鼎鼎的主角之一&#xff0c;主要应用于金融领域和涉及货币计算的场合。 那么&#xf…

异步轮询 Web API 的实现与 C# 示例

在现代软件开发中&#xff0c;异步轮询 Web API 是一种常见的做法&#xff0c;尤其是在需要定期从服务器获取数据更新的场景下。C# 作为一种功能强大的编程语言&#xff0c;提供了丰富的异步编程支持&#xff0c;使得实现异步轮询变得相对简单。本文将介绍如何使用 C# 快速实现…

Google Guava Cache简介

目录 简介和Redis的区别 简介 Google Guava 是一个开源的 Java 库&#xff0c;其中提供了一系列强大的工具来简化 Java 开发工作。其中&#xff0c;Guava Cache 组件提供了一个内存缓存的实现&#xff0c;可以显著提高应用程序的性能。这是一个高效且灵活的缓存解决方案&#…

conda 创建新的虚拟环境报错

conda 创建新的虚拟环境报错 CorruptedEnvironmentError: The target environment has been corrupted. Corrupted environments most commonly occur when the conda process is force-terminated while in an unlink-link transaction. 把错误的文件删除如A.json 再重新运行…

JavaWeb-js(4)

js事件 在前端页面中&#xff0c;js程序大多数是由事件来驱动的&#xff0c;当触发某些事件的时候&#xff0c;可以使用js负责响应。 js事件由三部分组成: 事件源——》指的是被触发的对象; 事件类型——》如何触发的事件&#xff0c;如:鼠标单击、双击、键盘操作等;…

钓鱼网站制作-克隆163企业邮箱

这里克隆163企业邮箱比较费劲&#xff0c;和之前的还不一样&#xff0c;这个克隆的目录比较多&#xff0c;发现好多工具都克隆不全&#xff0c;要不就是缺少图片要不就是缺少功能 首先效果 可以看到成功记录账户密码&#xff0c;接下来再来伪装到域名 这里克隆网站使用神器 …

stm32使用单通道规则组ADC

Driver_ADC.c 如果需要关闭adc转换&#xff0c;只需要设置CNT&#xff0c;将其置为0&#xff0c;后面再转换一次就停止了。 #include "Driver_ADC.h"void Driver_ADC1_Init(void) {/* 1. 时钟配置 *//* 1.1 adc时钟 */RCC->APB2ENR | RCC_APB2ENR_ADC1EN;RCC-&g…

bev 之 fastBEV

前面我们提到bev 之 LSS, 知道视觉的BEV方案的主要痛点在于: 1、depth 的预测 2、图像特征到BEV特征之间的视图变换消耗大量计算 LSS 为什么需要D维深度 占据大量消耗的原因是LSS 对每个图像特征点引入深度D&#xff0c;即假设每个像素上存在可能的D维深度。也就是假设不同像…