为了让多个串口可以同时实现printf输出,有两种方法:重定向fputc函数或自定义一个串口的printf函数。
目录
一、重定向fputc
写在usart.c中,实现串口1的printf输出
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
}
#endif
二、自定义printf函数
需要添加两个头文件:#include <stdarg.h> 、 #include <stdio.h>
并在函数之前对长度进行定义:
#define USART6_REC_LEN 256
extern size_t strlen(const char *);
/*
用固件库定义串口函数
1、申明头文件#include<stdarg.h>
2、buffer的大小根据需要调整,相应的循环条件也要改,此处可以定义成宏,方便调节buffer大小。
3、定义va_list变量,该变量是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。
4、va_start让arg_ptr指向printf函数可变参数里边的第一个参数;
5、vsnprintf()将按照fmt的格式将arg_ptr里的值依次转换成字符保存到buffer中,该函数有最大字符数限制,超过后会被截断,且该函数会自动在字符串末尾加‘\0’。
6、最后必须调用va_end(),由此确保堆栈的正确恢复。
*/
void USART6_printf(char *fmt, ...)
{
char buffer[USART6_REC_LEN+1]; // 数据长度
u8 i = 0;
va_list arg_ptr;
va_start(arg_ptr,fmt);
vsnprintf(buffer,USART6_REC_LEN+1,fmt,arg_ptr);
while ((i < USART6_REC_LEN) && (i < strlen(buffer)))
{
while((USART6->SR&0X40)==0);//循环发送,直到发送完毕
USART6->DR=(u8)buffer[i++];
}
va_end(arg_ptr);
}