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生成的初始化代码所以与教程给出代码相差较大

相关推荐
jencepan2 小时前
纳安级功耗,5.5V/2A,23-6封装,单节锂电升压DCDC方案,晶艺LA2112N
单片机·嵌入式硬件
BMS小旭2 小时前
CubeMx-CAN
单片机·学习·cubemx·can
EVERSPIN11 小时前
基于灵动MM32F0140国产32位单片机的Mini-LED应用
单片机·嵌入式硬件·32位单片机·国产32位单片机
XXYBMOOO12 小时前
内核驱动开发与用户级驱动开发:深度对比与应用场景解析
linux·c++·驱动开发·嵌入式硬件·fpga开发·硬件工程
剑之所向16 小时前
MCU开机按键,怎么避免抖动造成的开机
数据库·单片机·mongodb
钟佩颖19 小时前
STM32
stm32·单片机·嵌入式硬件
平凡灵感码头19 小时前
天天在用的芯片:78L05 电源稳压器详解
单片机·嵌入式硬件
Zeku19 小时前
20251228 - Linux 驱动开发硬件管理机制笔记
stm32·freertos·linux驱动开发·linux应用开发
恶魔泡泡糖20 小时前
51单片机动态数码管应用2
单片机·嵌入式硬件·51单片机