STM32 串口printf函数重映射

目录

前言:

1.在Scr文件夹下建立retarget.c文件

2.在Inc文件夹下建立retarget.h文件

3.屏蔽syscalls.c文件

目录

前言:

方法1:

1.在Scr文件夹下建立retarget.c文件

2.在Inc文件夹下建立retarget.h文件

3.屏蔽syscalls.c文件

4.包含头文件

5.重新编译

方法2:

1.原理

2.打印中文乱码设置

3.不能打印浮点数设置

总结:


4.包含头文件

5.重新编译



前言:

 基于CubeIDE环境+HAL库实现,作为学习记录使用。

printf函数是C语言函数库中自带的函数,最初用于电脑上使用C语言时,将需要显示的内容通过C语言库中的fputc函数打印到电脑屏幕,不同的C库中的fputc指向的输出目标也不是一样的,所以需要重定向。

方法1:

1.在Scr文件夹下建立retarget.c文件

        在Scr文件夹下建立retarget.c文件,并插入以下代码

// All credit to Carmine Noviello for this code
// https://github.com/cnoviello/mastering-stm32/blob/master/nucleo-f030R8/system/src/retarget/retarget.c
 
#include <_ansi.h>
#include <_syslist.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/times.h>
#include <limits.h>
#include <signal.h>
#include <../Inc/retarget.h>
#include <stdint.h>
#include <stdio.h>
 
#if !defined(OS_USE_SEMIHOSTING)
 
#define STDIN_FILENO  0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
 
UART_HandleTypeDef *gHuart;
 
void RetargetInit(UART_HandleTypeDef *huart) {
  gHuart = huart;
 
  /* Disable I/O buffering for STDOUT stream, so that
   * chars are sent out as soon as they are printed. */
  setvbuf(stdout, NULL, _IONBF, 0);
}
 
int _isatty(int fd) {
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
    return 1;
 
  errno = EBADF;
  return 0;
}
 
int _write(int fd, char* ptr, int len) {
  HAL_StatusTypeDef hstatus;
 
  if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
    hstatus = HAL_UART_Transmit(gHuart, (uint8_t *) ptr, len, HAL_MAX_DELAY);
    if (hstatus == HAL_OK)
      return len;
    else
      return EIO;
  }
  errno = EBADF;
  return -1;
}
 
int _close(int fd) {
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
    return 0;
 
  errno = EBADF;
  return -1;
}
 
int _lseek(int fd, int ptr, int dir) {
  (void) fd;
  (void) ptr;
  (void) dir;
 
  errno = EBADF;
  return -1;
}
 
int _read(int fd, char* ptr, int len) {
  HAL_StatusTypeDef hstatus;
 
  if (fd == STDIN_FILENO) {
    hstatus = HAL_UART_Receive(gHuart, (uint8_t *) ptr, 1, HAL_MAX_DELAY);
    if (hstatus == HAL_OK)
      return 1;
    else
      return EIO;
  }
  errno = EBADF;
  return -1;
}
 
int _fstat(int fd, struct stat* st) {
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) {
    st->st_mode = S_IFCHR;
    return 0;
  }
 
  errno = EBADF;
  return 0;
}
 
#endif //#if !defined(OS_USE_SEMIHOSTING)

2.在Inc文件夹下建立retarget.h文件

        在Inc文件夹下建立retarget.h文件,并插入以下代码

// All credit to Carmine Noviello for this code
// https://github.com/cnoviello/mastering-stm32/blob/master/nucleo-f030R8/system/include/retarget/retarget.h
 
#ifndef _RETARGET_H__
#define _RETARGET_H__

 
#include "stm32f1xx_hal.h" //这里根据自己的单片机型号做修改
#include <sys/stat.h>
 
void RetargetInit(UART_HandleTypeDef *huart);
int _isatty(int fd);
int _write(int fd, char* ptr, int len);
int _close(int fd);
int _lseek(int fd, int ptr, int dir);
int _read(int fd, char* ptr, int len);
int _fstat(int fd, struct stat* st);

 
#endif //#ifndef _RETARGET_H__//如果使用cubeide生成会包含#ifnde   #define   #endif  需要去重复

3.屏蔽syscalls.c文件

        在Src文件夹下右键syscalls.c点击属性

        取消源码构建

4.包含头文件

        在主函数main.c文件下包含头文件,并将printf()函数映射到指定的串口

      包含头文件:  

#include "../inc/retarget.h"   //用于printf函数串口重映射

        printf()映射到指定的串口

RetargetInit(&huart1); //映射大UART1上

5.重新编译

       保存并 重新编译后即可使用printf()函数

方法2:

1.原理

先看源码:实际上printf()函数是调用extern int __io_putchar(int ch) __attribute__((weak));函数将字符一个一个的打印出来,但实际上这个函数并没有实现,需要我们自己实现

在main函数中添加


/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

int __io_putchar(int ch)
{
	HAL_UART_Transmit(huart1, (const uint8_t *)&ch, 1, 1000);
	return ch;
}

2.打印中文乱码设置

右键工程->属性按下图将编码改为GBK

3.不能打印浮点数设置

总结:

两种方法的实质是一样的,都是先指定串口再重写函数,方法1比较全面,方法只写了发送,比较简略,任君选择参考。

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
retarget.h文件是一个头文件,通常用于嵌入式系统中的编译器和操作系统的新定向功能。这个文件定义了一些定向函数,用于定向标准输入、输出和错误流。 在嵌入式系统中,通常没有标准输入输出设备,如控制台或终端。相反,系统可能使用串口、网络或其他专门的输入输出设备进行通信。在这种情况下,就需要使用定向功能将用户输入和程序输出导向到相应的设备。 retarget.h文件中定义了一些定向函数,如 _ttywrch、_sys_exit、_isatty 和 _write 等。这些函数可以根据系统的需要进行自定义实现,以实现对标准输入输出和错误流的定向。 在 _ttywrch 函数中,将从标准输入获取的字符发送到特定的设备,例如串口。_sys_exit 函数用于程序终止时的处理,可能会涉及到关闭设备、释放资源等操作。_isatty 函数判断一个文件描述符是否连接到一个终端设备。_write 函数用于将字符或字符串发送到特定设备。 通过在retarget.h文件中定义这些函数的自定义实现,可以根据实际的硬件、操作系统和编译器环境,将标准输入输出和错误流定向到合适的设备,以实现与用户或其他设备的交互。 总的来说,retarget.h文件是用于嵌入式系统中的编译器和操作系统的新定向功能的头文件,通过定义一些定向函数,实现将标准输入输出和错误流定向到特定设备的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值