在CLion中重定向scanf()和printf()函数至串口#STM32

嵌入式串口交互:在CLion中链接的是GNU-Tools-ARM-Embedded\arm-none-eabi\include里面的stdio.h,需重构syscalls.c中以下回调函数或者在项目中添加retarget.h和.c文件并注释掉syscalls.c中同名函数:

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)

新建一个retarget.h文件内容如下:

#ifndef _RETARGET_H__
#define _RETARGET_H__

#include "stm32f1xx_hal.h"
#include <sys/stat.h>
#include <stdio.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__

再新建一个retarget.c文件内容如下:

#include <_ansi.h>
#include <_syslist.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/times.h>
#include <retarget.h>
#include <stdint.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;
}

需要注意的是:printf()和scanf()都是用轮询方式,没有使用中断。调用scanf()在串口助手中输入数据时,必须以空格结束,然后点击发送,否则无法完成发送(mcu会认为串口一直没有收到数据),一直处于判断串口Flag的状态(__HAL_UART_GET_FLAG()),陷入UART_WaitOnFlagUntilTimeout()函数下的while循环当中出不来。

附上调试成功后的效果:串口交互 Hello world!

main.c中添加代码:

#include "retarget.h"

UART_HandleTypeDef huart1;    //声明串口句柄
MX_USART1_UART_Init();        //STM32CubeMX生成

RetargetInit(&huart1);

int main(void)
{
    // 此处省略初始化代码
    while (1)
    {
        char buff[100];
        printf("\r\n Your name:");
        scanf("%s",buff);
        printf("\r\nHello,%s!\r\n",buff);
        return 0;
    }
}

串口助手传送门:【免费】串口助手/串口调试工具资源-CSDN

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值