STM32的USART串口通信

Posted 可乐飞冰5399

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32的USART串口通信相关的知识,希望对你有一定的参考价值。

一、串口协议和RS-232标准

串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,设备之间通过少量数据信号线(一般是 8 根以下),地线以及控制信号线,按数据位形式一位一位地传输数据的通讯方式。而并行通讯一般是指使用 8、 16、 32 及 64 根或更多的数据线进行传输的通讯方式,可以同时传输多个数据位的数据,而串行通讯,同一时刻只能传输一个数据位的数据。

对于串口通讯协议,我们把它分为物理层和协议层。物理层规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。

1)物理层

串口通讯的物理层有很多标准及变种,其中RS-232 标准主要规定了信号的用途、通讯接口以及信号的电平标准。

使用 RS-232 标准的串口设备间常见的通讯结构图

在上面的通讯方式中,两个通讯设备的“DB9 接口”之间通过串口信号线建立起连接,串口信号线中使用“RS-232标准”传输数据信号。由于 RS-232电平标准的信号不能直接被控制器直接识别,所以这些信号会经过一个“电平转换芯片”转换成控制器能识别的“TTL 标准”的电平信号,才能实现通讯。串口通讯使用的电平标准可分为 TTL标准及 RS-232标准。


RS-232 与 TTL 电平标准下表示同一个信号

CH340 是一个USB 总线的转接芯片,实现USB 转串口、USB 转IrDA 红外或者USB 转打印口。为了增加串口通讯的远距离传输及抗干扰能力,RS-232标准使用-15V 表示逻辑 1, +15V 表示逻辑 0。常常会使用 MH340芯片对 USB/TTL与RS-232电平的信号进行转换。

CH340工作原理图

2)协议层

串口通讯的数据包由发送设备通过自身的 TXD 接口传输到接收设备的 RXD 接口。在串口通讯的协议层中,规定了数据包的内容,它由启始位、主体数据、校验位以及停止位组成,通讯双方的数据包格式要约定一致才能正常收发数据。

串口数据包的基本组成图

数据包的起始信号由一个逻辑0的数据位表示,而数据包的停止信号可由0.5、 1、 1.5或2个逻辑1的数据位表示。在数据包的起始位之后紧接着的就是要传输的据的长度常被约定为 5、 6、 7 或 8 位长。在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。
通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter)是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。 USART 就是对传输数据时的传输参数有具体规定。

USART 功能框图

①功能引脚②数据寄存器③控制器(发送器和接收器)④小数波特率生成
还有校验控制、中断控制模块未在图中框出。

二、一个STM32的USART串口通讯程序

1)代码编写

标准库函数对每个外设都建立了一个初始化结构体,结构体成员用于设置外设工作参数,这些设定参数将会设置外设相应的寄存器,达到配置外设工作环境的目的,充分利用他们将大大减少编程的工作量。

USART 初始化结构体

typedef struct {
uint32_t USART_BaudRate; // 波特率
uint16_t USART_WordLength; // 字长
uint16_t USART_StopBits; // 停止位
uint16_t USART_Parity; // 校验位
uint16_t USART_Mode; // USART 模式
uint16_t USART_HardwareFlowControl; // 硬件流控制
} USART_InitTypeDef;

USART 时钟初始化结构体

typedef struct {
uint16_t USART_Clock; // 时钟使能控制
uint16_t USART_CPOL; // 时钟极性
uint16_t USART_CPHA; // 时钟相位
uint16_t USART_LastBit; // 最尾位时钟脉冲
} USART_ClockInitTypeDef;

这里将以查询方式完成一个串口通信:
STM32系统给上位机(win10)连续发送“hello windows!”。win10采用“串口助手”工具接收,设置波特率为115200,1位停止位,无校验位;

我们首先需要完成 USART 初始化配置, 包括 GPIO 配置,USART 配置等,接下来就可以把数据发送给串口调试助手了。

