一、通信接口背景知识
1、处理器与外部设备通信的两种方式
并行通信:
传输原理:数据各个位同时传输
优点:速度快
缺点:占用引脚资源多
(例如:A向B进行传输时一次性可以用8个引脚进行传输,效率高速度快,但是占用引脚多)
串行通信:
传输原理:数据按位顺序传输
优点:占用引脚资源少
缺点:速度相对较慢
(例如:A向B进行传输时要用8个引脚,但每次只用一个引脚,8个引脚逐个使用,占用引脚少)
2、串行通信
按照数据传送方向,分为:
单工:数据传输只支持数据在一个方向上传输
半双工:允许数据在两个方向上传输,但是在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信
全双工:允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接受设备都有独立的接受和发送能力
串行通信的通信方式:
同步通信:带时钟同步信号传输。SPI,IIC通信接口
异步通信:不带时钟同步信号。UART(通用异步收发器),单总线
二、STM32串口通信基础
USART:通用同步异步收发器(同步有时钟信号)
UART:通用异步收发器(异步无时钟信号)
UART异步通信方式引脚连接方法
-RXD:数据输入引脚。数据接收
-TXD:数据发送引脚。数据发送
图片总结:通信方式:同步通信一定有同步时钟,异步通信无同步时钟。通信方向:全双工的发送和接收都有独立的引脚。半双工只占用一个通信引脚(可以发送和接收)。
UART异步通信方式特点:
·全双工异步通信
·支持小数波特率发生器系统,提供精确的波特率。(通信双方事先约定好一种速度即波特率)
·可配置的16倍过采样或8倍过采样,为速度容差与时钟容差的灵活配置提供了可能。(F1与F4UART唯一区别,一般采用16倍过采样)
·可配置的停止位(支持1或者2位停止位)
·可编程的数据字长度(8位或者9位)
·可配置的使用DMA多缓冲器通信
·单独的发送器和接收器使能位
·检测标志:接收缓冲器;发送缓冲器空;传输结束标志;(STM32与外部设备进行通信的时候接收到一个数据后会有相应的标志)
·多个带标志的中断源,触发中断(串行通信可以发送接收数据,接收到一个数据可以触发一个中断)
·其他:校验控制、四个错误检测标志
STM32串口通信过程
STM32串口异步通信需要定义的参数
1、起始位
2、数据位(8位或9位)
3、奇偶校验位(第9位)
4、停止位(1、15、2位)
5、波特率设置
理解:
1:(事先约定)A与B通信,空前状态是1,而起始位是0(低电位)证明通信已经开始了
2:数据位(八位到九位)
3:例如前八位中有五个1,三个0,而第九位是奇偶校验位(假设偶),则第九位为1,同前八位组成六个1
4:(事先约定)约定1或0,然后停止,进行下一个数据帧
5:通信双方事先约定好波特率
三、实例编写
1、常用的串口相关寄存器:
·USART_SR状态寄存器(用0~9位,每一位是一个状态标志位)
·USART_DR数据寄存器(用0~8位,发送接收数据时使用)
·USART_BRR波特率寄存器(用0~3位:USARTDIV的小数部分、4~15位:USARTDIV的整数部分)
库函数调用:
状态寄存器调用函数:
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx,uint16_t USART_FLAG);
数据寄存器调用函数:
void USART_SendData(USART_TypeDef*USARTx,uint16_t Data);
uint16_t USART_ReceiveData(USART_TypeDef*USARTx);
波特率寄存器调用函数:
void USART_Init(USART_TypeDef*USARTx,USART_InitTypeDef*USART_InitStruct);
【波特率的计算方法:fPCLKx(x=1,2)/(USARTDIV*16) OVER8=0】
fPCLKx是给串口时钟(PCLK1用于USART2~5,PCLK2用于USART1和USART6)
一般注重求USARTDIV的值,易知波特率、PCLKx时钟。
常见USARTDIV的结果是小数,将USARTDIV转化位波特率寄存器时,整数部分写入4~15位,小数*16写入0~3位
2、串口配置一般步骤
串口时钟使能:RCC_APBxPeriphClockCmd();
GPIO时钟使能:RCC_AHB1PeriphClockCmd();
引脚复用映射:GPIO_PinAFConfig();
GPIO端口模式设置:GPIO_Init();模式设置为GPIO_Mode_AF
串口参数初始化:USART_Init();
开启中断并且初始化NVIC:NVIC_Init();USART_ITConfig();
使能串口:USART_Cmd();
编写中断处理函数:USARTx_IRQHandler();
串口数据收发:void USART_SendData();//发送数据到串口,DR
uin16_t USART_ReceiveData();//接收数据,从DR读取接收到的数据
串口传输状态获取:FlagStatus USART_GetFlagStatus(); void USART_ClearITPendingBit();
3、代码
void My_Usart1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//GPIOA使能时钟
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);//PA9、PA10映射到串口1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//最重要的是将模式设为复用
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//串口初始化
USART_InitStructure.USART_BaudRate=115200;
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//硬件流控制
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_InitStructure.USART_Parity=USART_Parity_No;//奇偶校验
USART_InitStructure.USART_StopBits=USART_StopBits_1;//停止位
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长
USART_Init(USART1,&USART_InitStructure);
USART_Cmd(USART1,ENABLE);
//使能中断
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
}
//中断服务函数
void USART1_IRQHandler(void)
{
u8 res;
//判断中断发生
if(USART_GetITStatus(USART1,USART_IT_RXNE)){
res=USART_ReceiveData(USART1);
USART_SendData(USART1,res);
}
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
My_Usart1_Init();
while(1);
}
串口通信