单片机中printf函数的运用

合集下载

单片机C语言实现printf

单片机C语言实现printf

单片机串口实现printf函数背景叙述:在初学C语言时,利用printf函数向屏幕上输出字符,非常的好用和方便。

学会单片机以后,尤其在学会串口通信之后,通过单片机的串口向PC机发送数据,怎么实现printf函数的功能。

对于学习单片机来说,如果没有仿真器,出错误的时候不好找,只能用最笨的办法,使用printf函数,可是在KEIL里面使用printf却不像VC里面那么简单,因为其发送和硬件是有关系的。

所以今天就简单来说说怎么在51单片机中使用"printf"函数:包括使用自带的printf函数和自己动手写一个printf函数功能描述:通过printf函数向串口发送数据,显示在终端或者串口助手上Proteus中串口终端的介绍2、串口的配置尤其注意配置的波特率一定要和程序代码中所写的一样(否则会造成无法显示字符)数据位停止位奇偶校验位极性(这些属性基本上是默认的配置)3、串口终端的使用proteusvirtualterminal使用注意事项a.virtualterminal默认显示字符,如果单片机发送的是非显示字符,则虚拟终端不会显示,会导致用户认为通讯未通。

运行程序,在虚拟终端窗口里面点击右键,在弹出菜单里面:选HEXDISPLAYMODEU显示按十六进制显示,能显示所有字符。

b.virtualterminal默认情况下不显示回显字符,运行程序,在虚拟终端窗口里面点击右键,在弹出菜单里面:选EchoTypedCharacters显示回显字符c.virtualterminal和模拟物理串口COMPIM不能同时使用,同时使用会发生相互影响。

