写在前面——
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.5 串口通信实验,讲解串口的STM32CubeMX配置和程序设计
官方例程下载:https://pan.baidu.com/s/1QC5BnDgY1m1me6-ihQ_OUQ?pwd=nqb1
提取码:nqb1
目录
4.5 串口通信实验
4.5.1. 实验任务
- 串口通信:参看官方例程(HAL_04_USART_TX、HAL_05_USART_RX),实现数据接收/发送。
- 拓展功能:结合LED、LCD显示功能,综合运用串口通信功能。
4.5.2. 硬件连接
DAP Link的串口连接在芯片的PA9和PA10(Rx)引脚。按照交叉连接方式,PA9对应Usart1-Tx,PA10 对应Usart1-Rx。
4.5.3. 初始化配置(STM32CubeMX)
基本配置步骤:
1)点击USATR1 ,设置MODE为异步通信(Asynchronous)
2)GPIO引脚设置 USART1_RX/USART_TX
3)波特率为115200Bits/s ;传输数据长度为8 Bit;奇偶检验无;停止位1;接收和发送都使能
4)NVIC Settings 一栏使能接收中断
5)其他配置: SYS(默认设置),时钟树80MHz,工程名称:Usart1,填写路径,选择单独生成.c/.h文件。若需要LED、按键控制,可参考前述章节,合理配置。
6) GENERATE CODE
4.5.4. 应用程序设计(KEIL5)
打开工程后,main.c中将自动引用usart.h和初始化串口MX_USART1_UART_Init();
main.c中添加定义串口的类别名:husart1:(可省略,已在usart.h中声明)
串口通信,共六个常用函数,可在stm32g4xx_hal_uart.h的最后找到:
- HAL_UART_Transmit();串口发送数据,使用超时管理机制
- HAL_UART_Receive();串口接收数据,使用超时管理机制
这两个分别是阻塞式发送函数和阻塞式接收函数,即在未完成发送或接收前不会执行后面的代码,适合初学者使用。 - HAL_UART_Transmit_IT();串口中断模式发送
- HAL_UART_Receive_IT();串口中断模式接收
这两个函数名称后面多了一个IT,对应的是非阻塞式发送函数和非阻塞式接收函数,属于中断方式发送/接收数据。在执行完成接收或发送的任务,可在中断中执行想要实现的功能。 - HAL_UART_Transmit_DMA();串口DMA模式发送
- HAL_UART_Transmit_DMA();串口DMA模式接收
这两个函数属于DMA方式发送/接收数据,请自行查阅DMA,这里暂时还用不上。
其中,下面2个函数,常用于数据发送和接收:
UART_HandleTypeDef *huart 定义UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart1
*pData 需要发送的数据
Size 发送的字节数
Timeout 最大发送时间,发送数据超过该时间退出发送
举例:
//串口发送三个字节数据,最大传输时间0xffff
HAL_UART_Transmit(&huart1, (uint8_t *)ZZX, 3, 0xffff);
UART_HandleTypeDef *huart 定义UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart1
*pData 接收到的数据存放地址
Size 接收的字节数
1. 数据发送
数据发送,常用函数HAL_UART_Transmit。参看官方例程(HAL_04_USART_TX)。
在main.c中定义串口别名husart1、初始化串口后,编写发送数据的代码(注意,先定义相关的变量):
使用串口调试助手,配置波特率等,即可接收到数据并显示。
2. 数据接收
数据接收,常使用中断方式,函数HAL_UART_Receive_IT,参看官方例程(HAL_05_USART_RX)。
基本步骤为:
1) 定义接收数据的变量(可省略定义串口别名huart1,它已在usart.h中声明)、
2)串口初始化,并开启在接收中断
3)编写串口接收中断回调函数:
这样,通过串口助手发送字符,stm32将接收的字符存储到数组变量rx中,并控制LED显示状态。
在接收中断回调函数中可以添加发数据送函数,可将接收到的数据再返回给串口助手,如,添加以下语句:
HAL_USART_Transmit(&husart1,rx, 1, 100);
3. 练习一
下面实现一组功能,在上电开始打开LED4并使用阻塞式发送HELLO WORLD给上位机,发送完成后关闭LED4。使用非阻塞式接收,在接收到0xA2时打开LED1并发送LED1 OPEN给上位机,接收到0xA1时关闭LED1并发送LED1 CLOSE给上位机。上位机发送时使用16进制发送。
参考程序设计:
uint8_t rx = 0;//定义接收的变量
//定义三个发送的字符串
uint8_t tx[]="HELLO WORLD\r\n";
uint8_t tx1[]="LED1 OPEN\r\n";
uint8_t tx2[]="LED1 CLOSE\r\n";
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
HAL_UART_Receive_IT(&huart1, &rx, 1);//开始接收UART1的数据,存放在rx中,停止位为1位
while (1)
{
//开灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_11,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
HAL_Delay(500);
//使用UART1发送tx数据,利用sizeof函数获取它的位数并作为停止位,完成时间为50
HAL_UART_Transmit(&huart1,tx,sizeof(tx),50);
//发送完成后关灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_11,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
HAL_Delay(500);
}
}
//接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1) //串口1的判别
{
//如果接收到为A2,开灯,并发送tx1
if(rx==0xA2)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
//sprintf(tx, "%04d:Hello,world.\r\n", 100);
HAL_UART_Transmit(&huart1,tx1,sizeof(tx1),100);
HAL_UART_Receive_IT(&huart1, &rx, 1);
}
//如果接收到为A1,关灯,并发送tx2
else if(rx==0xA1)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
//sprintf(tx, "%04d:Hello,world.\r\n", 100);
HAL_UART_Transmit(&huart1,tx2,sizeof(tx2),100);
HAL_UART_Receive_IT(&huart1, &rx, 1);
}
}
}
4. 练习二(自行设计程序)
在LCD例程的基础上,进行串口与中断的配置,实现SysTICK秒计时,LCD实时显示秒值,通过UART1发送秒值到PC(每秒发送1次),并接收PC发送的数据对秒进行设置。
参考:模块考点小练习题目+例程02-UART
下载链接:https://pan.baidu.com/s/19HHqDubEZr8ClEaxbb2zIg?pwd=nqb1
提取码:nqb1
4.5.5. 小结
- 串口USART的CubeMX配置,特别是含中断方式的配置
- 掌握串口USART的数据发送函数(HAL_UART_Transmit_IT)、数据接收函数(HAL_UART_Receive_IT)
- 编写接收中断回调函数(HAL_UART_RxCpltCallback),实现循环接收、发送