一、串口通信

(一)串口协议和RS-232标准

1.串口通信协议

串口通信是指串口按位(bit)发送和接收字节。尽管比特字节(byte)的串行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。
串口通信协议是指规定了数据包的内容,内容包含了起始位、主体数据、校验位及停止位,双方需要约定一致的数据包格式才能正常收发数据的有关规范。在串口通信中,常用的协议包括RS-232、RS-422和RS-485

STM32的串口通信接口有两种,分别是:UART(通用异步收发器)、USART(通用同步异步收发器)。

引脚连接方式:
TXD <-----> RXD
RXD <-----> TXD
GND <----->GND

注:RXD:数据输入引脚,接受数据; TXD:数据发送引脚,数据发送;

对于两个芯片之间的连接,两个芯片GND共地,同时TXD和RXD交叉连接。这里的交叉连接的意思就是,芯片1的RxD连接芯片2的TXD,芯片2的RXD连接芯片1的TXD。这样,两个芯片之间就可以进行TTL电平通信了。

2.RS232串口标准

RS232串口标准,它的全名是“数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准”,该标准规定采用一个25个脚的DB-25连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。

下面以计算机和调制解调器之间的通信流程来说明RS-232串行通信原理。考虑当调制解调器处于应答方式下,计算机和调制解调器之间的RS-232信号间的交互关系和工作过程。假定调制解调器是全双工的,并以RS-232标准规范工作。

(1)初始状态时,RTS、CTS持续为ON,通过通信程序设置和监测RS232引线状态。在应答模式下,计算机中的软件一直监视着振铃指示(RI),等待RI发出ON信号。

(2)计算机上的通信程序在收到RI信号后,就开始通过振铃指示器ON/OFF变换的次数对振铃进行计数,当到达程设定的振铃次数时,通信程序就发生数据终端就绪(DTR)信号,强迫调制解调器进入摘机状态。

(3)等待2s后(FCC规定),调制解调器自动开始发送其应答载波。这时调制解调器发出调制解调器就绪(DSR)信号通知计算机:它已完成所有的准备工作并等待载波信号。

(4)在持续发出DTR信号期间,计算机软件监测DSR信号。当DSR信号变为ON时,计算机就知道调制解调器已准备数据链路的连接,计算机立即开始监测数据载波监测(CD)信号,以证实数据链路的存在。

(5)当源调制解调器的载波出现于电话线上时,应答调制解调器就发出CD信号。

(6)通过发送数据线(TD)和接收数据线(RD),开始全双工通信。在数据链路传输期间,计算机通过监测CD来确保数据链路的存在。

(7)通信任务一旦完成,计算机就禁止DTR,调制解调器用除去其载波音调、禁止CD和DSR来响应。随着链路被拆除,调制解调器就会返回初始状态。

RS-232串行通信距离较近时(<12m),可以用电缆线直接连接标准RS232端口,若距离较远需附加调制解调器( Mode),最为简单的且常用的是三线制接法,即地、接收数据、发送数据三脚相连。

3.RS232电平

RS232电平是指RS232串行通信接口中使用的电压级别。根据RS232标准,逻辑"1"表示为负电平(通常为-3V至-25V之间),而逻辑"0"表示为正电平(通常为+3V至+25V之间)。这种不对称的电平表示方式使得RS232能够在长距离和嘈杂环境下进行可靠通信。

RS232电平的特点包括:
①高电平范围为+3V至+25V,低电平范围为-3V至-25V。
②逻辑"1"使用负电平表示,逻辑"0"使用正电平表示。
③信号电平较高,能够抵抗干扰,并允许较长的传输距离(最长可达50英尺)。
④传输速率可达115200 bps(比特每秒)。

4.TTL电平

“TTL集成电路的全名是晶体管-晶体管逻辑集成电路(Transistor-Transistor Logic),主要有54/74系列标准TTL、高速型TTL(H-TTL)、低功耗型TTL(L-TTL)、肖特基型TTL(S-TTL)、低功耗肖特基型TTL(LS-TTL)五个系列。
标准TTL输入高电平最小2V,输出高电平最小2.4V,典型值3.4V;输入低电平最大0.8V,输出低电平最大0.4V,典型值0.2V。
S-TTL输入高电平最小2V,输出高电平最小Ⅰ类2.5V,Ⅱ、Ⅲ类2.7V,典型值3.4V;输入低电平最大0.8V,输出低电平最大0.5V。
LS-TTL输入高电平最小2V,输出高电平最小Ⅰ类2.5V,Ⅱ、Ⅲ类2.7V,典型值3.4V;输入低电平最大Ⅰ类0.7V,Ⅱ、Ⅲ类0.8V,输出低电平最大Ⅰ类0.4V,Ⅱ、Ⅲ类0.5V,典型值0.25V。

