菜只因C 2024-02-15 12:04 采纳率: 72.7%
浏览 10
已结题

关于#STM32#的问题:

Keil,利用scanf和printf进行格式化输入输出

int fputc(int c,FILE *stream)//printf
{
    uint8_t ch[1]={c};
    HAL_UART_Transmit(&huart1,ch,1,0xFFFF);
    return c;
}

int fgetc(FILE *stream)//scanf
{
    uint8_t ch[1];
    HAL_UART_Receive(&huart1,ch,1,0xFFFF);
    return ch[0];
}
while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
        scanf("%d:%d:%d",&hour,&min,&second);
        printf("%d:%d:%d\r\n",hour,min,second);
  }
  /* USER CODE END 3 */

微库已经勾选,USART1已经配置完毕,但输入有问题
假如输入5:20:23,输出5:0:0

  • 写回答

5条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-02-15 12:06
    关注

    引自免费微信小程序:皆我百晓生

    针对您在STM32上使用Keil和HAL库配置USART1进行scanf和printf格式化输入输出遇到的问题,当输入5:20:23时,输出结果却是5:0:0,这可能是由于scanf函数未能正确解析输入的时间格式。在微控制器环境下,标准输入输出函数(如scanf和printf)的行为可能与PC环境有所不同,尤其是在处理格式化字符串时。

    问题分析:

    1. 缓冲区问题:UART接收数据通常会有一定的延迟,而scanf在读取时可能会因为没有接收到完整的数据包(例如“5:20:23”)而导致解析失败。

    2. 格式匹配问题scanf的"%d:%d:%d"格式期望的是连续的冒号分隔的整数,但由于串口通信的异步性,它可能无法准确地按预期分割这些值。

    建议排查步骤及代码优化:

    #include "stdio.h"
    #include "string.h"
    #include "stm32f4xx_hal.h"
    
    // 假设已经初始化了HAL_UART_HandleTypeDef huart1
    
    #define MAX_RX_LEN 16 // 设置一个足够大的接收缓冲区
    char rx_buffer[MAX_RX_LEN]; 
    int hour, min, second;
    
    void process_input(void) {
        // 接收完整的一行数据
        uint8_t idx = 0;
        while (1) {
            HAL_UART_Receive(&huart1, &rx_buffer[idx], 1, 0xFFFF);
            if (rx_buffer[idx] == '\n' || idx >= (MAX_RX_LEN - 1)) { // 检查换行符或缓冲区满
                rx_buffer[idx] = '\0'; // 结束字符串
                break;
            }
            idx++;
        }
    
        // 解析输入的时间字符串
        sscanf(rx_buffer, "%d:%d:%d", &hour, &min, &second);
        
        printf("%d:%d:%d\r\n", hour, min, second);
    }
    
    int main(void) {
        HAL_Init();
        SystemClock_Config(); // 初始化系统时钟
        MX_GPIO_Init(); // 初始化GPIO
        MX_USART1_UART_Init(); // 初始化USART1
    
        while (1) {
            process_input();
        }
    
        return 0;
    }
    

    上述代码首先定义了一个较大的接收缓冲区来一次性接收一整行输入,然后通过sdkff()函数来解析这个缓冲区中的时间字符串,这样可以提高解析成功的概率。请注意,这种方法仍有可能因用户输入不规范(如缺少冒号)导致解析错误,因此实际应用中可能需要添加额外的错误检查和处理机制。

    同时,请确保USART1的接收中断或者DMA模式已启用,以便在接收到指定数量的数据后能及时触发进一步的数据处理,这对于实时性和准确性至关重要。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 2月26日
  • 已采纳回答 2月26日
  • 创建了问题 2月15日

悬赏问题

  • ¥15 is not in the mmseg::model registry。报错,模型注册表找不到自定义模块。
  • ¥15 安装quartus II18.1时弹出此error,怎么解决?
  • ¥15 keil官网下载psn序列号在哪
  • ¥15 想用adb命令做一个通话软件,播放录音
  • ¥30 Pytorch深度学习服务器跑不通问题解决?
  • ¥15 部分客户订单定位有误的问题
  • ¥15 如何在maya程序中利用python编写领子和褶裥的模型的方法
  • ¥15 Bug traq 数据包 大概什么价
  • ¥15 在anaconda上pytorch和paddle paddle下载报错
  • ¥25 自动填写QQ腾讯文档收集表