d.启动仿真后可以右键单击终端,最后一栏打开和关闭串口显示终直接使用系统自带的printf函数:特别注意需要置位TI=1,否则是无法发送的,程序如下(此程序在proteus终端上不能显示汉字,但在串口调试助/******decription ******************手上可以)利用printf函数向串口打印信息51单片机晶振频率11.0592MHZ 串口通信波特率9600bps******* includesfile ************* **********************************『#include<reg51.h>#include<intrins.h>#include<string.h>#include<stdio.h>#defineucharunsignedchar #defineuintunsignedintvoiddelay_1ms(uintz){uintx,y;for(x=z;x>0;x--)for(y=110;y>0;y--); }voiduart_init(void)TMOD=0x20;〃定时计数器1,工作方式2TH1=0xFD;〃设置波特率9600TL1=0xFD;TR1=1;SCON=0x50;PCON=0x00;EA=1;ES=1;TI=1;〃若利用printf函数则TI初始值必须置1 )voidmain()(uart_init();while(1)(//SBUF='H';//while(TI==0);//TI=0;printf("iamherro!\n\r");delay_1ms(1000);(ff=0;printf("%c",num);)))voidser_interrupt()interrupt4(if(RI==1)(ES=0;RI=0;num=SBUF;ES=1;ff=1;))4.编写自己的printf函数(这个函数不能再proteus中仿真,但实际中可以使用)a.预备知识①C语言函数:vsprintf,其原型为intvsprintf(char*string,char*format,va_listparam);,作用为将param按格式format写入字符串string中,因此他可以用于将任何格式数据转化为字符串数据,比如把整数97转化为ASCII码的97的程序就像下面这样vsprintf(string,"%d",97),当然还有一点需要注意:在keil 里面使用sprintf需要包含stdio.h这个头文件(当然这里也可以使用sprintf,作用完全差不多,只需要稍加修改即可,不多介绍)。

关于printf的详细分析陈

关于printf的详细分析陈
*
*Exceptions:
*,诠释_flush(流) - 刷新缓冲区的一个单一的流
unsigned char y;
char putchar (char c)
{
disp(x,y,8,16,ZF+(c-ASCII)*16);
x+=8; //每个字符占8个像素
return c;
}
//扩展的printf //带x y坐标的printf (可不要)
//用在单片机中 x,y为全局坐标 如果坐标为为其它类型,如int 只需将unsigned char改为int
#include
#include
#include
#include
#include
/***
*int printf(format, ...) - print formatted data
*
*Purpose:
* Prints formatted data on stdout using the format string to
* problems flushing the buffer, set the stream flag to error.
* Multi-thread version assumes stream lock is held by caller.
*
*Entry:
* FILE* stream - stream to flush
//函数__iob_func()又在是_file.c中实现的:
/*
* FILE descriptors; preset for stdin/out/err (note that the __tmpnum field * is not Nhomakorabea*

单片机中printf函数的运用

单片机中printf函数的运用

51中printf使用注意C51标准串口发送程序(已C8051F120为例,注意C8051F120特殊功能寄存器是分页的)/***********************************************************函数名称:send_char_com函数功能:向串口发送一字节字符入口参数:unsigned char sendByte 一个字节字符(8 bit)出口参数:无备注:***********************************************************/void send_char_com(unsigned char sendByte){char SFRPAGE_SA VE = SFRPAGE; //用到TI0(SCON0.1)SFR页:0SFRPAGE = UART0_PAGE;SBUF0=sendByte;while (TI0== 0); //等待发送完毕TI0= 0; //清发送中断标志TI0SFRPAGE = SFRPAGE_SA VE;}/***********************************************************函数名称:send_char_com函数功能:向串口发送一个字符串入口参数:unsigned char *str 字符串数组首地址unsigned int strlen 该字符串长度出口参数:无备注:***********************************************************/void send_string_com( unsigned char *str, unsigned int strlen){unsigned int k= 0 ;do {send_char_com(*(str + k));k++;}while (k < strlen);}在C51中直接使用printf比自己编个串口发送字符串的函数方便,但有几个问题要注意的。

单片机中printf函数的重映射

单片机中printf函数的重映射

单片机中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)。

c51 printf使用方法

c51 printf使用方法

c51 printf使用方法
C51是一种被广泛使用的单片机芯片,printf是一种常用的输出函数。

在C51中,使用printf函数可以简便地输出结果。

使用方法如下:
1. 在程序开头添加头文件 #include <stdio.h>。

2. 使用printf函数输出结果。

例如,printf('Hello World!'); 将会输出字符串Hello World!。

3. 可以使用格式化字符串输出变量的值。

例如,printf('x = %d', x); 将会输出x的值,%d是占位符,表示输出整数。

4. 如果要输出多个变量,可以在格式化字符串中使用多个占位符。

例如,printf('x = %d, y = %f', x, y); 将会输出x和y的值,%d 表示整数,%f表示浮点数。

5. 如果要换行输出,可以在字符串中添加转义字符。

例如,printf('Hello
World!'); 将会输出两行,第一行是Hello,第二行是World!。

注意事项:
1. 在使用printf函数时,要确保所要输出的变量类型与格式化字符串中所指定的类型一致,否则会输出错误的结果。

2. 在使用printf函数时,要注意输出缓冲区的大小,以防止缓冲区溢出。

3. 在使用printf函数时,要注意输出的内容是否会影响程序的运行,以防止出现意外的错误。

51单片机之printf

51单片机之printf

51单片机之printftypedef char *va_list;我先在知道想要在51单片机使用printf有两种办法,一种是用库自己的printf,一种是写自己的printf,不过都很简单,我先介绍一下库的printf吧。

1、首先添加头文件#include2、配置一下串口,但是在串口初始化的时候TI必须为1,否则无法发送。

3、也可以使用中断接收,但是不要再中断里有TI=0;这条语句,否则也发送不成功。

就这么简单,你就可以使用printf(&ldquo;&rdquo;,x,x,x)了,嘎嘎!#include#include#define FOSC 11059200L//系统时钟频率#define BAUD 9600 //串口波特率void USART_Init();void Delay100us() //@11.0592MHz{unsigned char i, j;i = 2;j = 15;do{while (--j);} while (--i);}void main(){unsigned int a=99;//定义的数不能是char 或者unsigned charchar table[]=&quot;abc&quot;;char *abc=table;USART_Init();Delay100us();while(1){printf(&quot;%d %c %x %s&quot;,a,(char)a,a,table) ;//必须(char)a强制转换一下Delay100us();Delay100us();Delay100us();Delay100us ();Delay100us();Delay100us();Delay100us();Delay100us();}}void USART_Init(void){AUXR=0x40;//定时器1的速度是传统的8051的12倍不分频不可以位寻址TMOD=0x00;//设置定时器1为16位自动重装寄存器不可以位寻址SCON=0x50;//设置为8位波特率可变并允许串口接收使能PCON=0x00;//用定时器1模式0时于PCON无关了TL1=(65536-(FOSC/4/BAUD));TH1=(65536-(FOSC/4/BAUD))>;>;8;TI=1;//用系统自带的printf函数,TI必须等于1,否则无法发送,不能TR1=1;//使能定时器1ES=1; //串口中断使能EA=1; //全局中断使能}void Uart() interrupt 4 using 1{static unsigned char RI_date=0;if(RI)//接收成功RI置位{RI_date=SBUF;RI=0;}if(TI)//发送成功TI置位{//TI=0;//用系统的printf的时候,如果又用到中断的话,那么这句话就得屏蔽,否则无法发送}}还有一种就是自己写printf。

printf在单片机c语言中作用

printf在单片机c语言中作用

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!"。

c51 printf使用方法

c51 printf使用方法

c51 printf使用方法C51是一款高性能的单片机,它具有强大的功能和广泛的应用场景。

在C51编程过程中,printf是一种非常常用的调试方式,可以使程序输出信息在串口终端中显示出来。

但是,printf的使用方法并不是那么显而易见,需要一些技巧和方法才能正确使用。

本文将从步骤上详细介绍C51中的printf使用方法。

1、先定义一个串口进行初始化,因为printf要通过串口发送数据给上位机,先要定义一个串口进行初始化。

UART是一种常见的串口通信方式,在C51的编程中也是最常用的一种。

在初始化串口的时候需要设置一些参数,如波特率、校验位等等,这些参数需要根据实际情况来选择。

2、定义一个函数,这个函数将主要用来将数据发送给串口,因为printf函数需要调用这个函数来发送数据。

这个函数的实现主要包括将要发送的数据保存到缓冲区,然后把缓冲区的数据通过串口发送出去。

需要注意的是,这个函数的设计要尽量简单,不要过于复杂,否则会影响程序的运行效率。

3、定义一个宏,这个宏将起到重要的作用,它将使printf函数输出的信息在屏幕上显示。

这个宏将用来格式化传入的各种参数,在消息传输时起到很大的作用。

宏定义时需要指定一些参数,这些参数需要根据具体的需求来确定。

4、使用printf函数,最后一步是使用printf函数将消息输出到屏幕上。

在使用printf函数时,需要注意传入的参数要根据之前定义的宏来格式化。

如果传入的参数没有被正确格式化,将无法正确地在屏幕上显示。

总之,printf是C51中非常重要的调试方式,它可以帮助程序员查看程序运行状态,了解程序执行情况。

但是,printf的使用方法需要一些技巧和方法才能正确使用。

只有掌握了这些方法,才能在C51编程中更加轻松地使用printf函数。

如何在单片机上使用printf函数

如何在单片机上使用printf函数

如何在单片机上使用printf函数当我们在调试代码时,通常需要将程序中的某个变量打印至PC 机上,来判断我们的程序是否按预期的运行,printf 函数很好的做到了这一点,它能直接以字符的方式输出变量名和变量的值,这样使输出的信息很直观;但printf函数在使用时,不仅仅要初始化串口,还需要其它的一些设置或者要调用其它的一些函数,否则printf 函数将不能按我们想要的方式执行。

由于不同的编译器studio 函数不一样,所以使用的方法也不一样,这需要大家去看编译器的help,这里我以STM32、LPC24 和AVR 整理了几个串口打印程序,供需要的朋友参考。

简介:1、在KEIL 下使用printf 函数,以STM32 为例在uart.c 中添加如下代码View Codeint fputc(int ch, FILE *f){ USART_SendData(USART1, (uint8_t) ch); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} return ch;}int fgetc(FILE *f){ while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET) {} return (int)USART_ReceiveData(USART1);} 这样,只要在需要用printf 的文件里#include 就可以了,printf 会自已的调用fputc 函数来实现串口数据的输出。

