单片机中printf函数的运用
- 格式:doc
- 大小:20.00 KB
- 文档页数:4
单片机串口实现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,作用完全差不多,只需要稍加修改即可,不多介绍)。
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函数的重映射
一、源自于:大侠有话说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函数可以简便地输出结果。
使用方法如下:
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单片机之printftypedef char *va_list;我先在知道想要在51单片机使用printf有两种办法,一种是用库自己的printf,一种是写自己的printf,不过都很简单,我先介绍一下库的printf吧。
1、首先添加头文件#include2、配置一下串口,但是在串口初始化的时候TI必须为1,否则无法发送。
3、也可以使用中断接收,但是不要再中断里有TI=0;这条语句,否则也发送不成功。
就这么简单,你就可以使用printf(“”,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[]="abc";char *abc=table;USART_Init();Delay100us();while(1){printf("%d %c %x %s",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语言的基本概念。
单片机是一种集成了微处理器、存储器和各种外设接口的微型计算机系统。
它通常用于控制和管理各种电子设备。
而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是一款高性能的单片机,它具有强大的功能和广泛的应用场景。
在C51编程过程中,printf是一种非常常用的调试方式,可以使程序输出信息在串口终端中显示出来。
但是,printf的使用方法并不是那么显而易见,需要一些技巧和方法才能正确使用。
本文将从步骤上详细介绍C51中的printf使用方法。
1、先定义一个串口进行初始化,因为printf要通过串口发送数据给上位机,先要定义一个串口进行初始化。
UART是一种常见的串口通信方式,在C51的编程中也是最常用的一种。
在初始化串口的时候需要设置一些参数,如波特率、校验位等等,这些参数需要根据实际情况来选择。
2、定义一个函数,这个函数将主要用来将数据发送给串口,因为printf函数需要调用这个函数来发送数据。
这个函数的实现主要包括将要发送的数据保存到缓冲区,然后把缓冲区的数据通过串口发送出去。
需要注意的是,这个函数的设计要尽量简单,不要过于复杂,否则会影响程序的运行效率。
3、定义一个宏,这个宏将起到重要的作用,它将使printf函数输出的信息在屏幕上显示。
这个宏将用来格式化传入的各种参数,在消息传输时起到很大的作用。
宏定义时需要指定一些参数,这些参数需要根据具体的需求来确定。
4、使用printf函数,最后一步是使用printf函数将消息输出到屏幕上。
在使用printf函数时,需要注意传入的参数要根据之前定义的宏来格式化。
如果传入的参数没有被正确格式化,将无法正确地在屏幕上显示。
总之,printf是C51中非常重要的调试方式,它可以帮助程序员查看程序运行状态,了解程序执行情况。
但是,printf的使用方法需要一些技巧和方法才能正确使用。
只有掌握了这些方法,才能在C51编程中更加轻松地使用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 用法详解:从基础用法到高级应用的一步一步回答导语:在嵌入式系统开发中,对于调试和输出信息的需求是不可或缺的。
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中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);。