STM32 Uart中断发送打印乱码问题记录

print 和scanf 重定向

这里需要解决2个问题;

  1. print 和scanf重定向 编写对应的内部函数

  2. 编译器兼容MDK和GCC

参考内容

基于 VsCode + GCC + STM32 环境下的串口输入输出重定向_gcc libc 重定向-CSDN博客

修改后的参考代码,亲自用VSCODE GCC和MDK测试 ok

cpp 复制代码
#include "stdio.h"


// 条件编译
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif /* __GNUC__ */




/* 告知连接器不从C库链接使用半主机的函�???????? */
// 标准库需要的支持函数                 
struct __FILE 
{ 
    int handle; 
}; 
 
// 定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
    x = x; 
} 
 
FILE __stdout;




/**
  * 函数功能: 重定�??? c库函�??? printf�??? DEBUG_USARTx
  * 输入参数: �???
  * �??? �??? �???: �???
  * �???    明:�???
  */
PUTCHAR_PROTOTYPE
{

  /***********等待上一次发送完成************/
	while(huart1.gState == HAL_UART_STATE_BUSY_TX);
  // HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFF); //阻塞式无限等�???
  HAL_UART_Transmit_IT(&huart1, (uint8_t *)&ch, 1); //中断方式
  // HAL_UART_Transmit_DMA(&huart1, (uint8_t *)&ch, 1); //DMA方式
  return ch;
}


/**
  * 函数功能: 重定�??? c库函�??? getchar,scanf�??? DEBUG_USARTx
  * 输入参数: �???
  * �??? �??? �???: �???
  * �???    明:�???
  */
GETCHAR_PROTOTYPE
{
  uint8_t ch = 0;

  // HAL_UART_Receive(&huart1, &ch, 1, 0x0FF);
  HAL_UART_Receive_IT(&huart1, &ch, 1);
  //  HAL_UART_Receive_DMA(&huart1, &ch, 1);
    
  return ch;
}


#ifdef __GNUC__
// 禁用半主机:
#pragma import(__use_no_semihosting)     //关闭半主机模式,只需要在任意�????????个C文件中加入即可�??
int _write(int file, char *ptr, int len)
{
    int DataIdx;
    for (DataIdx = 0; DataIdx < len; DataIdx++) 
    { 
        __io_putchar(*ptr++); 
    }
    return len;
}

int _read(int file, char *ptr, int len)
{
  int DataIdx;

  for (DataIdx = 0; DataIdx < len; DataIdx++)
  {
    *ptr++ = __io_getchar();
  }

  return len;
}
#endif

总结几个内容:

1.不同编译环境下的输入/输出重定向

在 gcc环境下,printf重定向跟以往的在 MDK上的重定向有点不同。

  • Keil、IAR等MDK上面,都是用以下方式重定向的
cpp 复制代码
int fputc(int ch, FILE *f)
int fgetc(FILE *f)
  • gcc环境下,使用的是如下方式:
cpp 复制代码
int _write(int file, char *ptr, int len)
int _read(int file, char *ptr, int len)

因此用条件编译兼容两种情况

  1. 禁用半主机也是在GCC下才使用,因此全部防止到了如下条件编译中

注意,如下的_wirte和_read 也调用了前面的PUTCHAR_PROTOTYPE和GETCHAR_PROTOTYPE

cpp 复制代码
#ifdef __GNUC__
// 禁用半主机:
#pragma import(__use_no_semihosting)     //关闭半主机模式,只需要在任意�????????个C文件中加入即可�??
int _write(int file, char *ptr, int len)
{
    int DataIdx;
    for (DataIdx = 0; DataIdx < len; DataIdx++) 
    { 
        __io_putchar(*ptr++); 
    }
    return len;
}

int _read(int file, char *ptr, int len)
{
  int DataIdx;

  for (DataIdx = 0; DataIdx < len; DataIdx++)
  {
    *ptr++ = __io_getchar();
  }

  return len;
}
#endif

通过以上修改后已经完成了重定向

2.printf打印不全(或打印乱码问题)

最初参考代码如下,此处此时了三种方式,只有阻塞式可以完整打印

cpp 复制代码
PUTCHAR_PROTOTYPE
{


  // HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFF); //阻塞式
  HAL_UART_Transmit_IT(&huart1, (uint8_t *)&ch, 1); //中断方式
  // HAL_UART_Transmit_DMA(&huart1, (uint8_t *)&ch, 1); //DMA方式
  return ch;
}

,其它两种方式打印效果如下

while1内容如下

printf("Hello, uart printf simple!");

HAL_Delay(1000);

实际打印效果如下

原因是没有发送完成又被新的中断打断了

查找参考资料:【stm32使用CMSIS-Driver printf串口重映射打印不完整的问题】_cmsis 重写printf-CSDN博客

修改增加等待不忙发送,即增加如下红色部分后测试中断方式正常,DMA应该也正常.

PUTCHAR_PROTOTYPE

{

/***********等待上一次发送完成************/

while(huart1.gState == HAL_UART_STATE_BUSY_TX);

// HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFF); //阻塞式无限等�???

HAL_UART_Transmit_IT(&huart1, (uint8_t *)&ch, 1); //中断方式

// HAL_UART_Transmit_DMA(&huart1, (uint8_t *)&ch, 1); //DMA方式

return ch;

}

发送修改后测试ok

那么接收是否需要增加状态判断,判断不忙或者IDLE时再接收?

最近简单使用了STM32,如上简单记录下.

串口配置参考

【STM32F4+CubeMX零基础快速入门】串口收发全攻略_哔哩哔哩_bilibili

printf重定向参考

基于 VsCode + GCC + STM32 环境下的串口输入输出重定向_gcc libc 重定向-CSDN博客

STM32 gcc与mdk下的printf重定向方式_gcc printf与keil printf-CSDN博客

相关推荐
qq_7556822406 小时前
STM32使用NRF2401进行数据传送
stm32·单片机·嵌入式硬件
FreakStudio12 小时前
开源一款串口舵机驱动扩展板-FreakStudio多米诺系列
单片机·嵌入式·大学生·电子diy
艾格北峰13 小时前
STM32 物联网智能家居 (六) OLED显示设备
arm开发·stm32·单片机·嵌入式硬件·物联网·智能家居
weixin_5358542216 小时前
oppo,汤臣倍健,康冠科技,高途教育25届春招内推
c语言·前端·嵌入式硬件·硬件工程·求职招聘
热爱嵌入式的小许17 小时前
STM32 HAL库&标准库+ESP8266+机智云
stm32·单片机·嵌入式硬件·stm32移植机智云·stm32连接机智云·hal库移植机智云·标准库移植机智云
无际单片机编程17 小时前
面对STM32的庞大体系,如何避免迷失在细节中?
java·stm32·单片机·嵌入式硬件·嵌入式开发
【云轩】18 小时前
【零基础实战】用STM32玩转DRV8313电机驱动:从原理到无人机/机器人控制
stm32·机器人·无人机
2301_7646022320 小时前
stm32hal库寻迹+蓝牙智能车(STM32F103C8T6)
stm32·单片机·嵌入式硬件
楼台的春风20 小时前
PWM(脉宽调制)技术详解:从基础到应用实践示例
c语言·stm32·单片机·嵌入式硬件·mcu·物联网·嵌入式
Jack1530276827921 小时前
芯谷D668:便携式录音机与耳机式盒式录音机的理想音频解决方案
嵌入式硬件·音视频·家庭影院·麦克风阵列处理器·便携式录音机·耳机式盒式录音机