单片机中printf函数的重映射
- 格式:docx
- 大小:11.90 KB
- 文档页数:3
STM32 printf 函数重映射/* Private function prototypes -----------------------------------------------*/#ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker- >Libraries->Small printf set to Yes) calls __io_putchar() */ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endif /* __GNUC__ *//** * @brief Retargets the C library printf function to the USART. * @param None * @retval None */PUTCHAR_PROTOTYPE{ /* Place your implementation of fputc here */ /* Loop until the end of transmission */ while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET) {} /* write a character to the USART */ USART_SendData(EVAL_COM1, (uint8_t) ch);return ch;}某人的解释:这段代码的意思是将C 语言的库函数printf 重定向,或重映射,这词有点太专业,简单的讲:就是C 语言的库中printf 函数会调用PUTCHAR_PROTOTYPE 这个硬件接口函数,向显示器上输出char 型变量,用来显示,STM32 当然是没有显示器的,所以就用UART 输出Char 型变量到PC 机,由PC 机的超级终端来显示,说白了,就是原来送到显示器上的显示数据,现在送到STM32 的串口上;如果调不过去,你要注意两点:1.你的板子上用的是不是USART1,如果是,那连到PC 的串口,就可以在超级终端上,看到打印出来的东西了,如果不是,请参考第2 点.2.先将你的板子上的USART 初始化,然后把PUTCHAR_PROTOTYPE 函数体中的USART1 换成你现在用的那个USART.于免费送一个注意点,当然以上也都免费,呵呵1.STM32 的外设输出引脚可以重映射,如USART2,要注意板子上,是按原来的引。
stm32重定向printf的原理在嵌入式系统中,调试是一个非常重要的环节。
而在调试过程中,printf函数是最常用的调试手段之一。
在STM32中,printf函数默认是向串口发送数据,但是有时候我们需要将printf函数的输出重定向到其他设备或者接口上。
本文将以STM32为例,介绍如何实现printf函数的重定向。
一、printf函数的实现原理printf函数是C语言标准库中的一个输出函数,其原型为:int printf(const char *format, ...);。
printf函数的作用是将格式化的字符串输出到标准输出设备上。
在STM32中,默认情况下,printf 函数的输出设备是串口。
其实现原理如下:1.调用stm32fxxx_hal_uart.c中的HAL_UART_Transmit函数,将格式化的字符串发送到串口中。
2.在stm32fxxx_hal_uart.c中,HAL_UART_Transmit函数通过USARTx_SR寄存器判断发送是否完成,如果未完成,则等待发送完成。
3.发送完成后,HAL_UART_Transmit函数返回。
二、printf函数的重定向在某些情况下,我们需要将printf函数的输出重定向到其他设备或接口上,例如:SD卡、LCD屏幕、WiFi模块等。
这时候,我们需要自定义一个输出函数,并将其与printf函数关联起来,实现printf函数的重定向。
下面,我们将以重定向printf函数输出到LCD 屏幕为例,介绍如何实现printf函数的重定向。
1.定义一个输出函数我们先定义一个输出函数,将其命名为LCD_Printf,其实现原理如下:void LCD_Printf(char *str){/* 将格式化的字符串输出到LCD屏幕上 */}2.将LCD_Printf函数与printf函数关联在main函数中,我们需要将LCD_Printf函数与printf函数关联起来,代码如下:/* 重定向printf函数 */int fputc(int ch, FILE *f){/* 将字符转换成字符串 */char str[2] = {0};str[0] = ch;/* 调用LCD_Printf函数,将字符输出到LCD屏幕上 */LCD_Printf(str);return ch;}在上述代码中,我们定义了一个名为fputc的函数,该函数的作用是将printf函数的输出重定向到LCD屏幕上。
printf和scanf家族函数底层I/O函数重定向至串口神枪摘要:C标准库的printf是输出给显示器的,而scanf则是从键盘上把数据输入到指定的变量之中。
在ARM嵌入式开发中,往往需要通过串口进行一些调试、输入以及输出等。
那么,就得对这些家族函数的底层I/O函数进行修改,这样才能真正使用标准的C库printf和scanf家族函数。
一、概述和printf和scanf相关的家族函数包括:输出: printf、puts、putc、putchar、fprintf、fwrite、fputs等。
输入: scanf、gets、getc、getchar、fscanf、fread、fgets等。
被输入输出调用的底层I/O函数,包括fputc、fgetc、ferror等。
综上所述,我们只要将fputc和fgetc重新定向至串口就可以了!二、实现方法如果使用C标准库函数,则要避免链接使用半主机模式的相关函数,Retarge.c文件中的#pragma import(__use_no_semihosting_swi) 和 _sys_exit 函数实现就是来确保不链接半主机模式函数的。
好在Keil MDK已经为我们提供了这样的接口文件Retarge.c。
文件位置:C:\Keil\ARM\Startup,(C:\Keil\为我的Keil安装根目录)文件名称:Retarget.c文件内容:因此我们的工作就是:(1) 将该Retarget.c文件加入到自己的工程中。
(2) 提供Serial.c文件(名字随意),在文件中实现sendchar和getkey函数。
(3) sendchar为串口单字符发送函数,getkey为串口单字符接收函数。
这两个函数的实现如下:(1) 以LPC1758为例(2) 以STM32F103为例至此,所有工作已完毕,可以调用printf、scanf等函数了。
printf在单片机c语言中作用以printf在单片机c语言中的作用为题,需要详细介绍和解释printf函数在单片机中的作用和使用方法。
首先,我们来了解一下单片机和c语言的基本概念。
单片机是一种集成了微处理器、存储器和各种外设接口的微型计算机系统。
它通常用于控制和管理各种电子设备。
而c语言是一种通用的高级程序设计语言,广泛应用于嵌入式系统开发领域,尤其是在单片机编程中。
在单片机中,printf函数是一个非常重要的输出函数,它可以将格式化的数据打印输出到终端设备或其他输出设备上。
printf函数的语法格式如下:printf("格式控制字符串", 参数列表);其中,格式控制字符串用来定义输出的格式,它可以包含普通字符和格式转换说明符。
参数列表是一个可选项,用来指定要输出的数据。
printf函数可以输出各种类型的数据,如整数、浮点数、字符等。
下面我们通过一些具体的例子来说明printf函数的使用方法。
1. 输出整数型数据:int num = 123;printf("整数:%d\n", num);上述代码将会在终端上输出"整数:123"。
2. 输出浮点型数据:float f = 3.14;printf("浮点数:%f\n", f);上述代码将会在终端上输出"浮点数:3.140000"。
3. 输出字符型数据:char ch = 'A';printf("字符:%c\n", ch);上述代码将会在终端上输出"字符:A"。
4. 输出字符串:char str[] = "Hello World!";printf("字符串:%s\n", str);上述代码将会在终端上输出"字符串:Hello World!"。
简单地说:想在mdk 中用printf,需要同时重定义fputc函数和避免使用semihosting(半主机模式),标准库函数的默认输出设备是显示器,要实现在串口或LCD输出,必须重定义标准库函数里调用的与输出设备相关的函数。
例如:printf输出到串口,需要将fputc里面的输出指向串口(重定向),方法如下:#ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endif /* __GNUC__ */PUTCHAR_PROTOTYPE{/* Place your implementation of fputc here *//* e.g. write a character to the USART */USART_SendData(USART1, (uint8_t) ch);/* Loop until the end of transmission */while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);return ch;}因printf( )之类的函数,使用了半主机模式。
使用标准库会导致程序无法运行,以下是解决方法: 方法1.使用微库,因为使用微库的话,不会使用半主机模式.方法2.仍然使用标准库,在主程序添加下面代码:#pragma import(__use_no_semihosting)_sys_exit(int x){x = x;}struct __FILE{int handle;/* Whatever you require here. If the only file you are using is *//* standard output using printf() for debugging, no file handling *//* is required. */};/* FILE is typedef’ d in stdio.h. */FILE __stdout;如果使用的是MDK,请在工程属性的“Target-》Code Generation中勾选Use MicroLIB”;今天参考了一下论坛,使用微库可以很好的解决这个问题。
这个概念在嵌入式操作系统中比较重要,由于存在任务的调度,它实时系统,可剥夺型内核中是危险的,如同一个安静的水雷。
可能会被触发,也可能安然无恙。
由于它运行结果的不可预期性,会使系统带来隐患。
printf()经常有重入解释不可重入函数不可以在它还没有返回就再次被调用。
例如printf,malloc,free等都是不可重入函数。
因为中断可能在任何时候发生,例如在printf执行过程中,因此不能在中断处理函数里调用printf,否则printf 将会被重入。
函数不可重入大多数是因为在函数中引用了全局变量。
例如,printf会引用全局变量stdout,malloc,free 会引用全局的内存分配表。
个人理解:如果中断发生的时候,当运行到printf的时候,假设发生了中断嵌套,而此时stdout资源被占用,所以第二个中断printf等待第一个中断的stdout资源释放,第一个中断等待第二个中断返回,造成了死锁,不知这样理解对不对。
不可重入函数指的是该函数在被调用还没有结束以前,再次被调用可能会产生错误。
可重入函数不存在这样的问题。
不可重入函数在实现时候通常使用了全局的资源,在多线程的环境下,如果没有很好的处理数据保护和互斥访问,就会发生错误。
常见的不可重入函数有:printf --------引用全局变量stdoutmalloc --------全局内存分配表free --------全局内存分配表在unix里面通常都有加上_r后缀的同名可重入函数版本。
如果实在没有,不妨在可预见的发生错误的地方尝试加上保护锁同步机制等等。
下面引用一段别人的解释:这主要在多任务环境中使用,一个可重入的函数简单来说,就是:可以被中断的函数。
就是说,你可以在这个函数执行的任何时候中断他的运行,在OS的调度下去执行另外一段代码而不会出现什么错误。
而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等等,所以他如果被中断的话,可能出现问题,所以这类函数是不能运行在多任务环境下的。
单片机重映射随着科技的发展和应用的广泛,单片机(Microcontroller)在各个领域中得到了广泛的应用。
单片机重映射(Remapping)是指将单片机的引脚或者功能进行重新分配和配置,以满足特定应用需求的一种技术手段。
通过单片机重映射,可以使单片机具备更多的功能和扩展性,提高系统的灵活性和效率。
单片机重映射涉及到对单片机的引脚和功能进行重新配置,使其能够适应不同的应用场景。
在单片机设计中,通常会有一些功能模块或引脚需要被多个外设所共享,而这些外设可能需要在不同的时间段内使用。
为了解决这个问题,就需要对单片机进行重映射,将不同的功能或引脚分时使用,从而实现多个外设的共享。
单片机重映射的具体实现方法可以有多种,比较常见的有软件重映射和硬件重映射两种方式。
软件重映射是通过软件编程的方式实现的,通过对单片机的寄存器进行设置和配置,将某个引脚或功能从一个外设映射到另一个外设。
软件重映射的优点是灵活性高,可以根据需要随时进行配置和修改。
但是,软件重映射的缺点是需要占用额外的处理器资源和时间,并且可能会影响系统的实时性能。
硬件重映射是通过硬件电路的方式实现的,通过对单片机的引脚进行物理连接和切换,将某个引脚或功能从一个外设映射到另一个外设。
硬件重映射的优点是实时性好,不会影响系统的性能和时序要求。
但是,硬件重映射的缺点是配置和修改比较困难,需要设计和制造专门的硬件电路。
单片机重映射的应用非常广泛。
在嵌入式系统中,由于单片机的引脚和功能资源有限,需要通过重映射来实现多个外设的共享。
比如,一个单片机可能需要同时连接多个传感器、执行器和通信模块,通过重映射可以将不同的功能映射到不同的引脚上,从而实现多个外设的并行工作。
在工业控制系统中,单片机重映射也发挥着重要的作用。
工业控制系统通常需要连接大量的传感器、执行器和通信设备,通过重映射可以将不同的功能映射到不同的引脚上,从而实现系统的灵活配置和扩展。
单片机重映射还可以用于汽车电子、医疗设备、智能家居等领域。
printf在单片机c语言中作用在单片机编程中,printf是一个非常重要的函数,它用于将数据输出到标准输出设备,比如串口、LCD等。
使用printf函数可以方便地在调试过程中输出变量、调试信息等,帮助程序员进行错误定位和调试。
printf函数的基本语法如下:```cint printf(const char *format, ...);```其中,format是一个格式化字符串,用来指定输出的格式,...表示可以输入多个参数。
printf函数可以输出各种格式的数据,如字符、字符串、整数、浮点数等。
在格式化字符串中,可以使用一些转义字符来控制输出的格式,比如%c表示输出一个字符,%s表示输出一个字符串,%d 表示输出一个有符号十进制整数,%f表示输出一个浮点数等。
下面通过一些示例来说明printf函数的使用方法。
1. 输出字符```cchar ch = 'A';printf("输出一个字符:%c\n", ch);```输出结果为:输出一个字符:A2. 输出字符串```cchar str[] = "Hello, World!";printf("输出一个字符串:%s\n", str);```输出结果为:输出一个字符串:Hello, World!3. 输出整数```cint num = 123;printf("输出一个整数:%d\n", num);```输出结果为:输出一个整数:1234. 输出浮点数```cfloat f = 3.14;printf("输出一个浮点数:%f\n", f);```输出结果为:输出一个浮点数:3.140000除了基本的数据类型外,printf函数还支持输出其他类型的数据,如数组、结构体等。
5. 输出数组```cint arr[] = {1, 2, 3, 4, 5};int length = sizeof(arr) / sizeof(arr[0]);printf("输出一个数组:");for(int i = 0; i < length; i++){printf("%d ", arr[i]);}printf("\n");```输出结果为:输出一个数组:1 2 3 4 56. 输出结构体```cstruct student{char name[20];int age;};struct student stu;strcpy(, "Tom");stu.age = 18;printf("输出一个结构体:姓名:%s,年龄:%d\n", , stu.age);```输出结果为:输出一个结构体:姓名:Tom,年龄:18需要注意的是,printf函数在单片机中的使用需要借助相应的库函数,比如stdio.h头文件中的printf函数。
STM32单片机编程printf()函数重定向
在stm32 单片机编程中,可以重定向printf()函数来输出调试信息。
编写fputc()函数其实printf()函数在头文件中被定义成了一个宏,会调用到
fputc()函数,但在stm32 单片机编程中不可以直接调用标准库的fputc()函
数进行输出信息,需要自己编写fputc()函数供printf()函数来调用。
编译
器进行编译时首先会调用自己编写的fputc()函数,而不是库函数。
intfputc(int ch,FILE*f)
{
USART_SendData(USART1, (uint16_t)ch); //通过串口输出
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) !=SET);//等待输出完毕
return ch;
}
此时假定串口1 即USART1 可以正常通讯,fputc()函数的作用就是把
printf()函数重定向到串口1 上输出信息。
配置自己动手写好fputc()后,要在文件中包含stdio.h 文件。
#include 在MDK 软件界面单击Target options 按钮,在Code Genetation 一栏中选择Use MicroLIB 选项,即完成了配置,此时printf()函数一定重定向到了串口1 即USART1 上,可以正常使用printf()函数。
tips:感谢大家的阅读,本文由我司
收集整编。
仅供参阅!。
一、printf常用说明printf的格式控制的完整格式:% - 0 m.n l或h 格式字符下面对组成格式说明的各项加以说明:①%:表示格式说明的起始符号,不可缺少。
②-:有-表示左对齐输出,如省略表示右对齐输出。
③0:有0表示指定空位填0,如省略表示指定空位不填。
④m.n:m指域宽,即对应的输出项在输出设备上所占的字符数。
N指精度。
用于说明输出的实型数的小数位数。
为指定n时,隐含的精度为n=6位。
⑤l或h:l对整型指long型,对实型指double型。
h用于将整型的格式字符修正为short型。
----------------------------------格式字符格式字符用以指定输出项的数据类型和输出格式。
①d格式:用来输出十进制整数。
有以下几种用法:%d:按整型数据的实际长度输出。
%md:m为指定的输出字段的宽度。
如果数据的位数小于m,则左端补以空格,若大于m,则按实际位数输出。
%ld:输出长整型数据。
②o格式:以无符号八进制形式输出整数。
对长整型可以用"%lo"格式输出。
同样也可以指定字段宽度用“%mo”格式输出。
例:main(){ int a = -1;printf("%d, %o", a, a);}运行结果:-1,177777程序解析:-1在内存单元中(以补码形式存放)为(1111111111111111)2,转换为八进制数为(177777)8。
③x格式:以无符号十六进制形式输出整数。
对长整型可以用"%lx"格式输出。
同样也可以指定字段宽度用"%mx"格式输出。
④u格式:以无符号十进制形式输出整数。
对长整型可以用"%lu"格式输出。
同样也可以指定字段宽度用“%mu”格式输出。
⑤c格式:输出一个字符。
⑥s格式:用来输出一个串。
有几中用法%s:例如:printf("%s", "CHINA")输出"CHINA"字符串(不包括双引号)。
stm32重定向printf的原理在STM32的开发中,我们经常需要使用printf函数输出调试信息。
但是,由于STM32没有像PC一样的标准输出设备,我们需要通过串口或LCD等外设来实现printf函数的输出。
本文将介绍如何通过重定向printf函数来实现STM32的调试输出。
1. printf函数的实现原理printf函数是C语言标准库中的一个输出函数,它可以将格式化的字符串输出到标准输出设备上。
在PC机上,标准输出设备一般是控制台窗口,而在STM32上,则需要通过外设来实现。
在C语言中,printf函数的实现是由库函数提供的。
库函数将printf函数中的字符串格式化成一定的格式,然后将格式化后的字符串输出到标准输出设备上。
在PC机上,标准输出设备一般是stdout指向的文件流,而在STM32上,则需要将stdout指向相应的外设。
2. 重定向printf函数的实现原理重定向printf函数的实现原理是将标准输出设备stdout指向外设。
在STM32中,我们可以通过重定向printf函数来将stdout 指向串口或LCD等外设。
2.1 重定向到串口将printf函数重定向到串口,可以将调试信息通过串口输出到PC机上的串口调试助手等工具中,方便调试。
在重定向printf函数到串口前,需要先初始化串口。
以下是串口初始化的代码:```UART_HandleTypeDef huart;void MX_USART_Init(void){huart.Instance = USART1;huart.Init.BaudRate = 115200;huart.Init.WordLength = UART_WORDLENGTH_8B;huart.Init.StopBits = UART_STOPBITS_1;huart.Init.Parity = UART_PARITY_NONE;huart.Init.Mode = UART_MODE_TX_RX;huart.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart) != HAL_OK){Error_Handler();}}```在初始化串口后,需要重定向printf函数到串口。
stm32重定向printf的原理在STM32开发中,我们常常需要使用printf函数输出调试信息。
但是,由于STM32没有像PC一样的标准输出设备(如显示器或串口),因此需要将printf函数重定向到一个输出设备上。
本文将介绍如何在STM32中实现printf函数的重定向,并讨论其原理和实现方法。
一、printf函数的基本原理printf函数是C语言中常用的输出函数,可以将格式化的数据输出到标准输出设备(如显示器或串口)。
其原型为:int printf(const char *format, ...);其中format是格式化字符串,...表示可变参数。
printf函数会将format字符串中的占位符替换成实际的参数,并输出到标准输出设备上。
例如:printf('Hello, %s!', 'world');输出结果为:Hello, world!在PC开发中,printf函数的标准输出设备通常是控制台窗口。
但是,在嵌入式开发中,标准输出设备通常是串口或LCD屏幕等外设,因此需要将printf函数重定向到相应的输出设备上。
二、重定向printf函数的原理在STM32中,如果要将printf函数重定向到串口或LCD屏幕等外设上,需要定义一个名为_putchar的函数,该函数将输出字符送到外设上。
然后,通过重定向stdout流的方式,将printf函数的输出重定向到_putchar函数上。
1. 定义_putchar函数_putchar函数的原型如下:int _putchar(char ch)其中ch为要输出的字符。
在实现_putchar函数时,需要将ch送到串口或LCD屏幕等外设上,具体实现方法取决于外设的驱动方式。
例如,如果要将输出送到串口上,可以使用HAL库提供的串口发送函数:int _putchar(char ch){HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);return ch;}上述代码中,HAL_UART_Transmit函数用于将一个字节的数据送到串口上,huart1是串口句柄,1表示数据长度为1字节,0xFFFF表示超时时间为无限大。
单片机中printf函数的重映射
一、源自于:大侠有话说1.如果你在学习单片机之前学过C 语言,那么一定知道printf 这个函数.它最最好用的功能
除了打印你想要的字符到屏幕上外,还能把数字进行格式化.例如十进制的33, 用十进制
方式输出就是33,用十六进制的形式就输出成21,如果用字符形式输出,那就是ASCII 码
表对应的!.
2. 51 年代,一些人软件仿真的时候也很喜欢使用printf,但实际代码运行中,用的人则不多,因
为别说51 年代,就是用AVR 的,也会觉得printf 这个函数耗费的CPU 资源相当可观.所以
printf 在8 位单片机时代,熟悉的人的确不多.但到了ARM 时代,情况则大为不同.毕竟
ARM 的处理能力和51 完全不是一个级别,这使得不少人开始喜欢使用printf 在实际项目
中作为调试过程的串口输出.因为它的格式化功能实在是相当方便.
而本例程就是教会你这么使用printf.
3.程序把printf 的输出对象设定为串口1.有一个标准的函数是必须要自己定义的,那就是
fputc,把这个函数的功能写成串口输出一个字符.建议在串口的初始化模块中定义
int fputc(int ch)。