stm32学习笔记----双串口同时打开时的printf()问题
2023-09-11 14:15:22 时间
stm32学习笔记----双串口同时打开时的printf()问题
最近因为要使用串口2外接PN532芯片实现通信,另一方面,要使用串口1来将一些提示信息输出到上位机,于是重定义了printf(),使其将打印的信息重定向至串口1。但是当在程序中调用printf()时,却发现上位机无论如何都接收不到信息,而且printf()之后的语句也不再执行,想必程序在printf()函数里面死掉了吧。当时觉得很纳闷,因为单独只使用一个串口时,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,PD6 RCC_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()内容发往串口1 USART_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也能正常打印;但这样太麻烦辣,每次打印一个字符。
于是网上查了一下,也有人遇到类似问题,而后评论下方有一个函数,说是可以双串口同时打开时,也可以一次性打印一串信息。抱着试一试的心态,将函数程序搬到我的工程中,没想到,还真行。下面贴出代码:
/* * 函数名: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 ); } }
相关文章
- ryu学习笔记(2) 之 ryu-manager运行报错
- V-rep学习笔记:Reflexxes Motion Library 2
- V-rep学习笔记:机器人逆运动学数值解法(The Pseudo Inverse Method)
- 【SpringMVC笔记】第四课 注解的处理器映射器和处理器适配器使用
- HTTP笔记(一)
- 《从零开始学Swift》学习笔记(Day 35)——会使用下标吗?
- 机器学习笔记 - 时间序列的趋势分量
- 机器学习笔记 - 什么是支持向量回归(SVR)?
- 数学建模学习笔记(二十三)灰色关联分析
- MyBatis 3学习笔记(二)
- 【数据结构笔记16】数据结构之图的四种存储结构(邻接矩阵、邻接表、十字链表、邻接多重表)
- Python:Python技巧之80个经典题——课程笔记(一)
- TypeScript学习笔记(四)—— TypeScript提高
- Java学习笔记六(I/O流)
- 《编程之美》学习笔记——指挥CPU占用率
- C++ Primer 学习笔记_38_STL实践与分析(12)--集成的应用程序容器:文本查询程序
- 知乎Live总结-重复nature文章笔记Single-cell
- Golang学习笔记
- STM32-嵌入式学习笔记03-EXTI中断的分析及应用
- C/C++学习笔记 各种字符转换记录
- C++学习笔记4--表达式