学习目标:
- 熟悉串口的通信原理
- 掌握串口基本配置
- 掌握UART收发中断控制
1.串口通信协议
1.1物理层
图1 串口通讯结构图
1.2电平标准
根据串口的通讯方式不同,电平准备不同。串口通讯可分为RS-232标准和TTL 标准,见表1所示:
通讯标准 | 电平标准 |
5V TTL | 逻辑1:2.4V - 5V |
逻辑0:0 - 0.5V | |
RS--232 | 逻辑1:-15V - -3V |
逻辑0:+3V - +15V |
1.3协议层
串口通信的数据包由发送设备通过TXD接口传输到接收设备的RXD接口,在串口通信之前,需要规定数据包的内容,包括起始位、数据主体、校验位、停止位组成。只有通信双方把数据格式规定好之后,才能正常通信。
1.3.1 波特率
在串口异步通信中,没有时钟信号,所以通信之间需要约定好波特率,表示每个码元的长度,常见的波特率有4800、9600、115200.
1.3.2 通信的起始信号和停止信号
串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一个逻辑 0 的 数据位表示,而数据包的停止信号可由 0.5、1、1.5 或 2 个逻辑 1 的数据位表示,只要双方约定 一致即可。
1.3.3 有效数据
有效数据位就是我们传输的正文,它紧接着起始信号之后,有效数据的长度可设定位5、6、7、或者8位,通常都设置为8位。
1.3.4 数据校验
数据位之后有一个可选校验位,因为通信过程中容易被外部干预数据出现偏差。可以加入对校验数据进行验证。校验方法有奇校验 (odd)、偶校验 (even)、0 校验 (space)、1 校验 (mark) 以及无校验 (noparity)。
奇校验:要求有效数据和校验位中“1”的个数为奇数,最后传输的数据将是 8 位的有效数据 加上 1 位的校验位总共 9 位。
偶校验:偶校验与奇校验要求刚好相反,要求帧数据和校验位中“1”的个数为偶数。
0 校验是不管有效数据中的内容是什么,校验位总为“0”,1 校验是校验位总为“1”。
2.串口的基本配置
(1)使能 RX 和 TX 引脚 GPIO 时钟和 USART 时钟;
(2)初始化 GPIO,并将 GPIO 复用到 USART 上;
(3)配置 USART 参数;
(4)配置中断控制器并使能 USART 接收中断;
(5)使能 USART;
(6)在 USART 接收中断服务函数实现数据接收和发送。
3.掌握UART收发中断控制
1、UART中断接收函数:HAL_UART_Receive_IT
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
2.调用接收中断函数和回调函数
#include "usart.h"
#include <string.h>
uint8_t uart_rxbuf[1];
char *str1="\nLED已经熄灭!\r\n";
char *str2="\nLED已经点亮!\r\n";
UART_HandleTypeDef huart2;
void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
HAL_UART_Receive_IT(&huart2, uart_rxbuf, 1);
/*这个MX_USART2_UART_Init函数是已经生成好了的
只需要添加上面这一句UART中断接收代码就行*/
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Transmit(&huart2, uart_rxbuf,1, 100); // 把收到的字节原样发送出去
if(uart_rxbuf[0]=='0'){ //比较字符数组里面的第一个字符,判断是否为0
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);//熄灭LED
HAL_UART_Transmit(&huart2,(uint8_t *)str1,strlen(str1),100);
}
else if(uart_rxbuf[0]=='1'){//比较字符数组里面的第一个字符,判断是否为1
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);//点亮LED
HAL_UART_Transmit(&huart2,(uint8_t *)str2,strlen(str2),100);
}
HAL_UART_Receive_IT(&huart2, uart_rxbuf, 1); // 重新注册一次,要不然下次收不到了
}
————————————————
版权声明:本文为CSDN博主「也无風雨也无晴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42852559/article/details/107685104