STM32F407轮询模式下HAL_UART_Receive参数问题及解决方法
问题
使用STM32F407通过UART轮询模式接收数据时,无法确定接收数据长度,将HAL_UART_Receive第三个参数设为strlen(data)导致代码无法正常运行。需求是接收"1"-"4"分别点亮对应引脚LED,"0"关闭所有LED,如何解决该问题?
原代码
char data[50]; while (1) { HAL_UART_Receive(&huart4, (uint8_t*)data, strlen(data), 100); if(strcmp(data,"1")==0){ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); } if(strcmp(data,"2")==0){ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET); } if(strcmp(data,"3")==0){ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); } if(strcmp(data,"4")==0){ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET); } if(strcmp(data,"0")==0){ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET); } else{ continue; } }
解决方案
1. 修复接收长度参数问题
strlen(data)会从数组起始位置找第一个\0来计算长度,但未初始化的data数组内存是随机值,导致接收长度完全不可控。轮询模式下,结合你的指令都是单字符的特点,直接固定接收长度为1即可:
// 接收1个字符,超时可设为HAL_MAX_DELAY(一直等待)或具体毫秒值 HAL_UART_Receive(&huart4, (uint8_t*)data, 1, HAL_MAX_DELAY);
2. 保证字符串比较的合法性
strcmp要求字符串必须以\0结尾,接收单个字符后需要手动添加结束符:
data[1] = '\0';
3. 优化后的完整代码示例
char data[2]; // 仅需存储1个字符+结束符,节省内存 while (1) { HAL_StatusTypeDef status = HAL_UART_Receive(&huart4, (uint8_t*)data, 1, HAL_MAX_DELAY); if (status != HAL_OK) { // 处理接收错误(超时、帧错误等) continue; } data[1] = '\0'; // 补充字符串结束符 if(strcmp(data,"1")==0){ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); } else if(strcmp(data,"2")==0){ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET); } else if(strcmp(data,"3")==0){ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); } else if(strcmp(data,"4")==0){ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET); } else if(strcmp(data,"0")==0){ // 批量操作引脚,简化代码 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET); } }
4. 可选:用字符直接比较提升效率
因为是单字符指令,直接比较字符比strcmp更高效:
switch(data[0]) { case '1': HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); break; case '2': HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET); break; case '3': HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); break; case '4': HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET); break; case '0': HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET); break; default: // 处理无效字符 break; }
内容的提问来源于stack exchange,提问作者busragulen
相关产品推荐
相关产品推荐

