一、基础知识:
串行通信的通信方式:
- 同步通信:带时钟同步信号的信息传输-SPI、IIC通信接口
- 异步通信:不带时钟同步信号的信息传输-UART(通用异步收发器)、单总线
STM32F4的串行通信接口
- UART-通用异步收发器
- USART-通用同步异步收发器
常见串行通信接口
通信标准 | 引脚说明 | 通信方式 | 通信方向 |
UART (通用异步收发器) | TXD:发送端 RXD:接受端 GND:公共地 | 异步通信 | 全双工 |
单总线 (1-wire) | DQ:发送/接受端 | 异步通信 | 半双工 |
SPI | SCK:同步时钟 MISO:主机输入,从机输出 MOSI:主机输出,从机输入 | 同步通信 | 全双工 |
I2C | SCL:同步时钟 SDA:数据输入/输出端 | 同步通信 | 半双工 |
STM32F4的通信引脚(适用于STM32F407ZGT6)
串口号 | RXD | TXD |
1 | PA10(PB7) | PA9(PB6) |
2 | PA3(PD6) | PA2(PD5) |
3 | PB11(PC11/PD9) | PB10(PC10/PD8) |
4 | PC11(PA1) | PC10(PA0) |
5 | PD2 | PC12 |
6 | PC7(PG9) | PC6(PG14) |
STM32F4异步通信方式特点:
- 全双工异步通信。
- 小数波特率发生器系统,提供精确的波特率。
- 可配置的16倍过采样或8倍过采样,因而为速度容差与时钟容差的灵活配置提供了可能。
- 可编程的数据字长度(8位或者9位);
- 可配置的停止位(支持1或者2位停止位);
- 可配置的使用DMA多缓冲器通信。
- 单独的发送器和接收器使能位。
- 检测标志:① 接受缓冲器 ②发送缓冲器空 ③传输结束标志
- 多个带标志的中断源。触发中断。
- 其他:校验控制,四个错误检测标志。
STM32F4串口通信过程:
二、STM32F4串口通信的基本设置:(时钟使能、IO口设置、波特率设置等)
正常模式下:需要RX和TX引脚,并作如下配置
- 发送或接收前保持线路空闲
- 数据(字长8位或9位),最低位在前
- 用于指示数据帧已经传输完成的0.5个、1个、1.5个、2个停止位
- 小数波特率发生器-带12位尾数和4位小数
- 状态寄存器-USART_SR
- 数据寄存器-USART_DR
- 波特率寄存器-USART_BRR
- 智能卡模式下的保护时间寄存器-USART_GTPR
同步模式下需要连接SCLK引脚:该引脚用于输出发送器的数据时钟,以便按照SPI主模式进行同步发送。
空闲字符:整个帧周期内电平均为1(停止位电平也为1)
停止字符:一个帧周期内接收到的电平均为0
发送和接收由通用波特率发生器驱动。发送器和接收器的使能位分别置1时将生成相应的发送时钟和接收时钟。
发送器:发送器可以发送8位或9位的数据字,具体取决于M位的状态。发送使能位TE置1时,发送移位寄存器的数据在TX引脚输出,相应的时钟脉冲在SCLK引脚输出。
字符发送:每个字符前都有一个起始位,其逻辑电平在一个周期内均为低电平,字符由可配置数量的停止位停止。
配置步骤:
- 使能USART-配置控制寄存器USART_CR1中的UE位为1(USART->CR1|=1<<13)
- 配置控制寄存器USART_CR1中的M位选择字长
- 配置控制寄存器USART_CR2中的STOP位选择停止位长度
- 如果需要进行多缓冲区通信则还需要配置USART_CR3中的DMA使能
- 配置波特率寄存器USART_BRR,设置数据的传输速率
- 将USART_CR1中的TE位置1以便在数据首次发送时发送一个空闲帧(USART->CR1|=1<<3)
- 在USART_DR数据寄存器中写入要发送的数据(该操作将清零TXE位-该位为1则说明数据寄存器中的数据已经传输到了移位寄存器中,并开始一位一位的通过TX引脚向外部传输,此时USART_DR寄存器中可以开始写入下一个数据而不会覆盖之前的数据。如果移位寄存器中的数据发送完成且TXE位为1则TC为会置1,表明一帧数据已传输完成),每个单缓冲模式下的发送数据都需要这个步骤重复
接收器:USART可以接收8位或9位的数据
起始位检测:16倍或8倍过采样时,起始位检测序列相同。在USRAT中检测到特定序列的采样时会检测到起始位。
字符接收:USART接收期间,首先通过RX引脚移入数据的最低有效位
配置步骤:
- 使能USART-配置控制寄存器USART_CR1中的UE位为1(USART->CR1|=1<<13)
- 配置控制寄存器USART_CR1中的M位确定字长
- 配置控制寄存器USART_CR2中的STOP位选择停止位长度
- 如果需要进行多缓冲区通信则还需要配置USART_CR3中的DMA使能
- 配置波特率寄存器USART_BRR,设置数据的传输速率
- 将USART_CR1中的RE位置1,之后接收器开始搜索起始位
- 如果接收到的数据已经由移位寄存器传输到了USART_DR中则状态寄存器USART_SR中的RXNE位会被置1,
小数波特率生成:对USARTDIV的尾数值和小数值进行编程时,接收器和发送器(RX和TX)的波特率均设置为相同值
公式一:适用于标准USART(包括SPI模式)的波特率
公式二:适用于智能卡、LIN和IrDA模式下的波特率
USARTDIV是一个存放在USART_BRR寄存器中的无符号定点数
- 当OVER8=0时是16倍过采样,小数编码部分为4位
- 当OVER8=1时是8倍过采样,小数编码部分为3位
串口模式配置:
USART模式 | USART1 | USART2 | USART3 | USART4 | USART5 | USART6 |
异步模式 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
硬件流模式 | 支持 | 支持 | 支持 | 不支持 | 不支持 | 支持 |
多缓冲区通信 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
多处理器通信 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
同步 | 支持 | 支持 | 支持 | 不支持 | 不支持 | 支持 |
智能卡 | 支持 | 支持 | 支持 | 不支持 | 不支持 | 支持 |
半双工 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
IrDA | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
LIN | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
串口通信的实例设置:
- 串口时钟使能:
串口作为STM32F4的一个外设,其时钟由外设时钟使能寄存器控制
串口号 | 时钟寄存器 | 使能命令 |
USART1 | RCC_APB2ENR | RCC->APB2ENR|=1<<4 |
USART2 | RCC_APB1ENR | RCC->APB1ENR|=1<<17 |
USART3 | RCC_APB1ENR | RCC->APB1ENR|=1<<18 |
USART4 | RCC_APB1ENR | RCC->APB1ENR|=1<<19 |
USART5 | RCC_APB1ENR | RCC->APB1ENR|=1<<20 |
USART6 | RCC_APB2ENR | RCC->APB2ENR|=1<< 5 |
- 串口波特率设置:
通过给波特率寄存器赋值直接设置串口波特率,RCC->BRR=arr;
- 串口控制:
通过串口控制寄存器RCC_CR1对串口进行相应的设置:
UE:置1使能USART,该位为0则USART预分频器和输出将停止
M:设定字长(0:1起始位,8数据位,n停止位;1:1起始位,9数据位,n停止位;)
OVER:采样模式设置(0:16倍过采样;1:8倍过采样)
RXNEIE:
TE:发送使能位
RE:接收使能位
- 数据接收与发送:
STM32F4的发送与接收是通过数据寄存器USART_DR来实现的,是一个双寄存器包含了TDR和RDR
- 串口状态:
串口状态通过串口状态寄存器获得,RXNE(读数据寄存器非空)该位为1时说明数据已经被接收到了USART_DR中,可以读取出来。
TC(发送完成)该位被置1说明USART_DR中的数据已经发送完成了。
三、设置例程
void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV@OVER8=0
mantissa=temp; //得到整数部分
fraction=(temp-mantissa)*16; //得到小数部分@OVER8=0
mantissa<<=4;
mantissa+=fraction;
RCC->AHB1ENR|=1<<0; //使能PORTA口时钟
RCC->APB2ENR|=1<<4; //使能串口1时钟
GPIO_Set(GPIOA,PIN9|PIN10,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU);//PA9,PA10,复用功能,上拉输出
GPIO_AF_Set(GPIOA,9,7); //PA9,AF7
GPIO_AF_Set(GPIOA,10,7);//PA10,AF7
//波特率设置
USART1->BRR=mantissa; //波特率设置
USART1->CR1&=~(1<<15); //设置OVER8=0
USART1->CR1|=1<<3; //串口发送使能
#if EN_USART1_RX //如果使能了接收
//使能接收中断
USART1->CR1|=1<<2; //串口接收使能
USART1->CR1|=1<<5; //接收缓冲区非空中断使能
MY_NVIC_Init(3,3,USART1_IRQn,2);//组2,最低优先级
#endif
USART1->CR1|=1<<13; //串口使能
}