5.RS232电平和TTL电平的区别

TTL电平标准是 低电平为0,高电平为1(对地,标准数字电路逻辑)。
RS232电平标准 是 正电平为0,负电平为1(对地,正负3-15V皆可,甚至可以用高阻态)。

(1)电压

RS232电平的电压范围较高,正负电平分别为+3V至+25V和-3V至-25V。而TTL电平的电压范围较低,一般为0.2V至3.4V或0V至5V。因此,RS232电平较高,能够提供更大的信号幅度,使其具有较强的抗噪声和抗干扰能力。

(2)范围

RS232电平的电压范围较大,它可用于长距离通信,最长传输距离可达50英尺,甚至更远。而TTL电平的传输距离较短,一般不超过15米。因此,在需要长距离通信的场景中,RS232电平更为合适。

(3)接口电路

RS232电平使用差分信号传输,即发送线和接收线各自携带相反的信号。这种差分传输方式可以有效抑制共模干扰,并提高数据传输的可靠性。而TTL电平使用单端信号传输,只用一根线传输信号,外加一根参考线,也就是地线。那一根线分别携带不同的电平表示逻辑"1"和逻辑"0"。TTL电平的接口电路相对简单,成本较低。

总结:

RS232是一种串行通信接口标准,其电平表示为负电平和正电平,适用于长距离和抗干扰要求较高的通信环境。与之相比,TTL电平具有低电压范围和较短的传输距离,适用于短距离通信和成本敏感的应用。

(二)USB/TTL转232"模块的工作原理

串口数据收发流程:

发生/接收实现过程
串口发送串口应用发送数据→USB串口驱动获取数据→驱动将数据经过USB通道发送给USB串口设备→USB串口设备接收到数据通过串口发送
串口接收USB串口设备接收串口数据→将串口数据经过USB打包后上传给USB主机→USB串口驱动获取到通过USB上传的串口数据→驱动将数据保存在串口缓冲区提供给串口应用读取

以CH340芯片模块为例

CH340C模块

CH340C USB转TTL模块以CH340C芯片为核心,内部自带晶振,最高波特率可达2Mbps,软件兼容CH341驱动,过流保护,引出相应的通讯接口与电源接口,通讯接口带有指示灯指示工作状态,通讯稳定,体积小。

CH40C特点:
①全速USB驱动,兼容USB2.0
②硬件全双工串口,内置收发缓冲区
③支持波特率50bps~2Mbps
④输出TTL电平3.3V,兼容5V的IO电平

Symbol(符号)Type(类型)Deion(描述)
TXD)输出串行数据输出口
RXD)输入串行数据输入口
GND)电源接地引脚
3V电源3.3V电源输出引脚(最高250mA)
5V电源5V电源输出引脚(最高500mA)
DTS输出MODEM联络输出信号,请求发送
DTR输出MODEM联络输出信号,数据终端就绪

输入输出接口引脚均带有LED指示灯
电源接口引脚中,5V的接口引脚带有LED指示灯

在这里插入图片描述

二、使用HAL库进行STM32的USART串口通信

(一)UART常用函数

1.串口句柄

HAL库在结构上,对每个外设抽象成了一个称为ppp_HandleTypeDef的结构体,其中ppp就是每个外设的名字。所有的函数都是工作在ppp_HandleTypeDef指针之下。

例如,使用USART1时,可以定义USART初始化结构体变量(全局变量)huart。

UART_HandleTypeDef huart1;
huart1就被称为串口的句柄,它被贯穿整个USART收发的流程。
在这里插入图片描述

2.HAL_UART_Transmit

通过该函数可向串口寄存器 USART_DR 写入一个数据,当向该寄存器写数据的时候,串口就会自动发送。
函数原型:

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

huart:串口句柄
pData : 发送数据的地址
Size :发送数据的大小
Timeout :超时时间

3.HAL_UART_Receive_IT

作用是开启接收中断,同时设置接收的缓存区以及接收的数据量,并进入回调函数。
函数原型:

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

huart:USART句柄类型变量
pData:接收区缓冲区
Size:接收数目。

HAL_UART_Receive_IT函数是启动串口接收并且是中断接收,需要在初始化USART外设之后才能被调用。

