目录
一、数据通信的基础概念
1.1、串行/并行通信
按数据通信方式分类:串行通信、并行通信
串行通信
并行通信
1.2、单工/半双工/全双工通信
按数据传输方向分类:单工通信、半双工通信、全双工通信
单工通信 半双工通信 全双工通信
单工通信:数据只能沿一个方向传输
半双工通信:数据可以沿两个方向传输,但需要分时进行
全双工通信:数据可以同时进行双向传输
1.3、同步/异步通信
按数据同步方式分类:同步通信、异步通信
同步通信:共用同一时钟信号
异步通信:没有时钟信号,通过在数据信号中加入起始位和停止位等一些同步信号
1.4、波特率
1、比特率:每秒钟传送的比特数,单位 bit/s
2、波特率:每秒钟传送的码元数,单位 Baud
3、比特率 = 波特率 * log2 M,M 表示每个码元承载的信息量
二进制系统中,码元承载的信息量为二,波特率数值上等于比特率
1.5、常见的串行通信接口
二、串口(RS-232)
2.1、什么是串口
串行通信接口:指按位发送和接收的接口。如:RS-232/422/485 等
RS-232接口(DB9)
数据:
TXD(pin 3):串口数据输出
RXD(pin 2):串口数据输入
握手:
RTS(pin 7):请求发送
CTS(pin 8):清除发送
DSR(pin 6):数据发送就绪
DCD(pin 1):数据载波检测
DTR(pin 4):数据终端就绪
地线:
GND(pin 5):信号地
其他:
RI(pin 9):振铃指示
2.2、RS-232电平与COMS/TTL电平对比
逻辑1 | 逻辑0 | |
RS-232电平 | -15V ~ -3V | +3V ~ +15V |
COMS电平(3.3V) | 3.3V | 0V |
TTL电平(5V) | 5V | 0V |
结论:COMS/TTL 电平不能与 RS-232 电平直接交换信息
2.3、设备间的RS-232通信示意图
特别注意:两个设备之间的 TXD 和 RXD,必须交差连接,方可正常通信
2.4、STM32串口与电脑USB口通信示意图
特别注意:两个设备之间的 TXD 和 RXD,必须交差连接,方可正常通信
2.5、RS-232异步通信协议
启动位:必须占 1 个位长,保持逻辑 0 电平
有效数据位:可选 5、6、7、8、9 个位长,LSB(最低有效位)在前,MSB(最高有效位)在后
校验位:可选占 1 个位长,也可以没有该位
停止位:必须有,可选占 0.5、1、1.5、2 个位长,保持逻辑 1 电平
三、STM32的USART
3.1、STM32的USART简介
USART(Universal synchronous asynchronous receiver transmitter),通用同步异步收发器
UART(Universal asynchronous receiver transmitter),通用异步收发器
USART/UART 都可以与外部设备进行全双工异步通信
USART,我们常用的也是异步通信
3.2、STM32的USART主要特性
1,全双工异步通信
2,单线半双工通信
3,单独的发送器和接收器使能位
4,可配置使用 DMA 的多缓冲器通信
5,多个带标志的中断源
3.3、STM32F1/F4/F7的USART框图
STM32F407xx 数据手册 USART 框图
USART 框图简化版
3.4、设置USART波特率(F4)
波特率计算公式:,其中 是串口的时钟
对于 F4,我们把 USART_CR1 寄存器的位 15 设置为 0,即使用 16 倍过采样
3.5、USART寄存器介绍
1、控制寄存器1(CR1)
该寄存器需要完成的配置
位13:使能USART
位12:配置8个数据位
位10:禁止检验控制
位5:使能接收缓冲区非空中断
位3:使能发送
位2:使能接收
2、控制寄存器2(CR2)
该寄存器需要完成的配置
位13:12:配置1个停止位
3、控制寄存器3(CR3)
该寄存器需要完成的配置
位3:配置不选择半双工模式
4、数据寄存器(DR)
设置好控制和波特率寄存器后,往该寄存器写入数据即可发送,接收数据则读该寄存器
5、状态寄存器(SR)
根据 TC 位可以知道能否发数据,根据 RXNE 位知道是否收到数据
四、HAL库外设初始化MSP回调机制
以 USART 为例
五、HAL库中断回调机制
以 USART 为例
六、USART/UART异步通信配置步骤
6.1、配置串口工作参数
HAL库驱动函数:HAL_UART_Init()
/**
* @brief Initializes the UART mode according to the specified parameters in
* the UART_InitTypeDef and create the associated handle.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);
关键结构体
typedef struct
{ uint32_t BaudRate; /* 波特率 */
uint32_t WordLength; /* 字长 */
uint32_t StopBits; /* 停止位 */
uint32_t Parity; /* 奇偶校验位 */
uint32_t Mode; /* UART 模式 */
uint32_t HwFlowCtl; /* 硬件流设置 */
uint32_t OverSampling; /* 过采样设置 */
}UART_InitTypeDef
6.2、串口底层初始化
HAL库驱动函数:HAL_UART_MspInit()
/**
* @brief UART MSP Init.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart);
用于配置 GPIO、NVIC、CLOCK 等
6.3、开启串口异步接收中断
HAL库驱动函数:HAL_UART_Receive_IT()
/**
* @brief Receives an amount of data in non blocking mode.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* the received data is handled as a set of u16. In this case, Size must indicate the number
* of u16 available through pData.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData Pointer to data buffer (u8 or u16 data elements).
* @param Size Amount of data elements (u8 or u16) to be received.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
作用:以中断的方式接收指定字节的数据
形参 1:是 UART_HandleTypeDef 结构体类型指针变量
形参 2:是指向接收数据缓冲区
形参 3:是要接收的数据大小,以字节为单位
6.4、设置优先级、使能中断
HAL库驱动函数:设置优先级 HAL_NVIC_SetPriority()、使能中断 HAL_NVIC_EnableIRQ()
HAL_NVIC_SetPriority()
/**
* @brief Sets the priority of an interrupt.
* @param IRQn External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f4xxxx.h))
* @param PreemptPriority The preemption priority for the IRQn channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority
* @param SubPriority the subpriority level for the IRQ channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority.
* @retval None
*/
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority);
HAL_NVIC_EnableIRQ()
/**
* @brief Enables a device specific interrupt in the NVIC interrupt controller.
* @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
* function should be called before.
* @param IRQn External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f4xxxx.h))
* @retval None
*/
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);
这两个函数在【5】STM32·HAL库·中断 中有详细讲解
6.5、编写中断服务函数
编写 USARTx_IRQHandler() 或 UARTx_IRQHandler() 函数处理接收到的数据
在中断向量表中有定义
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD UART4_IRQHandler ; UART4
DCD UART5_IRQHandler ; UART5
DCD USART6_IRQHandler ; USART6
6.6、串口数据发送
HAL库驱动函数:HAL_UART_Transmit()
/**
* @brief Sends an amount of data in blocking mode.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* the sent data is handled as a set of u16. In this case, Size must indicate the number
* of u16 provided through pData.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData Pointer to data buffer (u8 or u16 data elements).
* @param Size Amount of data elements (u8 or u16) to be sent
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
作用:以阻塞的方式发送指定字节的数据
形参 1 :UART_HandleTypeDef 结构体类型指针变量
形参 2:指向要发送的数据地址
形参 3:要发送的数据大小,以字节为单位
形参 4:设置的超时时间,以ms单位
七、IO引脚复用功能
7.1、通用与复用
通用:IO 端口的输入或输出是由 GPIO 外设控制
复用:IO 端口的输入或输出是由其它非 GPIO 外设控制
7.2、STM32F4/F7/H7的IO引脚复用
为了解决 F1 系列存在的 IO 复用功能冲突问题,F4 往后的系列都加入了复用器
复用器特点
1、每个 IO 引脚都有一个复用器
2、复用器采用 16 路复用功能输入(AF0 到 AF15)
3、复用器一次仅允许一个外设的复用功能 (AF) 连接到 IO 引脚
4、通过GPIOx_AFRL和GPIOx_AFRH寄存器进行配置
温馨提示:复位完成后,所有 IO 都会连接到系统的复用功能 0 (AF0)
IO 引脚复用映射示意图
GPIO 复用功能低位寄存器(AFRL)
GPIO 复用功能高位寄存器(AFRH)
八、编程实战
串口实验
main.c
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
int main(void)
{
uint8_t len;
uint16_t times = 0;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
while(1)
{
if (g_usart_rx_sta & 0x8000) /* 接收到了数据? */
{
len = g_usart_rx_sta & 0x3fff; /* 得到此次接收到的数据长度 */
printf("\r\n您发送的消息为:\r\n");
HAL_UART_Transmit(&g_uart1_handle,(uint8_t*)g_usart_rx_buf,len,1000); /* 发送接收到的数据 */
while(__HAL_UART_GET_FLAG(&g_uart1_handle,UART_FLAG_TC)!=SET); /* 等待发送结束 */
printf("\r\n\r\n"); /* 插入换行 */
g_usart_rx_sta = 0;
}
else
{
times++;
if (times % 5000 == 0)
{
printf("\r\n正点原子 STM32开发板 串口实验\r\n");
printf("正点原子@ALIENTEK\r\n\r\n\r\n");
}
if (times % 200 == 0) printf("请输入数据,以回车键结束\r\n");
if (times % 30 == 0) LED0_TOGGLE(); /* 闪烁LED,提示系统正在运行. */
delay_ms(10);
}
}
}
usart 文件使用【1】STM32·HAL库·新建工程模板【一步到位】中导入的即可
如果是使用 VScode 出现串口输出以下乱码,需要修改编码方式为 GB2312 重新保存