一、通信接口背景知识
1.通信的两种方式: ①并行通信
- 传输原理:数据各个位同时传输。
- 优点:速度快
- 缺点:占用引脚资源多
②串行通信
- 传输原理:数据按位顺序传输。
- 优点:占用引脚资源少
- 缺点:速度相对较慢
2.串行通信 按照数据传送的方向,分为: - 单工:数据传输只支持数据在一个方向上传输
- 半双工:允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信
- 全双工:允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。
3.串行通信的通信方式
- 同步通信:带时钟同步信号传输
如SPI,IIC通信接口 - 异步通信:不带时钟同步信号
如UART(通用异步收发器),单总线 4.常见的串行通信接口:
通信标准 | 引脚说明 | 通信方式 | 通信方向 |
---|
UART(通用异步收发器) | TXD:发送端、RXD:接受端、GND:公共地 | 异步通信 | 全双工 | 单总线(1-wire) | DQ:发送/接受端 | 异步通信 | 半双工 | SPI | SCK:同步时钟、MISO:主机输入,从机输出、MOSI:主机输出,从机输入 | 同步通信 | 全双工 | I2C | SCL:同步时钟、SDA:数据输入/输出端 | 同步通信 | 半双工 |
二、STM32串口通信基础
1.STM32的串口通信接口
- UART:通用异步收发器
- USART:通用同步异步收发器
- 大容量STM32F10x系列芯片,包含3个USART和2个UART
2.UART异步通信方式引脚连接方法 - RXD:数据输入引脚。数据接受。
- TXD:数据发送引脚。数据发送。
串口号 | RXD | TXD |
---|
1 | PA10 | PA9 | 2 | PA3 | PA2 | 3 | PB11 | PB10 | 4 | PC11 | PC10 | 5 | PD2 | PC12 |
3.UART异步通信方式特点:
- 全双工异步通信。
- 分数波特率发生器系统,提供精确的波特率。
- -发送和接受共用的可编程波特率,最高可达4.5Mbits/s
- 可编程的数据字长度(8位或者9位);
- 可配置的停止位(支持1或者2位停止位);
- 可配置的使用DMA多缓冲器通信。
- 单独的发送器和接收器使能位。
- 检测标志:①接受缓冲器②发送缓冲器空③传输结束标志
- 多个带标志的中断源。触发中断。
- 其他:校验控制,四个错误检测标志。
4.串口通信过程 传输速度由波特率决定。 5.STM32串口异步通信需要定义的参数: ①起始位 ②数据位(8位或者9位) ③奇偶校验位(第9位)
- 奇校验:如前面传输了奇数个1,则奇偶校验位设置为0;如前面传输了偶数个1,则奇偶校验位设置为1。
- 偶校验:如前面传输了奇数个1,则奇偶校验位设置为1;如前面传输了偶数个1,则奇偶校验位设置为0。
④停止位(1,15,2位) ⑤波特率设置 6.USART框图
三、 STM32串口常用寄存器和库函数
1.常用的串口相关寄存器 ①USART_SR状态寄存器 ②USART_DR数据寄存器 ③USART_BRR波特率寄存器 ④USART_CRx控制寄存器 2.波特率计算方法
T
X
/
R
x
波特率
=
f
P
C
L
K
x
(
16
?
U
S
A
R
T
D
I
V
)
T_X/R_x波特率=\frac{f_{PCLK_x}}{(16*USARTDIV)}
TX?/Rx?波特率=(16?USARTDIV)fPCLKx???
- 上式中,
f
P
C
L
K
x
f_{PCLK_x}
fPCLKx??是给串口的时钟(PCLK1用于USART2、3、4、5,PCLK1用于USART1);USARTDIV是一个无符号定点数,我们只要得到USARTDIV的值,就可以得到串口波特率寄存器USART->BRR的值,反过来,我们得到USART->BRR的值,也可以推导出USARTDIV的值。但我们更关心的是如何从USARTDIV的值得到USART_BRR的值,因为一般我们知道的是波特率和
P
C
L
K
x
PCLK_x
PCLKx?的时钟,要求的就是USART_BRR的值。
- 假设我们的串口1要设置为115200的波特率,而PCLK2的时钟为72M。这样,我们根据上面的公式有:
U
S
A
R
T
D
I
V
=
72000000
/
(
115200
?
16
)
=
39.0625
USARTDIV=72000000/(115200*16)=39.0625
USARTDIV=72000000/(115200?16)=39.0625 那么得到: DIV_Fraction=16*0.0625=1=0X01(小数部分) DIV_Mantissa=39=0X27(整数部分) 这样,我们就得到了USART->BRR的值为0X0271。只要设置串口1的BRR寄存器值为0X0271就可以得到115200的波特率。 3.串口操作相关库函数(省略入口参数):
void USART_Init();
void USART_Cmd();
void USART_ITConfig();
void USART_SendData();
unit16_t USART_ReceiveData();
FlagStatus USART_GetFlagStatus();
void USART_ClearFlag();
ITStatus USART_GetITStatus();
void USART_ClearITPendingBit();
typedef struct
{
uint32_t USART_BaudRate;
uint16_t USART_WordLength;
uint16_t USART_StopBits;
uint16_t USART_Parity;
uint16_t USART_Mode;
uint16_t USART_HardwareFlowControl
} USART_InitTypeDef;
4.串口配置的一般步骤 ①串口时钟使能,GPIO时钟使能
RCC_APB2PeriphClockCmd();
②串口复位
USART_DeInit();
③GPIO模式设置
GPIO_Init();
注意:需要查中文参考手册看设置为什么模式 (8.1.11外设的GPIO配置)
④串口参数初始化
USART_Init();
⑤开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)
NVIC_Init();
USART_ITConfig();
⑥使能串口
USART_Cmd();
⑦编写中断处理函数
USARTx_IRQHandler();
⑧串口数据收发
void USART_SendData();
unit16_t USART_ReceiveData();
⑨串口传输状态获取
FlagStatus USART_GetFlagStatus(USART_Typedef*USARTx,unit16_t USART_FLAG);
void USART_ClearITPendingBit(USART_TypeDef*USARTx,unit16_t USART_IT);
四、串口配置一般步骤
#include "stm32f10x.h"
void My_USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
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();
USART_SendData(USART1,0xaa);
while(1);
}
|