【蓝桥杯嵌入式】UART(收发)
全部代码网盘自取
链接:https://pan.baidu.com/s/1PX2NCQxnADxYBQx5CsOgPA?pwd=3ii2
提取码:3ii2
1、电路图
2、Cube配置
打开PA9、10串口
选择异步模式,并根据题目要求设置串口波特率,一般要求设置为9600。
打开串口中断
3、串口收发函数
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) |
用于以中断方式接收数据。当UART接收到数据时,硬件中断被触发,允许CPU处理其他任务。这种方式适用于需要快速响应或同时执行多个任务的场景。 |
|
HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) |
用于以阻塞方式接收数据。函数调用后,CPU将等待直到接收到指定数量的数据或超时。这种方式简单易用,但会阻塞CPU,直到数据接收完成。 |
|
HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size) |
用于以中断方式发送数据。当UART发送缓冲区为空时,硬件中断被触发,允许CPU在等待发送数据的同时处理其他任务。 |
HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout) |
用于以阻塞方式发送数据。函数调用后,CPU将等待直到所有数据发送完毕或超时。这种方式确保了数据的发送,但会阻塞CPU。 |
4、sizeof和strlen
关于上面这些函数在确定要接收的数据长度时用sizeof还是strlen的问题:(其实都可以,影响不大)
Strlen |
|
Sizeof |
|
5、代码
5.1 串口发送数据
main.c
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
#include "string.h"
void SystemClock_Config(void);
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */char temp[10];int a=666;float b=666.666;char c='6';char d[]="66666666";/* USER CODE END 2 *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */sprintf(temp,"%d\r\n",a);HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);sprintf(temp,"%.3f\r\n",b);HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);sprintf(temp,"%c\r\n",c);HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);sprintf(temp,"%s\r\n",d);HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);HAL_Delay(500);}
}
5.2 串口printf重定向
勾选Use MicroLIB,指定编译器使用 MicroLIB作为标准C库,否则无法使用printf.
MicroLIB是一种精简版的C标准库,它比完整的 ANSI C标准库(如 NewLib 或 NewLib)占用更少的内存,这使得它非常适合资源受限的嵌入式系统。
在main.c修改
/* USER CODE BEGIN WHILE */while (1){printf("%d\r\n",a);printf("%.3f\r\n",b);printf("%c\r\n",c);printf("%s\r\n\r\n",d);HAL_Delay(500);/* USER CODE END WHILE */}
在usart.c中增加(放在其他地方也行)
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1,(unsigned char*)&ch,1,50);return ch;
}
5.3 串口接收数据
interrupt.c
#include "interrupt.h"char rxdata[30];
uint8_t rxdat;
uchar rx_pointer;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//接收回调函数
{rxdata[rx_pointer++]=rxdat; //存放读取到的字符,每次存放位置自增1HAL_UART_Receive_IT(&huart1,&rxdat,1);//每次中断只能接收一个字符
}
interrupt.h
#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_#include "main.h"
#include "usart.h"
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);#endif
main.c
#include "main.h"
#include "usart.h"
#include "gpio.h"
/* USER CODE BEGIN Includes */
#include “stdio.h”
#include "interrupt.h"
void uart_pro(void);
extern uchar rx_pointer;
extern char rxdata[30];
extern uchar rx_pointer;
extern uint8_t rxdat;
/* USER CODE END Includes */
void SystemClock_Config(void);
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */HAL_UART_Receive_IT(&huart1,&rxdat,1); //串口接收初始化
/* USER CODE END 2 *//* USER CODE BEGIN WHILE */while (1){if(rx_pointer!=0) //防止接收不完整{int temp=rx_pointer;HAL_Delay(1);if(temp==rx_pointer)uart_pro();}/* USER CODE END WHILE */}
}void uart_pro(void)
{if(rx_pointer>0){printf("%s",rxdata);}rx_pointer=0;memset(rxdata,0,30); //rxdata指向的内存区域的前30个字节全部设置为0
}
一定要记得进行串口接收初始化