嵌入式串口交互:在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