码迷,mamicode.com
首页 > 其他好文 > 详细

单片机工程加入printf函数

时间:2015-07-29 17:08:47      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:

之前学习用的是Alientek MiniSTM32开发板,使用的开发环境可以通过特殊的配置集成printf函数,调试程序的时候不大喜欢用仿真器,最近项目开始使用单片机,只能够用UART1_Send(uint8_t * const tx_buf,uint16_t tx_num),真心有点不习惯没有printf函数的日子,程序调试的话最方便莫过于printf函数,于是开始研究如何在单片机中加入printf函数。

跟串口驱动相关的函数put_char(uint8_t data),需要根据不同的嵌入式平台做出相应的变动,因为put_char()函数只是发送一个字节的串口操作函数,所以基本原则是发送新的data字节A1之前需要检查该串口前一个发送字节A0是否已经发送完毕,只有A0已经发送完毕,才能够将新的字节数据A1写入串口发送寄存器中,同样A2的发送也需要等待A1发送完毕。

va_start()等定义在头文件stdarg.h、stdio.h、stdlib.h中,所以需要添加这些头文件,这些头文件均是编译器include路径下的,我这里使用的是IAR开发环境,一般情况下使用<>包含头文件,编译器时软件会自动在其安装目录下去搜索这些头文件,如果使用"x.h"则是在工程路径下去查找x.h文件
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <stdarg.h>
 4 
 5 static void put_char(uint8_t data)  
 6 {  
 7     if (data == /r)  
 8         put_char(0x09);  
 9     while ( !(UCSRA & (1<<UDRE)) )    // 不为空,等之  
10         ;  
11     UDR = data; //将数据传给串口发送寄存器    
12 }  
13   
14 void my_printf(const char* fmt,...)  
15 {  
16     const char* s;  
17     int d;  
18     char buf[16];  
19     va_list ap;  
20     va_start(ap,fmt);   // 将ap指向fmt(即可变参数的第一个?下一个?)  
21     while (*fmt)  
22     {  
23         if (*fmt != %)  
24         {  
25             put_char(*fmt++);   // 正常发送  
26             continue;     
27         }  
28         switch (*++fmt) // next %  
29         {  
30         case s:  
31             s = va_arg(ap,const char*); // 将ap指向者转成char*型,并返回之  
32             for (; *s; s++)  
33                 put_char(*s);  
34             break;  
35         case x:  
36             d = va_arg(ap,int);     // 将ap指向者转成int型,并返回之  
37             itoa(d,buf,16);         // 将整型d以16进制转到buf中  
38             for (s = buf; *s; s++)  
39                 put_char(*s);  
40             break;  
41         case d:  
42             d = va_arg(ap,int);  
43             itoa(d,buf,10);         // 将整型d以10进制转到buf中  
44             for (s = buf; *s; s++)  
45                 put_char(*s);  
46             break;  
47         default:  
48             put_char(*fmt);  
49             break;  
50         }  
51         fmt++;  
52     }  
53     va_end(ap);  
54 }  

 

部分开发环境可能没有itoa()函数,这里从阿莫论坛找到了itoa()函数的原型,如果编译器提示找不到itoa函数,可以将下面的代码拷贝到上述printf函数所在的文件当中,该函数经测试可用。

 1 char *itoa(int num,char *str,int radix) 
 2 {     
 3     /* 索引表*/
 4     char index[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
 5     unsigned unum; /* 中间变量 */
 6     int i=0,j,k;     /* 确定unum的值 */ 
 7     if(radix==10&&num<0) /* 十进制负数 */
 8     {     
 9         unum=(unsigned)-num;
10         str[i++]=-;     
11     }
12      else 
13         unum=(unsigned)num; /* 其他情况 */    /* 逆序 */
14     do{         
15             str[i++]=index[unum%(unsigned)radix]; 
16             unum/=radix;     
17         }while(unum);
18      str[i]=\0;     /* 转换 */
19     if(str[0]==-) 
20         k=1; /* 十进制负数 */ 
21     else 
22         k=0;
23     char temp; 
24     for(j=k;j<=(i-1)/2;j++)
25      {         
26         temp=str[j]; 
27         str[j] = str[i-1+k-j]; 
28         str[i-1+k-j] = temp;     
29     } 
30     return str; 
31 }            

 

最后就可以在主函数中,加入代码进行测试

uint8_t buffer[]="hello world";

uint8_t x=0x64;

my_printf("test %s,%d,0x%x\r\n",buffer,x,x);

最终输出结果是

test hello world,100,0x64

单片机工程加入printf函数

标签:

原文地址:http://www.cnblogs.com/codecamel/p/4686437.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!