串口通信
定义:
串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式,如I2C通信、SPI通信、USART通信、EEPROM通信等。
分类:
串行通信:数据按位顺序依次传输,如8个数据位依次传输,速度慢,但占用引脚资源少
按照数据传送方向分为:
- 单工:数据传输只支持数据在一个方向上传输。(只收不发或者只发不收,模式固定)
- 单双工:允许数据在两个方向上传输,但是在某一时刻,只允许数据在一个方向上传输。(能发能收,但不能同时进行)
- 全双工:允许数据同时在两个方向上传输。(能发能收,且能同时进行)
按照通信的方式可分为:
- 同步通信:带时钟同步信号传输,如SPI、IIC通信等
- 异步通信:不带时钟同步信号,如UART(通用异步收发器)、单总线等。
并行通信:数据各个位同时传输,如8个数据位同时传输,占用引脚资源慢,但速度快。
常见串口通信接口
硬件电路
- 简单双向串口通信有两根通信线(发送端TX和接收端RX)
- TX与RX要交叉连接
- 当只需单向的数据传输时,可以只接一根通信线
- 当电平标准不一致时,需要加电平转换芯片
串行通信协议
- 波特率:串口通信的速率
- 起始位:标志一个数据帧的开始,固定为低电平
- 数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行
- 校验位:用于数据验证,根据数据位计算得来
- 停止位:用于数据帧间隔,固定为高电平
USART
USART(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步收发器
USART是STM32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送出去,也可自动接收RX引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里
- 自带波特率发生器,最高达4.5Mbits/s
- 可配置数据位长度(8/9)、停止位长度(0.5/1/1.5/2)
- 可选校验位(无校验/奇校验/偶校验)
- 支持同步模式、硬件流控制、DMA、智能卡、IrDA、LIN
- STM32F103C8T6 USART资源: USART1、 USART2、 USART3
基本结构
数据帧
九位数据帧可以选择配置校验位(或者选择不配),八位数据帧不能配置校验位。
数据采样
一个字节一共十六次采样
如果该序列不完整,那么接收端将退出起始位侦测并回到空闲状态(不设置标志位)等待下降沿。
如果3
个采样点都为
’0’(
在第
3
、
5
、
7
位的第一次采样,和在第
8
、
9
、
10
的第二次采样都为
’0’)
, 则确认收到起始位,这时设置RXNE
标志位,如果
RXNEIE=1
,则产生中断。
如果两次
3
个采样点上仅有
2
个是
’0’(
第
3
、
5
、
7
位的采样点和第
8
、
9
、
10
位的采样点
)
,那么起始 位仍然是有效的,但是会设置NE
噪声标志位。如果不能满足这个条件,则中止起始位的侦测过
程,接收器会回到空闲状态
(
不设置标志位
)
。
如果有一次
3
个采样点上仅有
2
个是
’0’(
第
3
、
5
、
7
位的采样点或第
8
、
9
、
10
位的采样点
)
,那么起 始位仍然是有效的,但是会设置NE
噪声标志位。
奇偶校验位
因为在通信过程中易受到外部干扰而导致数据出现偏差,所以在有效数据之后增加了校验位来解决这个问题,校验方式需要配置,校验方式有奇校验、偶校验、0校验和1校验:
- 奇校验要求有效数据和校验位中“1”的个数为奇数;
- 偶校验则要求有效数据和校验位中“1”的个数为偶数;
- 0校验位则是校验位始终为0,在收到报文后,检测校验位是否为0;
- 1校验则是校验位始终为1,在收到报文后,检测校验位是否为1;
波特率计算
发送器和接收器的波特率由波特率寄存器BRR里的DIV确定
波特率 = f PCLK2/1 / (16 * DIV)
初始化代码
串口设置的一般步骤可以总结为如下几个步骤:
- 串口时钟使能 GPIO 时钟使能
- 串口复位
- GPIO 端口模式设置
- 串口参数初始化
- 开启中断 并且初始化 NVIC(如果需要开启中断才需要这个步骤)
- 使能串口
- 编写中断处理函数
/**
* 函 数:串口初始化
* 参 数:无
* 返 回 值:无
*/
void Serial_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //开启USART1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//将PA9引脚初始化为复用推挽输出
/*USART初始化*/
USART_InitTypeDef USART_InitStructure;
//定义结构体变量
USART_InitStructure.USART_BaudRate = 9600;
//波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//硬件流控制,不需要
USART_InitStructure.USART_Mode = USART_Mode_Tx;
//模式,选择为发送模式
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_Init,配置USART1
/*USART使能*/
USART_Cmd(USART1, ENABLE); //使能USART1,串口开始运行
}