2、添加Retarget.c,实现在KEIL 下使用printf 函数,以LPC2478 为例首先在Keil 安装目录下面ARM/Startup/Retarget.c 找到Retarget.c 文件将其复制到你的工程文件夹下面;并将其加入到工程中在uart.c 中添加如下代码。

stm32 printf 用法

stm32 printf 用法

stm32 printf 用法题目:stm32 printf 用法详解:从基础用法到高级应用的一步一步回答导语:在嵌入式系统开发中,对于调试和输出信息的需求是不可或缺的。

printf 函数作为一个强大的输出函数,在stm32开发中也有着广泛的应用。

本文将从基础的printf用法开始,逐步深入,介绍stm32 printf的用法和高级应用,助您更好地掌握和运用这一重要工具。

第一步:了解printf函数printf函数是C语言标准库中的一个输出函数,其原型如下:cint printf(const char *format, ...);printf函数的参数是一个格式化字符串(format)和可选的其他参数,用于指定输出格式和内容。

它以变长参数的方式,根据格式化字符串中的占位符,将对应的参数格式化并输出到标准输出。

第二步:配置串口进行printf输出在stm32开发中,一般会使用串口作为printf的输出接口。

首先,我们需要配置相应的串口,设置波特率、数据位、奇偶校验位等参数。