在使能了USART接收中断之后,stm32在每次接收到一个字节数据之后,就会自动运行USART1_IRQHandler函数一次,但不会每次都运行一次HAL_UART_RxCpltCallback函数。只有当接收到数据字节数与在HAL_UART_Receive_IT函数设定的接收数目相等时才会运行一次接收完成回调函数。

注:一定要在进入while前写一次,为了开启中断(回调函数里面也会写的)

4.HAL_UART_RxCpltCallback

在判断到是接到串口数据并且数据数目达到设定值时就会调用接收完成回调函数HAL_UART_RxCpltCallback。这样我们在回调函数中实现我们的应用程序。

当CPU向串口发送数据,会产生接收中断,然后进入中断服务函数,调用回调函数,回调函数才是我们进行中断处理的地方

(二)程序编写

1.STM32CubeMX工程创建

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

2.编写程序

(1)STM32系统给windows11连续发送“hello windows!”

用keil打开刚刚生成的文件,找到main.c,并在main函数循环中使用 HAL_UART_Transmit函数发送hello windows!
在这里插入图片描述

 HAL_UART_Transmit(&huart1, "hello windows!\r\n",16,10); 
	  //延时
	  HAL_Delay(1000);

编译好后建议,使用ST-link在keil中直接下载,再按最小系统班的reset按钮,即可打开串口助手查看到发送的信息。
若是只使用ttl转串口(CH340),则需在下载时将boot0置1,以启动Bootloader来烧录程序;再将boot0置0,从flash中读取到代码,并且置0后也需要按reset键,此方法烧录运行程序十分麻烦,所以还是建议使用st-link进行烧录。
运行结果:
在这里插入图片描述

(2)在持续发送“hello windows!”的基础上,当上位机给stm32发送一个字符“#”后,stm32暂停发送“hello windows!”;发送一个字符“*”后,stm32继续发送
①定义全局变量

打开main.c文件,在void SystemClock_Config(void);之后定义全局变量

char c;//指令 0:停止  1:开始
char message[]="hello windows!\r\n";//输出信息
char tips[]="CommandError\r\n";//提示1
char tips1[]="Start.....\r\n";//提示2
char tips2[]="Stop......\r\n";//提示3
int flag=1;//标志 0:停止发送 1.开始发送
②开启中断

在进入while循环之前,写入HAL_UART_Receive_IT函数,以启动串口中断接收

  //设置接受中断
  HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);	
  //当flag为1时,每秒发送一次信息
  //当flag为0时,停止
③进行传输

在while循环中添加传输代码

if(flag==1){
			//发送信息
			HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF); 
			//延时
			HAL_Delay(1000);
		}
④重写中断处理函数

在main函数之后重写中断处理函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	
	//当输入的指令为#时,发送提示并改变flag
	if(c=='#'){
		flag=0;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF); 
	}
	
	//当输入的指令为*时,发送提示并改变flag
	else if(c=='*'){
		flag=1;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, strlen(tips1),0xFFFF); 
	}
	
	//当输入不存在指令时,发送提示并改变flag
	else {
		flag=0;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips, strlen(tips),0xFFFF); 
	}

	//重新设置中断
		HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);  
}

运行结果:
在这里插入图片描述

三、Keil中仿真逻辑分析仪查看程序时序

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

在这里插入图片描述
由此波形图可知:周期为1s,正确。
放大中间的竖线,可看到其中是一段段周期更小的波
在这里插入图片描述

通过查看peripherals中的USART1可看到其波特率实际为115107baud。
在这里插入图片描述

在这里插入图片描述

四、总结

在uart中断中:
①可以使用transmit函数来发送产生中断后需要信息,receive函数来接收中断指令,并且接收函数需要先定义,再回调使用。
②TTL转串口需要注意boot0或boot1的模式
在这里插入图片描述
③我在运行第二个程序时,在xcom中发送"#"会报CommandError的错误,说明最小系统板接受到的不是“#”,而更换为STC-ISP后,则能正确运行。而后又使用串口助手试了一下,也可以运行,个人推测xcom发送信息可能有问题。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

五、引用

【eefocus_3781508】rs232是什么电平 rs232电平和TTL电平的区别
【百度百科】RS-232
【百度百科】串口通信协议
【6¿6】嵌入式系统开发09——串口通信
【风间琉璃•】STM32G4之UART
【上下求索电子er】STM32基础:串口通信-轮询方式
【bit er】STM32—BOOT0和BOOT1

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