文章目录
【 0. 通信的分类 】
根据不同的定义标准有以下不同的分类
-
常见串行通信接口
-
STM32的串行通信接口
UART:通用异步收发器(Universal Asynchronous Receiver / Transmitter)
USART:通用同步/异步收发器 (Universal Synchronous/Asynchronous Receiver / Transmitter)
(大容量STM32F10x系列芯片,包含3个USART和2个UART)
本文章只讲 UART。
【 1. UART 】
特点
- 全双工异步通信。
- 分数波特率发生器系统,提供精确的波特率。
发送和接受共用的可编程波特率,最高可达4.5Mbits/s。 - 可编程的数据字长度(8位或者9位)。
- 可配置的停止位(支持1或者2位停止位)。
- 可配置的使用DMA多缓冲器通信。
- 单独的发送器和接收器使能位。
- 检测标志:① 接受缓冲器 ②发送缓冲器空 ③传输结束标志。
- 多个带标志的中断源,触发中断。
- 其他:校验控制,四个错误检测标志。
引脚
引脚连接方法:
RXD(Receive External Data):数据输入引脚。
TXD(Transmit External Data):数据发送引脚。
【 2. 串口通信过程 】
【 3. 数据位 】
- 起始位
- 数据位(8位或者9位)
- 奇偶校验位(第9位)
- 停止位(1,15,2位)
【 4. 波特率 】
【 6. 相关寄存器 】
【 7. 相关函数 】
初始化串口
void USART_Init(); //串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能
使能串口
void USART_Cmd(); //使能串口
串口发送数据
void USART_SendData(); //发送数据到串口,DR
串口接收数据
uint16_t USART_ReceiveData(); //接受数据,从DR读取接受到的数据
获取状态标志位
FlagStatus USART_GetFlagStatus(); //获取状态标志位
清除状态标志位
void USART_ClearFlag(); //清除状态标志位
使能串口中断
void USART_ITConfig(); //使能相关中断
获取串口中断标志位
ITStatus USART_GetITStatus(); //获取中断状态标志位
清除串口中断标志位
void USART_ClearITPendingBit(); //清除中断状态标志位
标志位核心代码
内部程序要求,发送的字符是以回车换行结束(0x0D,0x0A)
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//上一次接收到的数据为0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始(0xod后应该是0x0a)
else USART_RX_STA|=0x8000; //接收完成了
}
else //上一次接收到的数据不是0x0d
{
if(Res==0x0d)USART_RX_STA|=0x4000; //这次接收到0x0d,标志位bit14置1
else //这次没接收到0x0d,接收到数据位
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; //存入缓冲区
USART_RX_STA++; //有效数据个数+1
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误(大于缓冲区预定长度),重新开始接收
}
}
}
}
【 8. 配置过程 】
- 使能串口时钟,使能GPIO时钟。
- 配置GPIO端口模式(查表得)。
- 串口参数初始化。
- 开启中断并且初始化NVIC。(如果需要开启中断才需要这个步骤)。
- 使能串口。
- 编写中断处理函数。(如果需要开启中断才需要这个步骤)。
【 9. 范例 】
电脑发送字符到STM32,STM32接收并返回给电脑
#include "stm32f10x.h"
void myUSART_InitTypeDef(void)
{
GPIO_InitTypeDef MyGPIOstruct;
USART_InitTypeDef MyUSARTstruct;
NVIC_InitTypeDef MyNVICstruct;
/************①使能相应时钟***********/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //GPIO 时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //串口时钟使能
/*************②初始化GPIO口模式(查表得)*******/
MyGPIOstruct.GPIO_Mode=GPIO_Mode_AF_PP; //GPIO模式配置Pin9, TXD
MyGPIOstruct.GPIO_Pin=GPIO_Pin_9;
MyGPIOstruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&MyGPIOstruct);
MyGPIOstruct.GPIO_Mode=GPIO_Mode_IN_FLOATING; //GPIO模式配置Pin10,RXD
MyGPIOstruct.GPIO_Pin=GPIO_Pin_10;
MyGPIOstruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&MyGPIOstruct);
/***********③初始化串口参数***************/
MyUSARTstruct.USART_BaudRate=115200; //波特率配置
MyUSARTstruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //不适用硬件流
MyUSARTstruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx; //发送和接收均使能
MyUSARTstruct.USART_Parity=USART_Parity_No; //不使用奇偶校验位
MyUSARTstruct.USART_StopBits=USART_StopBits_1; //一个停止位
MyUSARTstruct.USART_WordLength=USART_WordLength_8b; //8位字长
USART_Init(USART1,&MyUSARTstruct);
/************④中断配置******************/
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //开启接收中断,接收数据后执行中断函数
MyNVICstruct.NVIC_IRQChannel=USART1_IRQn; //串口1入口参数
MyNVICstruct.NVIC_IRQChannelCmd=ENABLE; //使能
MyNVICstruct.NVIC_IRQChannelPreemptionPriority=1; //设置抢占优先级
MyNVICstruct.NVIC_IRQChannelSubPriority=1; //设置响应优先级
NVIC_Init(&MyNVICstruct); //设置相应中断响应优先级和抢占优先级
/************⑤使能串口******************/
USART_Cmd(USART1,ENABLE); //使能串口1
}
/************⑥编写中断处理函数******************/
void USART1_IRQHandler(void)
{
u8 res1;
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)) //第二个参数确定中断类型,即接收中断
{
res1=USART_ReceiveData(USART1);
USART_SendData(USART1,res1);
}
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //系统优先级分组2
myUSART_InitTypeDef();
while(1);
}