具体配置方法可参考stm32芯片的参考手册和相关资料。

第三步:重定向printf输出为了让printf函数的输出不再通过标准输出进行显示,而是通过串口输出,我们需要进行输出重定向。

在C语言中,可以通过重定义标准输出流(stdout)的方式实现。

下面是一个示例代码:c#include <stdio.h>#include <sys/stat.h>int _write(int file, char *ptr, int len){HAL_UART_Transmit(&huart1, (uint8_t *)ptr, len, 1000); 将输出通过串口发送出去return len;}int main(){printf("Hello, world!\n"); 通过串口输出"Hello, world!"return 0;}在上述代码中,通过实现_write函数,将printf函数的输出通过HAL_UART_Transmit函数发送到串口进行输出。

51单片机实现scanf和printf函数

51单片机实现scanf和printf函数

51 单片机实现scanf 和printf 函数
最开始学习C 语言时,使用printf 和scanf 进行格式化输入输出十分方便。

学习单片机有很长时间了,之前要再屏幕上显示一个变量或者通过串口传
出一些变量值观测的话,需要进行一系列的取余取整运算,很是麻烦。

最近又研究了一下keil 中针对printf 和scanf 的实现机理,做了一些改动,实现了标准格式化输入输出,共大家参考。

1.printf 函数在格式化输出时,向下调用了char putchar(char c);这个函数,在stdio.h 里可以发现有这个函数,所以我们需要自己构造一个这样的函数,
即通过串口putchar(),代码如下:
[cpp] view plain copychar putchar(char c)
{
hal_uart_putchar(c);
return c;
}。

printf在单片机中的用法

