STM32--USART(串口)

一、关键知识

九位数据一位校验位

二、串口实战

实验成功现象发送一次信息GPIO引脚翻转一次也就是小灯亮或者灭一次

STMCubemx配置

复制代码
// uint8_t ARR[6]={'H','E','L','L','O'};
	 uint8_t ARR ;


//		HAL_UART_Receive(&huart1,&ARR,1,100)
		if(HAL_UART_Receive(&huart1,&ARR,1,100) == HAL_OK)  //如果接受收到了信息
		{
			if(ARR == 0X01)
			{
			HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8);//翻转GPIO引脚也就是小灯亮灭
			HAL_UART_Transmit(&huart1,&ARR,1,100);//并且发送接收到的信息
		  
		  }
//		  HAL_Delay(10);
	  }

被注释的代码为实验一的代码

三、串口接受中断

如果有多个传感器接收数据或者其他导致延时,上例延时1000ms时接收到18次但是只发送了6次,数据丢失了

!!!有没有方法将上述第一个if到延时函数给他独立出来不受延时函数的影响???--串口接受中断

增加中断

复制代码
/* USER CODE BEGIN Includes */
uint8_t ARR = 0;// 定义接收缓存变量
/* USER CODE END Includes */

  /* USER CODE BEGIN 2 */
  
  HAL_UART_Receive_IT(&huart1, &ARR, 1);
  /* USER CODE END 2 */

/* USER CODE BEGIN 4 */


// 串口接收完成中断回调函数(HAL库规范,接收完成后自动触发)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance == USART1) // 确认是USART1中断
  {
    if(ARR == 0X01)
    {
      HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);
      HAL_UART_Transmit(&huart1, &ARR, 1, 500); // 回传数据(此处非中断上下文,可短暂阻塞)
    }
    
    // 重新开启接收中断(HAL库中断为单次触发,需手动重启)
    HAL_UART_Receive_IT(&huart1, &ARR, 1);
  }
}


/* USER CODE END 4 */

HAL_UART_RxCpltCallback 是 STM32 HAL 库中串口接收完成中断的回调函数。

四、不定长度数据包

复制代码
#define BUF_MAX_LEN 100  // 缓冲区最大长度
uint8_t buf[BUF_MAX_LEN] = {0};  // 接收缓冲区
uint8_t NUM = 0;                 // 缓冲区索引,初始化为0
uint8_t ARR = 0;                 // 单个字节接收缓存

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance == USART1) // 确认是USART1中断
  {
    if (NUM < BUF_MAX_LEN) {
      buf[NUM] = ARR;
      NUM++;
    } else {
      // 循环缓冲区:复位索引,覆盖旧数据(也可根据需求丢弃新数据)
      NUM = 0;
      buf[NUM] = ARR;
      NUM++;
    }
	     // 处理接收到的数据(非阻塞)
    HAL_UART_Transmit_IT(&huart1, buf, 1); // 非阻塞回传
    
  
  }
	  // 重启中断接收,实现下一次接收
    HAL_UART_Receive_IT(&huart1, buf, 1);
}


/* USER CODE END 4 */

上述代码存在数据丢失?为什么

优化代码

复制代码
// UART接收完成中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance == USART1) // 确认是USART1中断
  {  
    uint8_t temp_arr = ARR; // 保存接收到的字节
    
    // 存储到缓冲区
    if (NUM < BUF_MAX_LEN) {
      buf[NUM] = temp_arr;
      NUM++;
    } else {
      // 循环缓冲区:复位索引,覆盖旧数据
      NUM = 0;
      buf[NUM] = temp_arr;
      NUM = 1;
    }
    
    // 翻转LED指示收到数据
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);
    
    // 打印接收到的字符
    printf("%c", temp_arr);
    
    // ★★★ 关键:重新启动接收中断 ★★★
    HAL_UART_Receive_IT(&huart1, &ARR, 1);
  }
}

// 添加UART错误回调函数
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance == USART1)
  {
    // 清除错误标志
    __HAL_UART_CLEAR_OREFLAG(huart);
    
    // 重新启动接收
    HAL_UART_Receive_IT(&huart1, &ARR, 1);
    
    printf("\r\nUART Error Cleared!\r\n");
  }
}

依旧会丢包1!!!!!!

这个代码添加重定向printf ,printf是向屏幕打印的,重定向之后printf可以面向串口,添加下面这个函数即可重定向printf

复制代码
int fputc(int ch, FILE *f)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    return ch;
}

注释:使用重定向时必须把这个勾上

遇到问题:传输过程中数据丢失

注释:由于使用Cubemax生成的初始化代码所以与教程给出代码相差较大

相关推荐
Deitymoon3 小时前
STM32——串口中断接收
stm32·单片机·嵌入式硬件
charlie1145141914 小时前
嵌入式C++实践开发第21篇(单片机实践):按钮输入 —— 硬件原理、消抖与HAL API
开发语言·c++·单片机
一起搞IT吧4 小时前
Android性能系列专题理论之十一:block IO问题分析思路
android·嵌入式硬件·智能手机·性能优化
余生皆假期-5 小时前
YuanHub 源码分析【一】FlashDB 初始化与项目应用
笔记·单片机·嵌入式硬件
Deitymoon5 小时前
STM32——串口通信发送数据
stm32·单片机·嵌入式硬件
玩转单片机与嵌入式5 小时前
嵌入式AI场景:哪些应用场景不适合将AI模型部署到单片机(MCU)中?
人工智能·单片机·嵌入式硬件
czwxkn6 小时前
8STM32(stdl)低功耗模式
stm32·单片机·嵌入式硬件
czwxkn6 小时前
9STM32(stdl)看门狗
stm32·单片机·嵌入式硬件
coward916 小时前
Linux 内核 KGDB 以及内核驱动单串口调试笔记:telnet + agent-proxy + gdb-multiarch 实践
linux·单片机·嵌入式硬件
刻BITTER7 小时前
VirtualBox 安装Armbian x86 虚拟机
linux·嵌入式硬件