目录
通讯接口背景知识
两种通讯方式对比
通讯方式 | 并行通讯 | 串行通讯 |
传输原理 | 数据各个位同时传输 | 数据按位顺序传输 |
优点 | 速度快 | 占用引脚资源少 |
缺点 | 占用引脚资源多 | 速度相对较慢 |
串口通讯
按照数据传送方向分为: 单工、半双工、全双工
- 单工:数据传输只支持数据在一个方向上传输
- 半双工:允许数据在两个方向上传输,但两个方向不可同时进行传输
- 全双工:允许数据在两个方向传输,并两个方向可同时进行传输(需要独立的发送端及接收端)
按照串行通信通信方式分为:同步通信、异步通信
- 同步通信:带时钟同步信号传输(例:SPI、IIC 通信)
解析:除数据线外,还会有时钟线,数据传输受时钟线限制
- 异步通信:不带时钟同步信号 (例:UART,单总线)
解析:由于没有时钟线,故通信双方必须约定好波特率(数据传输速度)进行数据解析
常见的串行通信接口
通信标准 | 引脚说明 | 通信方式 | 通信方向 |
UART | TXD:发送端 RXD:接收断 GND:公共地 | 异步通信 | 全双工 |
单总线 (1-wire) | DQ:发送/接收端 | 异步通讯 | 半双工 |
SPI | SCK:同步时钟 MISO:主机输入,从机输出 MOSI:主机输出,从机输入 | 同步通讯 | 全双工 |
IIC | SCL:同步时钟 SDA:数据输入/输出端 | 同步通信 | 半双工 |
STM32串口通信基础
STM32的串口通信接口
- UART(Universal Asynchronous Receiver/Transmitter):通用异步收发器
- USART(~ Synchronous/Asynchronous ~):通用同步异步收发器
UART异步通信方式引脚连接方法
RXD:数据输入引脚,用于数据接收
TXD:数据发送引脚,用于数据发送
注:接线时,应RXD接TXD,TXD接RXD,这样才可进行数据接收和发送
UART异步通讯方式特点
- 全双工异步通信
- 发送和接收公用可编程波特率
- 可编程的数据长度(8位或9位)
- 可配置的停止位
- 可配置的使用DMA多缓冲器通信
- 单独的发送器和接收器使能位
- 检测标志:接收缓冲器、发送缓冲器、传输结束标志
- 多个标志的中断源,可触发中断
- 具有校验控制,四个错误检测标志
串口通信过程
- 数据发送过程:MCU——>输出数据缓冲器——>串行输出移位寄存器——>串行输出 ——> 外部设备
- 数据接收过程:MCU<——输入数据缓冲器<——串行输入移位寄存器<——串行输入 <—— 外部设备
串口异步通讯需要定义的参数
- 起始位、数据位、奇偶校验位、停止位、波特率设置
STM32常用串口寄存器
常用三种串口相关寄存器
- USART_SR 状态寄存器:存储标志位状态,以确保串口通信正常进行
- USART_DR 数据寄存器:如果接收数据就读此寄存器,如果发送数据就写此寄存器
- USART_BBR 波特率寄存器:高十二位为整数部分,低四位为小数部分
波特率计算方法:
波特率=时钟/(波特率寄存器数值*16),故要设置某波特率,算出其波特率计算器数值,并写入寄存器即可设置成功
- USART_CR1 控制寄存器:使能位、校验的选择、字节长短选择等
注:如果用库函数写代码只需了解即可,其实本人对寄存器里面的很多位也不是很了解,如果有大佬看到望指点
STM32 常用库函数
控制SR寄存器的库函数
获取状态标志位:
FlagStatus USART_GetFlagStatus(); //获取状态标志位
清除状态标志位:
void USART_ClearFlag();//清除状态标志位
获取中断状态标志位:
ITStatus USART_GetITStatus();//获取中断状态标志位
清除中断状态标志位:
void USART_ClearITPendingBit();//清除中断状态标志位
控制DR寄存器的库函数
发送数据到串口:
void USART_SendData();//从TDR寄存器种写数据,并发送到串口
读取接收到的数据:
uint16_t USART_ReceiveData();//接收串口发来的数据,读出RDR寄存器中的数据
控制BBR与CR1寄存器的库函数
初始化串口:
void USART_Init();//串口初始化:波特率,字节长度,停止位等
使能串口:
void USART_Cmd();//使能串口
使能相关中断:
void USART_ITConfig();//使能相关中断
串口应用
串口配置基本步骤
1、串口时钟使能,GPIO时钟使能
2、GPIO端口模式设置
3、NVIC中断优先级设置
4、串口参数初始化
5、开启串口使能
6、编写接收中断处理函数(只有接收到数据,接收中断才会开启)
7、串口数据收发
使用printf发送字符串至串口
- 与C语言使用方法与格式相同,只是会发送字符串到上位机
正点原子接收并发回消息程序讲解
定义变量
u8 USART_RX_BUF[USART_REC_LEN];
/*接收上位机发送的字节缓存至数组,数组最大字节位USART_REC_LEN*/
u16 USART_RX_STA=0;
/*设置接收状态标记位*/
/*其有16位,15,14位用来判断是否接收完成,分别为0x0d(ASC码值为换行),0x0a(ASC码值为回车)*/
/*0~13位记录缓存字节个数*/
接收中断
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) // 判断接收中断是否开启
{
Res =USART_ReceiveData(USART1); //接收此次发来的8位数据
if((USART_RX_STA&0x8000)==0)//判断上一次接收的是否为换行
{
if(USART_RX_STA&0x4000)//判断上一次接收的是否为回车
{
if(Res!=0x0a)USART_RX_STA=0;//判断这次接收的是否为换行
else USART_RX_STA|=0x8000; //是换行,将接收标志位最高位置一
}
else //上一次接收的不是回车
{
if(Res==0x0d)USART_RX_STA|=0x4000;//判断这次接收的是不是回车,是回车将14位置一
else//这次接收的不是回车
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res;//接收数据写入缓冲数组
/*0x3fff=0011_1111_1111_1111 与 标志位相与 可得字节长度,因前两位为接收标志位*/
USART_RX_STA++;//字节长度加一
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;大于限定字节重新接收
}
}
}
}
接收完成
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//取出字节长度
printf("\r\你要发送的消息是:\r\n\r\n");//printf的使用
for(t=0;t<len;t++)
{
USART_SendData(USART1, USART_RX_BUF[t]);//从缓冲区逐个取出并发送
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//发送完成标志位
}
printf("\r\n\r\n");//
USART_RX_STA=0;//状态清零
}