IAR开发stm32-printf重定向

开发的时候用串口打印信息的时候发现printf重定向没任何输出,在网上找的方法都是这样的,这样的确是可以解决FILE未定义错误,但是输出还是没有
开发板:正点原子探索者
mcu:stm32f407
IDE:IAR Embedded Workbench for ARM 9.40.1
在这里插入图片描述
我是直接用的keil的例子,usart.c文件已经写好对printf重定向操作,即重写fputc函数,代码如下:

/* FILE 在 stdio.h里面定义. */
FILE __stdout;

/* 重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{
    while ((USART1->SR & 0X40) == 0);               /* 等待上一个字符发送完成 */

    USART1->DR = (uint8_t)ch;                       /* 将要发送的字符 ch 写入到DR寄存器 */
    return ch;
}

但是IAR并没有调用这个函数,IAR是调用__write,所以正确方式是重写__write函数,不过不能直接把fputc函数改名为__write,对,我最开始就是这么操作的,应该是这样的:

//串口重定向打印
size_t __write(int handle, const unsigned char * buffer, size_t size)
{
  /* Sending in normal mode */
  if(HAL_OK == HAL_UART_Transmit(&g_uart1_handle,(uint8_t *)buffer,size,100000))
  {
    return size;
  }
  else
  {
    return -1;
  }
}

第一张图片选full那个操作也是需要的
然后~,have fun!
在这里插入图片描述
另一种方法,串口printf打印已经结束了,还可以利用半主机模式(semihosting)重定向到IAR Embedded Workbench中的Terminal I/O
选项可以这么选
在这里插入图片描述
这样编译的话肯定报FILE未定义错误,可以直接把FILE相关代码注释掉,本来也没有使用那部分代码,这样操作的话也需要把刚才重写的__write函数注释掉,编译器内部实现操作
在调试时,通过View>Terminal I/O打开Terminal I/O窗口显示对应的打印输出,这种方式打印的很慢,也不支持中文打印,也可能可以支持,没仔细研究
在这里插入图片描述
还有通过SWD方式,我并没有尝试
参考链接:https://www.iar.com/zh/knowledge/support/technical-notes/general/implementing-printf-output

### STM32串口重定向 `fputc` 出现乱码的原因分析 在STM32开发过程中,当通过 `fputc` 实现串口重定向时,如果出现乱码现象,通常可能是由以下几个原因引起的: #### 1. **波特率设置不匹配** 波特率是通信双方约定的数据传输速率。如果发送端和接收端的波特率不同步,则会导致数据解析错误从而引发乱码问题。需确认STM32中的UART配置与终端工具(如SecureCRT、Putty等)所使用的波特率一致[^1]。 ```c // UART初始化函数中确保波特率正确配置 huart3.Init.BaudRate = 115200; HAL_UART_Init(&huart3); ``` --- #### 2. **Keil编译器未正确开启标准库支持** 为了使 `printf` 和其他标准输入/输出功能正常工作,在Keil项目中需要确保已包含 `<stdio.h>` 并定义了 `_REDIRECT_STDOUT` 宏或者手动实现 `fputc` 的重写逻辑。如果没有正确配置这些选项,可能会导致字符无法被正确处理而产生乱码。 ```c #include "stdio.h" int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF); return ch; } ``` --- #### 3. **中断优先级冲突** 某些情况下,高优先级的中断可能干扰到UART外设的工作流程,特别是对于时间敏感的操作而言。这可能导致部分字节丢失或延迟过大进而造成显示异常。因此建议调整相关外围设备的抢占优先级以及子优先级来避免此类情况发生[^2]。 ```c void MX_NVIC_Configuration(void){ NVIC_SetPriority(USART1_IRQn, 1); // 设置较低的抢占优先级 NVIC_EnableIRQ(USART1_IRQn); } ``` --- #### 4. **缓冲区溢出或其他硬件资源不足** 长时间连续打印大量信息至串口中断模式下运行时容易遇到内存分配失败等问题;另外还需注意电源电压稳定性等因素也可能间接影响通讯质量[^3]。 --- ### 综合解决方案 以下是综合考虑上述各点后的改进措施: - 确认并统一收发两端之间的波特率参数; - 在工程文件里加入必要的头文件声明,并按照实际需求编写合适的 `fputc` 方法体; - 调整好各个模块间的中断级别关系以防互相打扰; - 如果条件允许的话还可以尝试优化现有程序结构减少不必要的开销提高效率。 最终版代码如下所示: ```c #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif /* __GNUC__ */ PUTCHAR_PROTOTYPE{ HAL_StatusTypeDef status; do{ status=HAL_UART_Transmit(&huartX,(uint8_t*)&ch,1,HAL_MAX_DELAY); }while(status!=HAL_OK); return ch; } ``` > 注:这里的 huartX 应替换为您具体使用的串口号变量名比如 huart1 或者 huart2 等。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值