-
2021-03-08 10:13:49
STM32 串口打印函数
#include <stdarg.h> #include "main.h" #include "string.h" #include "usart.h" #include "usart_printf.h" #define TXBUF_SIZE_MAX 100 //串口输出 void usart_printf(UART_HandleTypeDef *huart,const char *format, ...) { va_list args; uint32_t length; uint8_t txbuf[TXBUF_SIZE_MAX] = {0}; va_start(args, format); length = vsnprintf((char *)txbuf, sizeof(txbuf), (char *)format, args); va_end(args); HAL_UART_Transmit(huart, (uint8_t *)txbuf, length, HAL_MAX_DELAY); memset(txbuf, 0, TXBUF_SIZE_MAX); }
更多相关内容 -
串口打印函数引起芯片工作异常
2022-02-14 11:39:08单片式开发中的串口调试在调试供应商提供的SDK源码时发现,在某个初始化函数中添加
printf
函数打印调试信息会导致原本正常工作的芯片无法工作。在其他函数使用printf
函数则不会出现该问题,说明串口功能的配置以及printf
函数的重定向均没有问题。
经过在线调试发现,程序卡死在printf
函数重定向中判断串口标志位的while
循环中,因此导致其他功能为正常工作。int fputc(int ch, FILE *f) { /* 将printf内容发往串口 */ USART_SendData(USART1, (unsigned char) ch); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // 卡死位置 return (ch); }
据此判断,该问题的出现跟串口有关。回到
main
函数时猛然发现如下代码:int main() { // ... dev_init(); // 在函数中添加printf函数就会导致上述问题 usart_config(); printf("demo application starting ... \r\n"); while(1) { // ... } }
好家伙~原来是因为在串口初始化完成之前调用了
dev_init();
函数,正是在dev_init();
函数中调用printf
函数导致芯片工作异常。原因是显而易见的,是因为在串口初始化完成之前调用了串口输出函数,相应的串口标志位一直为RESET
,导致程序陷入死循环。问题找到了,解决方案也自然明了了,将dev_init();
函数调整到usart_config();
后面即可。【敲黑板】
- 串口相关函数自身(如
printf
函数)及其调用者(如本文中的dev_init();
函数)应当在串口初始化完成之后被调用。 - 不要因为是原厂提供的SDK就默认其代码是没有问题的。
- 串口相关函数自身(如
-
基于HAL库的多串口打印函数(XL_Printf)
2021-12-15 10:50:05基于HAL库的多串口打印函数(XL_Printf) 本文参考以下文章: https://blog.csdn.net/sehanlingfeng/article/details/80383117 https://baike.baidu.com/item/va_list/8573665?fr=aladdin 一、重定向Printf的局限...基于HAL库的多串口打印函数(XL_Printf)
本文参考以下文章:
https://blog.csdn.net/sehanlingfeng/article/details/80383117
https://baike.baidu.com/item/va_list/8573665?fr=aladdin一、重定向Printf的局限性
- 使用重定向函数,需要添加
stdio.h
头文件
// 重定向函数1 int fputc(int ch,FILE *f) { uint8_t temp[1]={ch}; HAL_UART_Transmit(&UartHandle,temp,1,2); //UartHandle是串口的句柄 } //重定向函数2 PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&UARTHandle, (uint8_t *)&ch, 1, 0xFFFF); return ch; }
- 采用上述函数会存在以下问题
Printf
函数只用用于单一串口发送,想要用于多函数发送则需要将UartHandle
定义成全局变量,通过更改UartHandle
来实现发送串口的更换,不符合代码低耦合的要求,对于自定义发送不适合。
二、
va_list
方法va_list
是在C语言中解决变参问题的一组宏,所在头文件:#include <stdarg.h>
,用于获取不确定个数的参数。
#ifdef _M_ALPHA typedef struct { char *a0; /* pointer to first homed integer argument */ int offset; /* byte offset of next parameter */ } va_list; #else typedef char * va_list; #endif
_M_ALPHA是指DEC ALPHA(Alpha AXP)架构。所以一般情况下va_list所定义变量为字符指针。
INTSIZEOF 宏,获取类型占用的空间长度,最小占用长度为int的整数倍: #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) VA_START宏,获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是可变参数最左边的参数): #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) VA_ARG宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数描述了当前参数的类型): #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) VA_END宏,清空va_list可变参数列表: #define va_end(ap) ( ap = (va_list)0 )
- 原理不懂也没关系,直接用吧。
三、XL_Printf多串口打印函数
- 函数代码
#include <stdarg.h> /*-----串口发送函数---------------- 带字符解析的发送函数 ----------------------------------*/ uint8_t XL_Printf(UART_HandleTypeDef *huart,const char *format, ...) { char buf[512]; //定义临时数组,根据实际发送大小微调 va_list args; va_start(args, format); uint16_t len = vsnprintf((char *)buf, sizeof(buf), (char *)format, args); va_end(args); return HAL_UART_Transmit(huart,buf,len,1000); //串口打印函数,可以更换为中断发送或者DMA发送 }
- 使用方式与Printf函数一致
printf("%daaaabbbb%s%e",1,"gg",2000.3); XL_Printf(&huart1,"%daaaabbbb%s%e",1,"gg",2000.3);
其中串口号
&huart1
可以更换为其他串口 - 使用重定向函数,需要添加
-
串口打印函数,串口驱动
2014-01-24 22:12:33uart串口打印函数,c语言开发,通过配置寄存器,串口驱动打印。 -
Arduino Serial.print()串口打印函数
2021-09-17 17:09:55Arduino Serial.print()串口打印函数 将数据打印到串口,作为人类可读的ASCII文本。该命令可以采用多种形式。每个数字都使用ASCII字符打印。小数以类似的方式打印为ASCII数字,默认为两个小数点。字节作为单个字符...Arduino Serial.print()串口打印函数 将数据打印到串口,作为人类可读的ASCII文本。该命令可以采用多种形式。每个数字都使用ASCII字符打印。小数以类似的方式打印为ASCII数字,默认为两个小数点。字节作为单个字符发送。字符和字符串按原样发送。例如,
Serial.print(78)
//78Serial.print(1.23456)"
//1.23Serial.print('N')
//NSerial.print("Hello world.")
//Hello world
第二个可选参数指定要使用的基(格式);允许的值是BIN(二进制,或基数2),OCT(八进制,或基数8),DEC(十进制,或基数10),HEX(十六进制,或基数16)。对于浮点数,此参数指定要使用的小数位数。例如,
Serial.print(78, BIN)
//1001110Serial.print(78, OCT)
//116Serial.print(78, DEC)
//78Serial.print(78, HEX)
//4ESerial.print(1.23456, 0)
//1Ser
-
开发常用串口打印数据函数-printf_debug_log
2020-08-13 20:11:28串口打印函数-printf_debug_log 记录一下自己常用的串口打印函数,常用语抓包分析。 void printf_debug_log(uint8_t *buff, uint32_t len,bool flag) { static uint32_t print_cnt = 0; if(print_cnt ==0) { if... -
自定义函数实现单片机任意串口的printf()
2018-11-27 19:14:18自定义函数实现单片机任意串口的printf(),代码是51单片机实现效果,可移植到任意单片机。 -
STM32实现串口printf函数打印
2020-03-21 21:49:42一、串口设置 1. 异步模式 2. 参数 3. 只是作为发送,则可以不开中断 4. 生成代码如下 /* USART6 init function */ static void MX_USART6_UART_Init(void) { huart6.Instance = USART6; huart6.Init.BaudRate... -
单片机不支持printf函数,实现几个常用串口打印函数
2016-12-04 13:07:37在单机开发中经常使用串口调试或者收集实时各种数据类型不同的数据少不了使用printf()函数重定向,但是对于资源紧缺的单片机使用printf(),性能不佳。为了以后工作方便,把几个常用的打印函数记录下来。 整数打印 -
STM32之HAL例程分析-串口输出函数printf打印调试信息
2022-02-27 08:15:04HAL例程中使用句柄UartHandleTypedef 完成对串口通用参数的初始化,串口的底层硬件初始化则在函数HAK_UART_Init中的HAL_UART_MspInit函数中实现。 int main(void) { HAL_Init(); SystemClock_Config(); BSP_... -
自编串口打印函数
2012-02-24 11:22:58调试内核时,因为启动初期串口和printk都不...所以自己编写了串口打印函数。 void print_s(char *s){ while(*s!=0){ while(!((*(unsigned char *)0xf0532014) & 32)); //等待串口缓冲区空 *(unsigned -
STM32标准库自定义串口打印 log.7z
2020-08-25 17:22:49STM32的串口打印,支持不定长参数,调试时用,可以通过一个宏定义关闭所有的调试信息,方便调试。******************************/ -
自定义DSP串口输出实现可变参打印函数
2021-03-24 09:46:21在dsp串口驱动输出上实现类似于printf函数的可变参打印输出效果。串口驱动代码自行根据使用DSP处理器编写,本文不实现串口驱动和初始化。只实现变参输入转换过程函数。...// 串口打印输出 void uart_printf(char * fmt -
51单片机串口打印乱码的解决方法
2020-08-03 05:14:23我使用的是stc的89c52rc型号,晶振是12m。是因为买的最小系统就是这个频率。使用波特率位9600,将TL、TH都设置成0xfd后不管是英文还是中文的都是乱码。 -
Arduino常用串口操作函数
2020-06-06 08:01:11本文总结了Arduino常用串口操作函数,函数说明部分来源于Arduino 官网串口使用指南,示例与实验部分为自编。本文是对Arduino串口操作函数的较全面总结,可作为工具贴查找使用。 1.串口设置 Serial.begin(); 说明 ... -
51单片机串口通信调试printf函数重定向输出打印
2021-05-14 09:59:2351单片机串口通信以及printf调试串行通信1.串口初始化串口工作方式波特率设置通过软件直接生成串口初始化代码2.输出到串口3.发送字符串到串口4.printf重定向到串口5.补充printf格式化输出 串行通信 不知道你们写... -
串口打印数据
2021-05-10 09:06:27单片机通过串口打印数据,方便调试。 重定向 重定向printf很简单,我们知道,printf函数是调用putchar实现字符数据传送的。我们只要重写putchar函数,就可以对printf进输出重定向。 #include<stdio.h> /... -
STM32F107官方移植工程中,钩子函数中不能使用串口打印函数 APP_TRACE_INFO();
2018-12-18 16:06:13UCOSIII,STM32F107官方移植工程中,钩子函数中不能使用串口打印函数 APP_TRACE_INFO(); 未找到原因。 -
STM32串口打印
2021-12-14 13:50:03STM32串口打印 -
51单片机通过串口打印调试信息。
2021-09-02 14:59:43利用stc89C52的单片机的串口发送数据到电脑的串口助手中,打印出来信息; 这里如果换没学到串口的知识,那么可以跳过,或者简单学习下串口的知识。 直接调用一个函数就行,这个函数是利用51单片机 -
51单片机串口printf函数
2010-05-09 20:57:1751单片机串口printf函数,c格式,和标准pirntf用法相似,好用 -
一文了解串口打印
2020-11-10 09:16:34有些环境不方便连接Jlink进行硬件仿真,或者并不是必现的问题,我们需要定位出现问题的地方,可以选择保存log的方式,但是需要后续读取,且受到Flash大小的限制,如果可以放置一台计算机到现场,使用串口打印无疑是... -
printf()函数重定向到STM32串口输出
2020-08-03 11:33:19最近遇到需要MCU输出数字的问题,而STM32的串口输出的是字符型,最先想到的方法是将整型数据转换为字符型输出,C库函数中提供了相关的函数 。 -
HAL库+CubeMX+Stm32F405 实现串口定长收发、printf函数使用、自定义打印函数
2020-07-23 16:32:10HAL库+CubeMX+Stm32F405 实现串口定长收发、printf函数使用、自定义打印函数 详情请看:https://lindoglog.blog.csdn.net/article/details/107463926 -
STM32 KEIL 串口打印printf使用详解
2020-05-19 10:15:02常规打印方法 在STM32的应用中,我们常常对printf进行重定向的方式来把打印信息printf到我们的串口助手。在MDK环境中,我们常常使用MicroLIB+fputc的方式实现串口... -
STM8学习笔记---串口printf函数的实现
2020-04-08 17:18:20在使用单片机的时候,串口是要经常使用的功能,特别是在调试代码的过程中,经常需要使用串口打印出某些变量值,来判断程序执行流程是否正常。但是单片机默认情况下没有printf函数,如果需要使用printf函数的功能,就... -
一、hal库。stm32使用printf函数打印到串口
2020-04-14 21:46:02stm32使用printf函数打印到串口1.缘由2操作步骤3验证方式4遇到的坑5结尾 本项目使用到的软件 1. stm32cubeMX 2. sw4stm32 3. 串口助手 *以下所有带代码均在sw4stm32中编写,项目的初始化和生成都由stm32cubeMX生成。... -
单片机技术C51串口输出输入函数
2020-07-25 16:32:11本文给大家介绍了单片机技术C51串口输出输入函数。 -
浮点数在串口打印函数
2015-12-24 22:33:14/****************************************...网上的浮点数在串口打印的函数都不太完美,于是参考他们的一些算法自己写了一个比较完善的算法 可以完成包括负数和正数的浮点数转字符串的转换 *********************** -
定制自己的printf函数——以stm32串口打印为例
2019-12-30 14:55:13这个函数不仅在调试软件代码的时候经常有使用,单片机开发时也经常用于串口打印调试。所以,在此就如何让单片机使用printf来调试代码,开始接下来的学习,在此,请允许我以stm32hal库为例。 首先,要求开发环境支持...