目录:
一、概述
二、设置标志位选择需要的串口
三、更优解决方法
一、概述
printf()函数非常好用,但是重定义后只适用于单个串口,需要串口2使用printf(),需要重新定向。有关内容移步STM32关于printf重定向到串口。先贴一下双串口的配置和printf()的书写,mark一下。
void USART_Config()
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;//配置串口1时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);//配置串口2时钟,使用复用功能,打开AFIO,管脚重映射到PD5,PD6RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);/*配置串口1(USART1 Tx(PA.09))*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); /* 配置串口1(USART1 Tx(PA.10))*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);/*串口1工作模式(USART1 mode)配置 */USART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No ;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE);//使能串口/*配置串口2(USART2 Tx(PD.05))*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOD, &GPIO_InitStructure);/*配置串口2(USART2 Tx(PD.05))*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOD, &GPIO_InitStructure);/*串口2工作模式(USART2 mode)配置 */USART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStructure); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);USART_Cmd(USART2, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /*串口2中断配置*/ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}/*printf()函数重定向*/
int fputc(int ch, FILE *f)
{//将printf()内容发往串口1USART_SendData(USART1, (unsigned char) ch);while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET); return (ch);
}
当只开串口1时,printf()可以正常使用,但是同时使用串口1和串口2时,使用printf()就会输出不了信息,并且程序无法往下执行。若不用printf()函数,而直接使用USART_SendData(USART1,(unsigned char) ch)时,串口1也能正常打印;但这样太麻烦,每次打印一个字符。
二、设置标志位选择需要的串口
//标志量定义
int USART_PRINTF_FLAG = 2;//默认串口2//改写fputc
int fputc(int ch, FILE *f)
{if (USART_PRINTF_FLAG == 2){while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET);USART_SendData(USART2,(uint8_t)ch);}else{while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);USART_SendData(USART1,(uint8_t)ch);}return ch;
}
三、更优解决方法
/*
* 函数名:itoa
* 描述 :将整形数据转换成字符串
* 输入 :-radix =10 表示10进制,其他结果为0
* -value 要转换的整形数
* -buf 转换后的字符串
* -radix = 10
* 输出 :无
* 返回 :无
* 调用 :被USART_printf()调用
*/
static char *itoa(int value, char *string, int radix)
{int i, d;int flag = 0;char *ptr = string;/* This implementation only works for decimal numbers. */if (radix != 10){*ptr = 0;return string;}if (!value){*ptr++ = 0x30;*ptr = 0;return string;}/* if this is a negative value insert the minus sign. */if (value < 0){*ptr++ = '-';/* Make the value positive. */value *= -1;}for (i = 10000; i > 0; i /= 10){d = value / i;if (d || flag){*ptr++ = (char)(d + 0x30);value -= (d * i);flag = 1;}}/* Null terminate the string. */*ptr = 0;return string;} /*
* 函数名:USART_printf
* 描述 :格式化输出,类似于C库中的printf,但这里没有用到C库
* 输入 :-USARTx 串口通道
* -Data 要发送到串口的内容的指针
* -... 其他参数
* 输出 :无
* 返回 :无
* 调用 :外部调用
* 典型应用USART_printf( USART1, "\r\n this is a demo \r\n" );
* USART_printf( USART2, "\r\n %d \r\n", i );
* USART_printf( USART3, "\r\n %s \r\n", j );
*/
void USART_printf(USART_TypeDef* USARTx, uint8_t *Data,...)
{const char *s;int d; char buf[16];va_list ap;va_start(ap, Data);while ( *Data != 0) // 判断是否到达字符串结束符{ 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_TC) == RESET );}Data++;break;case 'd': //十进制 d = va_arg(ap, int);itoa(d, buf, 10);for (s = buf; *s; s++) {USART_SendData(USARTx,*s);while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );}Data++;break;default:Data++;break;} } /* end of else if */else USART_SendData(USARTx, *Data++);while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );}
}
原文出处:多串口同时打开时的printf()问题。
人生如逆旅,我亦是行人。觉得不错,动动发财的小手点个赞哦!