1. 基本介绍
1.1 简介
串口通信涉及USART。TX,RX,GND三根线就可以完成上位机和STM32的通信。 那么上位机和stm32是如何通过uart的通信的呢?换句话说,stm32怎么认识上位机发出的东西,上位机又怎么知道stm32发的是啥?
- 首先需要物理媒介
电气连接,上位机通过usb转为串口,当然转成的串口电平需要与stm32 电平匹配。 - 然后是协议
两点之间道路通了,需要有两者之间有特定的暗号,张三和李四才能保持长期稳定的沟通。这个暗号,就是串口协议。 - 最后是数据
有暗号了,张三李四就可以随便发东西了,比如张三送一箱芒果给李四,李四作为回礼送了一箱橙子。
简单的复习下串口协议。
1.2 串口协议
一个数据包,包括1位起始位,5-8位数据位,1位校验位,0.5-2个停止位,起始位一般为0,停止位的电平为1。 上位机一般采用串口助手与stm32进行通信。 串口助手的界面如下:串口助手底层的程序也是依照串口协议实现只不过通过软件界面显示出来。 你写的数据其实就是串口协议的0-7位的数据位,比如你写EB 90发送,上位机解析给EB加上衣服帽子,给90加上衣服帽子即起始校验停止,给发送出去,stm32接受到穿衣戴帽的EB,90后把衣服帽子丢掉还原成数据,进行其他处理。
1.3 通信过程
整个通信过程如下:
2.配置过程
2.1 引脚复用
GPIO有复用功能,每组GPIO(A-I)有16个引脚,引脚0-7为AFRL,8-15为AFRH,每一个理论上都可以选择AF0-AF15复用寄存器,实际上选择与端口复用特性有关。AF0是系统特性,复位完成后所有IO连接到AF0上。其他特性可选择,通过配置复用寄存器来将AF0与其他AF连接。
2.2 配置步骤
由于管脚复用,势必要同时使能GPIO时钟和外设时钟。 上面步骤中数据收发时,势必要涉及到1个问题: 上位机发给stm32的数据有了么,也就是stm32什么时候知道接收的数据?什么时候知道它返回给上位机数据完了? 从1.3可知,MCU内核是直接与数据缓冲寄存器沟通的,缓冲寄存器有没有数,MCU就知道了。这个有数通过SR寄存器的RXNE(置1表示数据被收到),没数通过TC(置1表示数据发送完)表示。 接下来的问题是,谁给这两个家伙置位? (有个问题是RXNE应该是与TXE对应,为何是与TC?TXE表示DR数据空了在移位寄存器里了,而TC表示移位寄存器里的东西都传完了,所以最终表示数据传完的是TC。) 根据配置步骤,下面来着重介绍几个函数。 1)GPIO初始化 注意要将GPIO的模式改为复用模式。
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
2)uart的初始化 初始化涉及的参数主要有波特率,数据位,停止位,校验位等。
USART_InitStructure.USART_BaudRate = bound;//波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
3)中断处理函数USART1_IRQHandler() 有以下事件可触发uart中断,最常用的是发送数据寄存器为空,接收数据寄存器不为空,对应的标志位位TXE,RXNE。只要DR里有数据,且中断不被打断,USART1_IRQHandler()就会一直执行。
2.3 例子
通过串口助手发送并返回发送的值。 1)在中断函数中,判断接收数据寄存器有值后读取,并且存入buffer中。
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
{
Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
if(USART_RX_STA==0)//接收未完成
{
USART_RX_BUF[RXnum]=Res;
RXnum++;
if(RXnum>4)
{
if(USART_RX_BUF[0]==0xEB&&USART_RX_BUF[3]==0x90)
{
USART_RX_STA=1; //接收正确,标志位置位
}else USART_RX_STA=0;
RXnum=0;
}
}
}
2)在主函数中,发送数据到上位机。当接收完成后,将接收的值发送出去,直到发送寄存器没有数据发送完成。
if(USART_RX_STA==1)
{
for(int i=0;i<5;i++)
{
USART_SendData(USART1,USART_RX_BUF[i]); //发送数据
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)!=SET);//发送未完成
}
USART_RX_STA=0;//发送完成标志位清零
}
结果如下:
参考文献
《STM32F4开发指南-库函数版本-V1.2》 《STM32F4xx中文参考手册》
|