新建工程,把STM32标准库添加进去,具体可参考我的上篇文章。在USER下新建bsp_usart.c和bsp _usart.h,用来存放 USART 的驱动程序及相关宏定义。

这里主要介绍bsp_usart.c中的几个主要函数。

bsp_usart.c

/***************** 初始化 **********************/
void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); // 打开串口 GPIO 的时钟
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);// 打开串口外设的时钟
// 将 USART Tx 的 GPIO 配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
// 将 USART Rx 的 GPIO 配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
//设置串口参数
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;// 配置波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;// 配置帧数据字长
USART_InitStructure.USART_StopBits = USART_StopBits_1;// 配置停止位 USART_InitStructure.USART_Parity = USART_Parity_No ;// 配置校验位
USART_InitStructure.USART_Mode = USART_Mode_Tx;// 配置工作模式为发送数据
USART_Init(DEBUG_USARTx, &USART_InitStructure);// 完成串口的初始化配置
USART_Cmd(DEBUG_USARTx, ENABLE);// 使能串口
}

使用 GPIO 之前都需要初始化配置它,并且还要添加特殊设置,我们在初始化时需要把它的模式设置为复用功能。 这里把串口的 Tx 引脚配置为复用推挽输出。

/***************** 发送一个字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
/* 发送一个字节数据到 USART */
USART_SendData(pUSARTx,ch);

/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}

/***************** 发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
unsigned int k=0;
do {
Usart_SendByte( pUSARTx, *(str + k) );
 k++;
} while (*(str + k)!='\\0');

/* 等待发送完成 */
while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) {
}
}

USART_GetFlagStatus 函数来获取 USART 事件标志来实现发送完成功能等待,它接收两个参数,一个是 USART,一个是事件标志。这里我们循环检测发送数据寄存器为空这个标志,保证数据发送完成后才退出函数。

main.c

#include "stm32f10x.h"
#include "bsp_usart.h"
void delay(uint32_t count)//延迟函数
{
	while(count--);
}
int main(void)
{	
   //初始化USART ,配置模式为115200 8-N-1
  USART_Config();
  while(1)
	{	
		Usart_SendString( DEBUG_USARTx,"hello windows\\n");
		//发送一个字符串
		delay(5000000);//延时发送
	}	
}

2)下载验证

点击魔法棒,点击Debug,勾选下面框出来的地方。


将生成的hex文件烧录进STM32F103c8芯片中,注意此时Boot0要置零,Boot1不变。否则系统将收不到数据,我就是一直卡在这,一直没有现象。打开串口调试助手,点击更多串口设置,配置模式为115200 8-N-1。点击打开串口,最终结果如下图。

三、观察管脚的时序波形

将USART1_SR拖进逻辑分析仪

设置波形的展示类型为Bit

点击全速运行,观察到下面的结果,串口输出波形是高低电平的连续转换。

要启动数据发送,需要先使能USART_CR1的TE位,则发送移位寄存器的数据会在TX引脚输出,从低位开始发送,在异步模式中,一个字符帧包含三部分:起始位+数据帧+停止位。中间部分的数据帧则是我们要发送的8位或9位数据。当使能TE位后,发送器开始会先发送一个空闲帧,然后往USART_DR写入要发送的数据。发送完成后,等待状态寄存器(USART_SR)的TC位置1后,则代表数据传输完成。串口输出的时序波形符合代码的逻辑。

四、总结

了解了串口协议以及这其中的原理后,才发现串口通信并不是很难。本文的串口通信串口仅涉及了发数据,在收数据上的功能还未完整,我会继续努力。也欢迎各位小伙伴在评论区留言或私聊我指出文章中的不足之处。

五、参考资料

野火STM32F103C8T6核心板资料下载
STM32的USART窗口通讯程序——串口通讯

以上是关于STM32的USART串口通信的主要内容,如果未能解决你的问题,请参考以下文章

STM32USART串口通信

16 . USART 串口通信实验

16 . USART 串口通信实验

16 . USART 串口通信实验

stm32串口通信

STM32串口通讯程序