printf在单片机中的用法
ES0=1;
pchar++;
}
while(TI0==0){};
TI0=0;
sprintf(PrintChar,"Test complete.\n");
send_string_com(PrintChar,15);
正确的输出如下:
正确的代码如下:
pchar = XRAM_START;
TI0=1;
for (i = 0; i < RAM_SIZE; i++)
{
*pchar= 0;
ES0=0;
printf("writing 0x%04x:%u\n",(unsigned)pchar,(unsigned) *pchar);
SFRPAGE_SAVE = SFRPAGE; //c8051f120特殊功能寄存器分页
SFRPAGE = UART0_PAGE;
TI0=1;
printf ("\n\nTest complete.");
TI0=0; //可以省略
WinAVR库中的printf()是可以直接传输数据到串口上的,但之前需要初始化很多东西。下面是avr-lib中的一个例子:
#include <stdio.h> static int uart_putchar(char c, FILE *stream); static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); static int uart_putchar(char c, FILE *stream) { if (c == ''\n'') uart_putchar(''\r'', stream); loop_until_bit_is_set(UCSRA, UDRE); UDR = c; return 0; } int main(void) { init_uart(); stdout = &mystdout; printf("Hello, world!\n"); return 0; }

stc printf 的用法

stc printf 的用法

stc printf 的用法printf是C语言中的一个重要函数,用于格式化输出数据。

在STC系列单片机中,也提供了类似的printf函数,用于在单片机上输出各种类型的数据。

本篇文章将介绍STCprintf的用法,包括函数原型、格式化字符串、输出数据类型等。

一、函数原型```cvoidprintf(constchar*format,...);```该函数接受一个格式化字符串和可变数量的参数,按照格式化字符串中的格式要求,将参数按照指定的格式输出到标准输出流(通常是终端或控制台)。

二、格式化字符串格式化字符串是由格式说明符和对应的参数组成。

在STCprintf 中,常用的格式说明符有:1.%d:输出十进制整数;2.%u:输出无符号十进制整数;3.%f:输出浮点数;4.%s:输出字符串;5.%%:表示占位符。

例如,以下格式化字符串分别表示输出一个整数、一个浮点数和一个字符串:```cintnum=123;floatf=3.14;charstr[]="Hello,world!";printf("整数:%d\n",num);//输出:整数:123printf("浮点数:%f\n",f);//输出:浮点数:3.140000printf("字符串:%s\n",str);//输出:字符串:Hello,world!```除了上述格式说明符外,还可以使用占位符和格式说明符组合的方式输出不同类型的数据。

例如,以下格式化字符串可以输出一个整数和一个浮点数,并按照小数点后两位的精度输出:```cprintf("小数:%.2f\n",f);//输出:小数:3.14```三、输出数据类型STCprintf可以输出各种类型的数据,包括整型、浮点型、字符型、枚举型等。

在实际应用中,需要根据具体的数据类型选择对应的格式说明符。

此外,还可以通过传递多个参数来同时输出多个数据。

printf在单片机c语言中作用

printf在单片机c语言中作用

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函数。

单片机使用printf函数进行串口打印输出

单片机使用printf函数进行串口打印输出

单片机使用printf函数进行串口打印输出
以前在使用keil 编写51 单片机程序的时候,经常使用printf 函数打印输出一些关键的过程数据到电脑,方便监控程序的运行状况。

最近使用IAR for MSP430 调试MSP430G2553 程序的时候,发现了一些小问题,MSP430G2553 单片机并没有按照我的预期输出数据到电脑。

带着疑惑我查看
了keil 的帮助文件里面的printf 函数说明,原来printf 函数最终是调用putchar 函数来实现打印输出字符的。

putchar,该函数将制定的表达式的值所对应的字符输出到标准输出终端上。

表达式可以是字符型或整型,它每次只能输出一个字符。

我们来看keil 标准函
数库里的putchar 函数的函数体。

根据说明提示,我在D:KeilC51LIB 文件夹里面找到了putchar.c 文件
#include
#define XON 0x11
#define XOFF 0x13
char putchar (char c) {
if (c == ) {
if (RI) {
if (SBUF == XOFF) {
do {
RI = 0;
while (!RI);
}
while (SBUF != XON);。

关于printf在单片机中支持字符汉字混合显示

关于printf在单片机中支持字符汉字混合显示
unsigned char char_sequence_number; //字符序号
if(c>=0x80)
{
one_hz[hzbz]=c;
hzbz=~hzbz;
if(!hzbz) //收到一个汉字
{
//发送汉字
for (char_sequence_number=0;HZ_LIB_INDEX[char_sequence_number]!='\0';char_sequence_number+=2) //如果没有查到就pass
// 系(0) 统(1) 检(2) 测(3) 中(4)
0x00,0x00,0x00,0x04,0xB4,0x94,0x6C,0x24,0xA6,0xA2,0x92,0xCA,0x82,0x82,0x00,0x00,
0x00,0x10,0x08,0x08,0x04,0x02,0x13,0x11,0x1F,0x00,0x02,0x04,0x04,0x0D,0x08,0x00,/*"系",0*/
0x00,0x00,0x90,0xFE,0x50,0xD0,0x30,0x50,0x48,0x46,0x44,0x28,0xD0,0xB0,0x00,0x00,
0x00,0x01,0x00,0x1F,0x00,0x00,0x10,0x16,0x10,0x13,0x14,0x1C,0x13,0x10,0x10,0x00,/*"检",2*/
{
disp(x,y,16,16,HZ_LIB_DOT+char_sequence_number*16); //显示一个汉字
x+=16;
break; //结束for

如何使用STM32单片机实现printf打印调试信息

如何使用STM32单片机实现printf打印调试信息

如何使用STM32单片机实现printf打印调试信息如何使用STM32单片机实现printf打印调试信息在写单片机程序时我们一般喜欢使用printf来通过串口打印调试信息,但这个函数是不可以直接使用的,必须做点对库函数的改动。

STM32M CUBE是ST官方提供的库以及初始化工具,很好很强大,但是在UART方面值提供了如下函数:HAL_StatusTypeDefHAL_UART_Transmit(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize,uint32_tTimeout);HAL_StatusTypeDefHAL_UART_Receive(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize,uint32_tTImeout);HAL_StatusTypeDefHAL_UART_Transmit_IT(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize);HAL_StatusTypeDefHAL_UART_Receive_IT(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize);HAL_StatusTypeDefHAL_UART_Transmit_DMA(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize);HAL_StatusTypeDefHAL_UART_Receive_DMA(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize);分别实现普通收发,中断收发,DMA收发,问题是所有函数要求发送和接收的buf必须要事先知道长度,也没有提供对单字节的收发,无法直接实现printf以及单字节接收。

avr单片机串口实现printf(使用变参函数)

avr单片机串口实现printf(使用变参函数)

avr单片机串口实现printf(使用变参函数)1./*2.* AVR串口实现printf函数3.编译器 avrstudio,avr-gcc4.使用硬件:avrmega16单片机5.*/6.#include <stdarg.h>7.#include <stdlib.h>8.#include <avr/io.h>9.10.typedef unsigned char uint8;11.static void usart_init(void)12.{13.UCSRA = 0x02; /*倍速*/14.UCSRB = 0x18; /*允许接收和发送*/15.UCSRC = 0x06; /*8位数据*/16.UBRRH = 0x00;17.UBRRL = 103;18.}19.static void put_char(uint8 data)20.{21.if (data == '/r')22.put_char(0x09);23.while ( !(UCSRA & (1<<UDRE)) ) // 不为空,等之24.;25.UDR = data;26.}27./*28.*/29.static void myprintf(const char* fmt,...)30.{31.const char* s;32.int d;33.char buf[16];34.va_list ap;35.va_start(ap,fmt); // 将ap指向fmt(即可变参数的第一个?下一个?)36.while (*fmt)37.{38.if (*fmt != '%')39.{40.put_char(*fmt++); // 正常发送41.continue;42.}43.switch (*++fmt) // next %44.{45.case 's':46.s = va_arg(ap,const char*); // 将ap指向者转成char*型,并返回之47.for (; *s; s++)48.put_char(*s);49.break;50.case 'x':51. d = va_arg(ap,int); // 将ap指向者转成int型,并返回之52.itoa(d,buf,16); // 将整型d以16进制转到buf中53.for (s = buf; *s; s++)54.put_char(*s);55.break;56.case 'd':57. d = va_arg(ap,int);58.itoa(d,buf,10); // 将整型d以10进制转到buf中59.for (s = buf; *s; s++)60.put_char(*s);61.break;62.default:63.put_char(*fmt);64.break;65.}66.fmt++;67.}68.va_end(ap);69.}70.int main(void)71.{art_init(); // 初始化串口73.uint8 i = 100;74.uint8* s = "Word!";75.while(1)76.{77.myprintf("/n/rHello %s/n/r0x%x = %d/n",s,i,i);78.}79.return 0;80.}上面这段代码是在网上的一个代码的修改,修改后直接适用于avr16单片机,编译环境是 avrstudio中的avr-gcc。

stm32中printf函数的用法和配置

stm32中printf函数的用法和配置

stm32中printf函数的用法和配置在STM32中使用printf函数来进行串口打印输出是一种常见的调试手段。

printf函数是C语言标准库中的一个函数,用于格式化输出字符串。

要在STM32中使用printf函数,需要完成以下几个步骤:1.配置串口:首先,需要在STM32的引脚配置中设置相应的引脚为串口模式,并且初始化串口对应的寄存器。

2. 配置printf函数:接下来,需要在代码中重新定义printf函数,使其能够与串口进行通信。

这可以通过重写标准库中的retarget.c文件完成。

3.初始化串口:在主函数中,需要进行串口的初始化,包括波特率、数据位、停止位等参数的配置。

4. 使用printf函数:配置完成后,可以直接在代码中使用printf函数来进行串口打印输出。

具体的配置和用法如下所示:1.配置串口:首先,在STM32的引脚配置中,将相应的引脚设置为串口功能,并初始化串口寄存器。

2. 配置printf函数:需要重新定义printf函数,将输出的数据通过串口发送出去。

可以在标准库的retarget.c文件中,重写以下函数:- int _write(int fd, char 某ptr, int len): 重写该函数,将ptr参数中的数据通过串口发送出去。

- int _read(int fd, char 某ptr, int len): 重写该函数,将串口接收到的数据存储到ptr参数中。

在以上两个函数中,可以使用串口的发送和接收函数来完成相应的操作。

3.初始化串口:在主函数中,需要进行串口的初始化,包括波特率、数据位、停止位等参数的配置。

可以使用CubeMX等工具来配置串口参数,并生成相应的初始化代码。

4. 使用printf函数:配置完成后,可以在代码中使用printf函数来进行串口打印输出。

例如:```cprintf("Hello, World!\n");```在串口接收到数据后,会自动将其发送到电脑终端,用于调试和输出信息。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

51中printf使用注意
C51标准串口发送程序(已C8051F120为例,注意C8051F120特殊功能寄存器是分页的)
/***********************************************************
函数名称:send_char_com
函数功能:向串口发送一字节字符
入口参数:unsigned char sendByte 一个字节字符(8 bit)
出口参数:无
备注:
***********************************************************/
void send_char_com(unsigned char sendByte)
{
char SFRPAGE_SA VE = SFRPAGE; //用到TI0(SCON0.1)SFR页:0
SFRPAGE = UART0_PAGE;
SBUF0=sendByte;
while (TI0== 0); //等待发送完毕
TI0= 0; //清发送中断标志TI0
SFRPAGE = SFRPAGE_SA VE;
}
/***********************************************************
函数名称:send_char_com
函数功能:向串口发送一个字符串
入口参数:unsigned char *str 字符串数组首地址
unsigned int strlen 该字符串长度
出口参数:无
备注:
***********************************************************/
void send_string_com( unsigned char *str, unsigned int strlen)
{
unsigned int k= 0 ;
do {
send_char_com(*(str + k));
k++;
}
while (k < strlen);
}
在C51中直接使用printf比自己编个串口发送字符串的函数方便,但有几个问题要注意的。

1. 使用printf之前要先包含stdio.h这个头文件
#include <stdio.h>
具体stdio.h包含的函数见下面网址
/support/man/docs/c51/c51_stdio_h.htm
2.
ES0=0; //禁止串口中断
SFRPAGE_SA VE = SFRPAGE; //c8051f120特殊功能寄存器分页
SFRPAGE = UART0_PAGE;
TI0=1;
printf ("\n\nTest complete.");
TI0=0; //可以省略
SFRPAGE = SFRPAGE_SA VE;
ES0=1; //打开串口中断
printf函数是调用putchar函数,从串口发送字符串的,可以从keil反汇编看出这一点。

在C51程序中printf的位置设一个断点,运行到断点处后,再一步步执行程序,可以看出,跳转到PRINTF执行。

PRINTF有很长一大段汇编,一步步执行。

运行到PUTCHAR处,这个就是串口发送字符串的函数。

可以看到有这么一句“C:0521 JNB TI0,C:0521”
第一次运行到这的时候,如果前面没有TI0=1,那么程序指针PC就一直在这条语句上判断,也就死在这里等待。

所以要使用printf,开头必须要先置TI0(传统51为TI)为1。

那么发送了第一个字节后,发送中断标志位TI0自动置1,再回到“C:0521 JNB TI0,C:0521”,接着发送第二个字节。

因为TI0为中断标志位,但如果程序使用了UAR0中断,那么在printf函数执行过程中就会不断调用中断函数(UART0_Interrupt),所以每次使用printf之前要先禁止串口中断(ES0=0)。

3. 由上面可以看到使用printf非常麻烦,其实可以用sprintf代替printf,只要在前面先定义一个存放字符串的数组。

……
unsigned char PrintChar[15]
……
SFRPAGE_SA VE = SFRPAGE; //C8051F120特殊功能寄存器分页
SFRPAGE = UART0_PAGE; //传统51单片机没有SFR分页
sprintf (PrintChar,"\nTest complete.");
send_string_com(s, 15);
SFRPAGE = SFRPAGE_SA VE;
上面总结得都是经验教训啊,在这个小小的bug上浪费了几天,记录下来,希望对大家有点帮助。

4. 当使用printf循环打印时要注意,下面程序是有问题的
pchar = XRAM_START;
for (i = 0; i < RAM_SIZE; i++)
{
*pchar= 0;
ES0=0;
TI0=1;
printf("writing 0x%04x:%u\n",(unsigned)pchar,(unsigned) *pchar);
ES0=1;
pchar++;
}
sprintf(PrintChar,"Test complete.\n");
send_string_com(PrintChar,15);
串口调试助手接收如下,可以看到第二次打印“write”时少了“w”。

用sprintf打印“Test”少了“T”。

可以重新看一下PUTCHAR处。

第一次发送字符的时候,由于TI0=1,所以在C:0x05B6的位置不会死等,执行C:0x05B9的时候TI0=0,接着A寄存器的值通过SBUF0发送。

由于串口发送的速率是很慢的(波特率才19200kBPS),所以,等在执行一遍上面的代码,回到C:0x05B6的时候,TI0还是为0,在C:0x05B6处等TI0变为1。

当串口发送完了之后,发送中断标志位TI0才被硬件置1。

此时PC机上的串口调试助手才显示刚发送的字符。

当发送最后一个字符时,C:0x05BB,把寄存在A的最后字符的ASCII代码复制给SUBF0后,并没有等待TI0变为1的指令,而是占用了下次for循环发送首字母的C:0x05B6,导致下次for循环首字母没有发送出去。

正确的办法是把TI0=1挪到for循环之后。

“Test”中的“T”没接收到也是同样的问题,最后一次发送的字符,没有等待TI0硬件置位的过程,造成发送的字符丢失。

正确的代码如下:
pchar = XRAM_START;
TI0=1;
for (i = 0; i < RAM_SIZE; i++)
{
*pchar= 0;
ES0=0;
printf("writing 0x%04x:%u\n",(unsigned)pchar,(unsigned) *pchar);
ES0=1;
pchar++;
}
while(TI0==0){};
TI0=0;
sprintf(PrintChar,"Test complete.\n");
send_string_com(PrintChar,15);。

相关文档
最新文档