一、串行通信简介
CPU与外围设备之间的信息交换称为通信。基本的通信方式有并行通信和串行通信两种。STM32单片机提供了功能强大的串行通信模块,即通用同步/异步收发器(USART)。
1.串行通信
串行通信是数据字节一位一位地依次传送的通信方式。串行通信的速度慢,但占用的传输线条数少,适用于远距离的数据传送。
从硬件上看,串行通信有单工、半双工和全双工通信。
- 单工通信就是数据只允许向一个方向进行传送。
- 半双工通信就是数据允许向两个方向进行传送,但一个设备的传送和接收过程不能同时进行。
- 全双工通信就是数据允许向两个方向进行传送,且一个设备的传送和接收过程可以同时进行。
2.串行异步通信和串行同步通信
串行通信按照串行数据的时钟控制方式分为异步通信和同步通信。
串行异步通信是一种常用的串行通信方式,一次通信传送一个字符帧。在发送字符时,发送的字符之间的时间间隔可以是任意的,接收端时刻做好接受的准备。串行异步通信的优点是通信设备简单、价格低廉,但因为具有起始位和停止位,所以传输效率较低。串行异步通信只适用于点对点。
串行同步通信要求在进行通信前先建立同步,发送频率和接收方的接收频率要同步。串行同步通信的传输速度较快,可用于点对多,多用于同一PCB上芯片级之间的通信。缺点是需要使用专用的时钟控制线来实现同步。
3.串行异步通信的数据传输形式
串行异步通信需要制定一些共同遵守的约定,其中最重要的是字长和波特率。
字长可以是8位或者9位,起始位为低电平,停止位为高电平,空闲帧全为1。发送和接收由一个共用的波特率发生器驱动。
波特率即数据的传送速率。在串行异步通信中,每秒钟传送的二进制数的位数称为波特率,单位是比特/秒(bit/s),或波特(baud)。波特率的倒数就是每一位的传送时间,称为位传送时间,单位为秒(s)。
二、STM32的USART
1.USART的特点
- 同步/异步全双工通信,低位先行。
- 可配置数据位长度(8位/9位)。
- 可配置停止位长度(0.5/1/1.5/2)。
- 可选的校验位(无校验/奇校验/偶校验)。
- 可配置波特率。
- 支持硬件流控制。
2.USART的结构
STM32有3~5个全双工的串行异步通信接口USART,简称串口。USART主要有发送引脚(RX)、接收引脚(TX)、清除发送(nCTS)、发送请求(nRTS)和发送器时钟输出(CK)等引脚来与外部设备相连,同时,其内部还包含了各种寄存器和功能模块等。
常用的引脚有RX发送引脚和TX接收引脚,使用这两个引脚,一般就可以实现双向通信。
3.USART的使用方式
三、USART的使用流程
STM32的USART一般使用异步通信方式,使用流程如下:
- 配置GPIO
- 配置USART
- 配置NVIC
- 编写中断服务函数(用于接收数据和进行其他操作)
- 发送数据
- 配置printf重定向(按需要选择配置或者不配置)
#include "stm32f10x.h" // Device header
/**********************************初始化USART1***********************************/
void Serial1_Init(void)
{
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA |RCC_APB2Periph_USART1,ENABLE );
//开启GPIO和USART1时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //配置发送引脚PA9
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU; //上拉输入
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; //配置接收引脚PA10
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=9600; //波特率,选择9600
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
//硬件流控制,不使用
USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx ; //配置为发送和接收模式
USART_InitStructure.USART_Parity=USART_Parity_No; //校验位,不适用
USART_InitStructure.USART_StopBits=USART_StopBits_1; //停止位,设1位
USART_InitStructure.USART_WordLength=USART_WordLength_8b; //数据位,设8位
USART_Init(USART1 ,&USART_InitStructure);
USART_ITConfig (USART1 ,USART_IT_RXNE ,ENABLE); //开启USART1的接收中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择优先级分组
NVIC_InitTypeDef NVIC_InitStructure; //配置NVIC,使用到中断都要配置
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);
USART_Cmd (USART1,ENABLE ); //使能USART1
}
/*********************************USART1中断服务函数*********************************/
void USART1_IRQHandler(void)
{
if(USART_GetITStatus (USART1,USART_IT_RXNE )==SET)
{
uint8_t value = 0;
value=USART_ReceiveData (USART1); //接收数据
//其他操作
USART_ClearITPendingBit (USART1,USART_IT_RXNE );
}
}
/*************************************发送数据***************************************/
USART_SendData(USART1, Byte); //发送数据的操作
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //等待发送完成
/*************************************printf重定向***********************************/
int fputc(int ch,FILE *f)
{
USART_SendData(USART1, ch); //发送数据的操作
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //等待发送完成
return ch;
}
//printf重定向到串口,需要在该文件#include <stdio.h>,作用是printf操作会将数据打印到串口