STM32下多串口用法

时间:2023-03-08 21:59:41

一个项目用到32下的多个串口,一般STM32C8T6型号拥有3个USART,串口的配置都很简单,但是要使用的话就得解决他们之间的矛盾,

printf函数到底输出在哪一个串口中?

先看这函数:

//重定义fputc函数,方便使用printf
int fputc(int Data, FILE *f)
{
while(!USART_GetFlagStatus(USART1,USART_FLAG_TXE)); //USART_GetFlagStatus:得到发送状态位
//USART_FLAG_TXE:发送寄存器为空 1:为空;0:忙状态
USART_SendData(USART1,Data); //发送一个字符 return Data; //返回一个值
}

在我们使用printf函数的时候,首先必须重定义fputc函数,在这个函数中,实现数据的发送,然后在     USART_SendData(USART1,Data);  中选择需要的串口。一般是选择串口1,所以这种情况下,

使用printf函数会打印到串口1。

那么我要用到串口2的printf函数该怎么办呢 ?

配置什么的还是和串口1一样,
1.配置usart2的串口配置,gpio,rcc enable。。。。
2.勾选usb micro lib,
3.添加头文件#include <stdarg.h>,编写USART2的printf函数:

void USART2_printf (char *fmt, ...)
{
char buffer[CMD_BUFFER_LEN+]; // CMD_BUFFER_LEN长度自己定义吧
u8 i = ; va_list arg_ptr;
va_start(arg_ptr, fmt);
vsnprintf(buffer, CMD_BUFFER_LEN+, fmt, arg_ptr);
while ((i < CMD_BUFFER_LEN) && buffer)
{
USART_SendData(USART2, (u8) buffer[i++]);
while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
}
va_end(arg_ptr);
}

仔细看我们会发现,其实这个函数中包含了fputc,然后吧   USART_SendData(USART1,Data);   改为  USART_SendData(USART2,(u8)buffer[i++]);   循环通过串口2发送。

还有一种方法就是自己实现 printf的源码(参考秉火程序):

/*
* 函数名:USART2_printf
* 描述 :格式化输出,类似于C库中的printf,但这里没有用到C库
* 输入 :-USARTx 串口通道,这里只用到了串口2,即USART2
* -Data 要发送到串口的内容的指针
* -... 其他参数
* 输出 :无
* 返回 :无
* 调用 :外部调用
* 典型应用USART2_printf( USART2, "\r\n this is a demo \r\n" );
* USART2_printf( USART2, "\r\n %d \r\n", i );
* USART2_printf( USART2, "\r\n %s \r\n", j );
*/
void USART2_printf ( USART_TypeDef * USARTx, char * Data, ... )
{
const char *s;
int d;
char buf[]; va_list ap;
va_start(ap, Data); while ( * Data != ) // 判断是否到达字符串结束符
{
if ( * Data == 0x5c ) //'\'
{
switch ( *++Data )
{
case 'r': //回车符
USART_SendData(USARTx, 0x0d);
Data ++;
break; case 'n': //换行符
USART_SendData(USARTx, 0x0a);
Data ++;
break; default:
Data ++;
break;
}
} else if ( * Data == '%')
{ //
switch ( *++Data )
{
case 's': //字符串
s = va_arg(ap, const char *); for ( ; *s; s++)
{
USART_SendData(USARTx,*s);
while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );//程序死在了这
} Data++; break; case 'd':
//十进制
d = va_arg(ap, int); itoa(d, buf, ); for (s = buf; *s; s++)
{
USART_SendData(USARTx,*s);
while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
} Data++; break; default:
Data++; break; }
}
else USART_SendData(USARTx, *Data++);
while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET ); }
}

然后在这里面修改串口号就可以。

参考资料:https://blog.****.net/xzongyuan/article/details/28626163