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博客

相关推荐
Mortal_hhh10 分钟前
VScode的C/C++点击转到定义,不是跳转定义而是跳转声明怎么办?(内附详细做法)
ide·vscode·stm32·编辑器
深圳市青牛科技实业有限公司23 分钟前
【青牛科技】应用方案|D2587A高压大电流DC-DC
人工智能·科技·单片机·嵌入式硬件·机器人·安防监控
Mr.谢尔比1 小时前
电赛入门之软件stm32keil+cubemx
stm32·单片机·嵌入式硬件·mcu·信息与通信·信号处理
LightningJie1 小时前
STM32中ARR(自动重装寄存器)为什么要减1
stm32·单片机·嵌入式硬件
鹿屿二向箔1 小时前
STM32外设之SPI的介绍
stm32
西瓜籽@2 小时前
STM32——毕设基于单片机的多功能节能窗控制系统
stm32·单片机·课程设计
远翔调光芯片^138287988724 小时前
远翔升压恒流芯片FP7209X与FP7209M什么区别?做以下应用市场摄影补光灯、便携灯、智能家居(调光)市场、太阳能、车灯、洗墙灯、舞台灯必看!
科技·单片机·智能家居·能源
极客小张5 小时前
基于STM32的智能充电桩:集成RTOS、MQTT与SQLite的先进管理系统设计思路
stm32·单片机·嵌入式硬件·mqtt·sqlite·毕业设计·智能充电桩
m0_739312878 小时前
【STM32】项目实战——OV7725/OV2604摄像头颜色识别检测(开源)
stm32·单片机·嵌入式硬件
嵌入式小章8 小时前
基于STM32的实时时钟(RTC)教学
stm32·嵌入式硬件·实时音视频