芯源半导体CW32
直播中

陈存楼

8年用户 1264经验值
私信 关注
[问答]

printf重定向之后无法运行是怎么回事?

参考 CW32F003_StandardPeripheralLib_V1.6ExamplesUARTUART_Printf  ,在代码中添加了#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */


PUTCHAR_PROTOTYPE
{
  USART_SendData_8bit(DEBUG_USARTx, (uint8_t)ch);

  while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);

  return ch;
}
在代码中添加printf之后进入调试模式点击RUN按钮是不能运行的。把print屏蔽之后就能运行。[/td][/tr]
以下内容为评论
[tr][td]参考 CW32F003_StandardPeripheralLib_V1.6ExamplesUARTUART_Printf  ,在代码中添加了#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */


PUTCHAR_PROTOTYPE
{
  USART_SendData_8bit(DEBUG_USARTx, (uint8_t)ch);

  while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);

  return ch;
}
在代码中添加printf之后进入调试模式点击RUN按钮是不能运行的。把print屏蔽之后就能运行。


回帖(1)

刘芳

2025-11-21 17:43:49

您的 printf 重定向问题可能由以下几个原因导致。请根据以下步骤排查:


1. 重定向函数实现不完整


您提供的代码片段不完整(结尾有 USART_SendData_8bit(D)。正确的重定向函数应包含以下要素:


PUTCHAR_PROTOTYPE
{
    USART_SendData_8bit(USART1, (uint8_t)ch); // 发送数据
    while (USART_GetFlagStatus(USART1, USART_FLAG_TX_EMPTY) == RESET); // 等待发送完成
    return ch;
}

关键点



  • 等待发送完成:必须添加 while 循环等待发送完成,否则数据可能未发送就被覆盖。

  • 正确实例名:确保 USART1 与您初始化时使用的外设名称一致(如 UART1USART1)。




2. UART 未正确初始化


参考 CW32 库的 UART_Printf 示例,检查以下初始化步骤:


void UART_Init(void)
{
    USART_InitTypeDef USART_InitStructure = {0};

    // 使能 USART 和 GPIO 时钟
    RCC_APBPeriphClk_Enable(RCC_APBENR_USART1, ENABLE);
    RCC_AHBPeriphClk_Enable(RCC_AHBENR_GPIOA, ENABLE);

    // 配置 TX 引脚 (PA9) 为复用功能
    GPIO_Init(GPIOA, GPIO_PIN_9, GPIO_Mode_AF_PP);

    // 配置 USART 参数
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_Init(USART1, &USART_InitStructure);

    USART_Cmd(USART1, ENABLE); // 使能 USART
}

常见错误



  • 未使能时钟(RCC_APBPeriphClk_Enable)。

  • 引脚复用模式错误(必须为 GPIO_Mode_AF_PP)。

  • 波特率/停止位配置不匹配。




3. 编译器/库配置问题


对于 GCC (Arm Embedded Toolchain):



  • 在链接器选项中添加 -u _printf_float(如果使用浮点数)。

  • 确保使用 --specs=nano.specs--specs=rdimon.specs(在链接器参数中)。


对于 Keil (ARMCC):



  • 勾选 Use MicroLIB(在 Target 选项卡中)。

  • 若未用 MicroLIB,需重载 fputc 并启用标准库。




4. 硬件连接问题



  • 确认 TX 引脚(如 PA9)已连接到 USB 转串口工具。

  • 检查串口工具的波特率是否与代码一致(如 115200)。




完整解决方案


步骤 1:修复重定向函数


#ifdef __GNUC__
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
    USART_SendData_8bit(USART1, (uint8_t)ch); // 替换 USART1 为您的实例
    while (USART_GetFlagStatus(USART1, USART_FLAG_TX_EMPTY) == RESET); // 等待发送完成
    return ch;
}

步骤 2:添加 UART 初始化代码


参考示例库的 UART_Printf 项目,复制完整的初始化函数并确保在 main() 中调用:


int main()
{
    UART_Init(); // 初始化 UART
    printf("Hello Worldn"); // 测试输出
    while(1);
}

步骤 3:检查编译器设置



  • Keil:启用 MicroLIB(Options for Target -> Target -> Use MicroLIB)。

  • GCC:在 Makefile 中添加链接参数:
    LDFLAGS += -u _printf_float -specs=nano.specs


步骤 4:验证硬件



  • 用示波器或逻辑分析仪检查 TX 引脚是否有信号。

  • 确认串口工具接地(GND)已连接。




常见问题排查表





































问题现象 可能原因 解决方案
无任何输出 UART 未初始化/时钟未使能 检查 RCC_APBPeriphClk_Enable 调用
输出乱码 波特率不匹配 检查代码与串口工具的波特率
仅第一个字符输出正确 缺少等待发送完成的循环 添加 while (USART_GetFlagStatus(...))
程序卡死 未启用 MicroLIB(Keil) 在 Keil 中勾选 Use MicroLIB
浮点数不打印 未启用浮点数支持(GCC) 添加 -u _printf_float

通过以上步骤应能解决问题。如仍有异常,建议使用 USART_SendData_8bit 直接发送字符串(绕过 printf)以隔离问题。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分