第二个vsnprintf函数()里面的函数为什么要加\n”否则不对

c语言printf函数的使用详解
字体:[ ] 类型:转载 时间:
本篇文章是对c语言中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在内存单元中(以补码形式存放)为(1111)2,转换为八进制数为(。③x格式:以无符号十六进制形式输出整数。对长整型可以用"%lx"格式输出。同样也可以指定字段宽度用"%mx"格式输出。④u格式:以无符号十进制形式输出整数。对长整型可以用"%lu"格式输出。同样也可以指定字段宽度用“%mu”格式输出。⑤c格式:输出一个字符。⑥s格式:用来输出一个串。有几中用法%s:例如:printf("%s", "CHINA")输出"CHINA"字符串(不包括双引号)。%ms:输出的字符串占m列,如字符串本身长度大于m,则突破获m的限制,将字符串全部输出。若串长小于m,则左补空格。%-ms:如果串长小于m,则在m列范围内,字符串向左靠,右补空格。%m.ns:输出占m列,但只取字符串中左端n个字符。这n个字符输出在m列的右侧,左补空格。%-m.ns:其中m、n含义同上,n个字符输出在m列范围的左侧,右补空格。如果n&m,则自动取n值,即保证n个字符正常输出。⑦f格式:用来输出实数(包括单、双精度),以小数形式输出。有以下几种用法:%f:不指定宽度,整数部分全部输出并输出6位小数。%m.nf:输出共占m列,其中有n位小数,如数值宽度小于m左端补空格。 %-m.nf:输出共占n列,其中有n位小数,如数值宽度小于m右端补空格。⑧e格式:以指数形式输出实数。可用以下形式:%e:数字部分(又称尾数)输出6位小数,指数部分占5位或4位。%m.ne和%-m.ne:m、n和”-”字符含义与前相同。此处n指数据的数字部分的小数位数,m表示整个输出数据所占的宽度。⑨g格式:自动选f格式或e格式中较短的一种输出,且不输出无意义的零。
---------------------------------------关于printf函数的进一步说明:如果想输出字符"%",则应该在“格式控制”字符串中用连续两个%表示,如:printf("%f%%", 1.0/3);输出0.333333%。
---------------------------------------对于单精度数,使用%f格式符输出时,仅前7位是有效数字,小数6位.对于双精度数,使用%lf格式符输出时,前16位是有效数字,小数6位.
######################################拾遗########################################由高手指点对于m.n的格式还可以用如下方法表示(例)char ch[20];printf("%*.*s\n",m,n,ch);前边的*定义的是总的宽度,后边的定义的是输出的个数。分别对应外面的参数m和n 。我想这种方法的好处是可以在语句之外对参数m和n赋值,从而控制输出格式。
%n 可以将所输出字符串的长度值赋绐一个变量, 见下例:
printf("hello world%n", &slen);
执行后变量被赋值为11。
又查了一下, 看到一篇文章(查看)说这种格式输出已经确认为一个安全隐患,并且已禁用。再搜搜果然这种用法都被用来搞什么溢出、漏洞之类的,随便找了一个:格式化字符串攻击笔记。
------------------------------------------
%p格式用来以十六进制整数形式输出内存地址 代码如下:#include &stdio.h&extern int etext, edata,
int main(void){&& printf("etext: \t%p\n", &etext);&& printf("edata: \t%p\n", &edata);&& printf("end: \t%p\n", &end);
&& return(0);}在链接过程中,链接器ld和ld86会使用变量记录下执行程序中每个段的逻辑地址。因此在程序中可以通过访问这几个外部变量来获得程序中段的位置。链接器预定义的外部变量通常至少有etext、_etext、edata、_edata、end和_end。
变量名_etext和etext的地址是程序正文段结束后的第1个地址;_edata和edata的地址是初始化数据区后面的第1个地址;_end和 end的地址是未初始化数据区(bss)后的第1个地址位置。带下划线'_'前缀的名称等同于不带下划线的对应名称,它们之间的唯一区别在于ANSI、 POSIX等标准中没有定义符号etext、edata和end。
当程序刚开始执行时,其brk所指位置与_end处于相同位置。但是系统调用sys_brk()、内存分配函数malloc()以及标准输入/输出等 操作会改变这个位置。因此程序当前的brk位置需要使用sbrk()来取得。注意,这些变量名必须看作是地址。因此在访问它们时需要使用取地址前缀 '&',例如&end等。例如:
extern int _
(int *) et = &_     // 此时et含有正文段结束处后面的地址。
下面程序predef.c可用于显示出这几个变量的地址。可以看出带与不带下划线'_'符号的地址值是相同的。 代码如下:/*Print the symbols predefined by linker.*/extern int end, etext,extern int _etext, _edata, _int main(void){&& printf("&etext=%p, &edata=%p, &end=%p\n", &etext, &edata, &end);&& printf("&_etext=%p, &_edata=%p, &_end=%p\n", &_etext, &_edata, &_end);&& return 0;}在Linux 0.1X系统下运行该程序可以得到以下结果。请注意,这些地址都是程序地址空间中的逻辑地址,即从执行程序被加载到内存位置开始算起的地址。
[/usr/root]# gcc -o predef predef.c[/usr/root]# ./predef&etext=4000, &edata=44c0, &end=48d8&_etext=4000, &_edata=44c0, &_end=48d8[/usr/root]#
如果在现在的Linux系统(例如RedHat 9)中运行这个程序,就可得到以下结果。我们知道现在Linux系统中程序代码从其逻辑地址0x处开始存放,因此可知这个程序的代码段长度是0x41b字节。
[root@plinux]# ./predef&etext=0x804841b, &edata=0x80495a8, &end=0x80495ac&_etext=0x804841b, &_edata=0x80495a8, &_end=0x80495ac[root@plinux]#
Linux 0.1x内核在初始化块设备高速缓冲区时(fs/buffer.c),就使用了变量名_end来获取内核映像文件Image在内存中的末端后的位置,并从这个位置起开始设置高速缓冲区。
附:C51 printf函数The optional characters l or L may immediately precede the type character to respectively specify long types for d, i, u, o, x, and X. The optional characters b or B may immediately precede the type character to respectively specify char types for d, i, u, o, x, and X.printf("%bx",(char)i);
如果是 可以sprintf(buf,"%d",a),结果正确char a,就必须sprintf(buf,"bd",a)如果在浮点数中,则可以sprintf(buf,"%1.3f",a)printf("%02BX%02BX\n", adch, adcl)怎么解释呢?是应该是C51上的表达方式
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具C_primer_plus(第五版)课后编程练习答案(完整)_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
C_primer_plus(第五版)课后编程练习答案(完整)
上传于||暂无简介
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩192页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢ccs studio里面如何使用printf函数 - 其他MCU产品 - 微处理器 MCU - 德州仪器在线技术支持社区
ccs studio里面如何使用printf函数
发表于1年前
<input type="hidden" id="hGroupID" value="36"
我实时仿真msp430芯片,用库里面的printf函数输出,串口调试助手没有输出信息,请问该如何弄&/p>&div style=&clear:&>&/div>" />
ccs studio里面如何使用printf函数
此问题尚无答案
All Replies
我实时仿真msp430芯片,用库里面的printf函数输出,串口调试助手没有输出信息,请问该如何弄
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
状元15806分
printf 和scanf函数是C语言中最常用的输入出函数,从学习C语言开始,就开始使用这两个函数,然而当写用C语言写单片机程序时却不能使用这两个函数,总觉得单片机的C语言和一般的C语言差别很大,写起来不大方便;其实,单片机的C语言也是标准C语言上扩展或是改动的,都支持格式化输入输出函数(printf 和scanf);事实上,printf,scanf只负责格式化输入输出的字符,至于从哪儿输入,输出到哪儿,他们分别依靠getchar和putchar函数,只要实现单片机上的getchar函数和putchar函数,即可正常使用printf函数和scanf函数,这可以给我们单片机的信息交互带来很多方便。下面我们就来实现他们的移置。
好好学习,天天向上。
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
状元15806分
硬件介绍:
硬件部分只需字符型输入输出设备:scanf从输入字符型设备读取字符,printf输出到字符型输出设备。在这里,我选用的字符型输入设备是超级终端,通过串口与单片机连接,输入字符;输出设备是超级终端和12864的液晶。scanf从串口读入字符,printf输出字符到串口和液晶。
有关串口的预提信息参考:。
有关液晶的具体信息参考:。
scanf还可以从按键读取信息,可以参考移置方法自行移置。
程序实现:
单片机在调用printf时,printf是负责将数据解析成ASCII码流,通过调用putchar函数依次将字符发出。如果在putchar内编写从串口发送一字节数据,则printf的结果将从单片机串口发送出;如果putchar是向液晶写字符,让液晶显示一个字符,则printf的结果将显示在液晶上。本程序实现putchar同时向串口和液晶同时发送一个字符(液晶是显示一个字符)。
putchar函数如下:
int putchar(int ch)
putchar2Com(ch);
putchar2Lcd(ch);
return (ch);
程序先向串口发送一个字符,然后像向晶发送字符。
其中:putchar2Com,向串口发送一个字符,代码如下:
int putchar2Com(int ch)
if (ch == &#39;\n&#39;)
// &#39;\n&#39;(回车)扩展成 &#39;\n&#39;&#39;\r&#39; (回车+换行) {
UartWriteChar(&#39;\r&#39;) ;
//0x0d 换行 }
UartWriteChar(ch);
//从串口发出数据 return (ch);
代码仅仅调用向串口写字符的函数UartWriteChar(ch)(详见Uart.c,在&二&中有介绍),当要输出换行时,需先输出&\n&将光标移至本行首位置,还需要&\r&(换行)才能将光标置于下一行起始位置,即将&\n&扩展为&\r&,&\n&两个字节依次发出。
purchar2Lcd函数比较复杂,因为我所使用的12864液晶是中文字库的液晶,每行8个地址,可以显示8个中文字符或16个英文字符,而putchar只发出一个字节,需要判断每个地址的前半字还是后半字(因为每个字可以显示中文,如果中文的两个字节在相邻的两个地址上,将不会显示,或是显示乱码)。
int putchar2Lcd(int ch)
char addr,
if (ch == &#39;\n&#39;)
// &#39;\n&#39;(回车),换行 {
ChangeNextRow();
addr = LcdReadAddr();
if(ch & 0x80)
LcdWriteData(ch);
LcdWriteData(0x20);
//写入一个空字符,根据地址判断是否为前半字 if(addr == LcdReadAddr())
//前半字 从新写入ch字符 {
LcdWriteComm(addr);
LcdWriteData(ch);
LcdWriteComm(addr);
dat = LcdReadData();
if(dat & 0x80)
//前一个字符是英文字符 {
LcdWriteData(0x20);
LcdWriteData(ch);
if((addr != LcdReadAddr()) &&
//写入的是行最后位的后半字则换行 (addr==0x87 || addr==0x97 || addr==0x8F || addr==0x9F))
ChangeNextRow();
return (ch);
这个函数首先判断换行;然后处理其他一般字符,如果是英文字符,不用考虑前后半字,只需正常写入液晶即可;如果是中文字符,在判断是否是前半字,前半字则直接写入,后半字则判断之前写入的前半字是否是中文,是则直接写入,不是则把英文字符移入后半字,然后写入;最后判断是否到行尾,是则换行。
程序更新为:更新日期::51
目的是修复原来,行尾前半字为英文,再输入中文会显示乱码。
int putchar2Lcd(int ch)
char addr,
char changeRowFlag = 0;
if (ch == &#39;\n&#39;)
// &#39;\n&#39;(回车),换行 {
ChangeNextRow();
changeRowFlag = 1;
else if (ch == &#39;\b&#39;)
// &#39;\b&#39; (退格) {
BackSpace();
addr = LcdReadAddr();
if(ch & 0x80)
LcdWriteData(ch);
LcdWriteData(0x20);
//写入一个空字符,根据地址判断是否为前半字 if(addr == LcdReadAddr())
//前半字 从新写入ch字符 {
LcdWriteComm(addr);
LcdWriteData(ch);
LcdWriteComm(addr);
dat = LcdReadData();
if(dat & 0x80)
//前一个字符是英文字符 {
LcdWriteData(0x20);
if((addr != LcdReadAddr()) &&
//写入的是行最后位的后半字则换行 (addr==0x87 || addr==0x97 || addr==0x8F || addr==0x9F))
ChangeNextRow();
changeRowFlag = 1;
LcdWriteData(ch);
if((addr != LcdReadAddr()) &&
//写入的是行最后位的后半字则换行,且未换过行 (changeRowFlag == 0) &&
(addr==0x87 || addr==0x97 || addr==0x8F || addr==0x9F))
ChangeNextRow();
return (ch);
前后半字判断方法如下:读液晶地址,向液晶写入一个空格,再读地址,两地址相同则是前半字,不同则是后半字。读地址函数在Lcd12864.c中,新加入函数,代码如下:
char LcdReadAddr()
WaitForEnable();
DATA_DIR_IN;
ch = DATA_IN;
//读数据 CLR_EN;
DATA_DIR_OUT;
return (ch|0x80);
这个是读地址,ch|0x80是因为写入液晶地址首位应为1.。
液晶中新加入两个函数,一个是上边的读地址,另外一个是读数据;作用是读取液晶当前地址处的数据,从而判断之前半字是否是中文。代码如下:
char LcdReadData()
WaitForEnable();
DATA_DIR_IN;
ch = DATA_IN;
//读数据 CLR_EN;
DATA_DIR_OUT;
另外 putchar还调用了换行&&ChangeNextRow函数,完成液晶输出换至下一行。
代码如下:
void ChangeNextRow()
addr = LcdReadAddr();
//当前地址 if(addr &= 0x88)
LcdWriteComm(0x90);
else if(addr &= 0x90)
LcdWriteComm(0x98);
else if(addr &= 0x98)
LcdWriteComm(0x88);
AddNewline();
//添加行,同时向上滚动 LcdWriteComm(0x98);
读取当前地址,判断在哪一行,然后写入下一行首地址;如果是最后一行,则所有安徽那个向上移,写入最后一行首地址。
AddNewLine函数完成所有行向上滚动一行,然后地址定位至最后一行。
代码如下:
void AddNewline()
char str[17];
str[16] = 0;
//第二行 移至第一行 LcdWriteComm(0x90);
LcdReadData();
//空读取 for(int i = 0;i&16;i++)
str[i] = LcdReadData();
LcdWriteString(0x80,str);
//第三行 移至第二行 LcdWriteComm(0x88);
LcdReadData();
for(int i = 0;i&16;i++)
str[i] = LcdReadData();
LcdWriteString(0x90,str);
//第四行 移至第三行 LcdWriteComm(0x98);
LcdReadData();
for(int i = 0;i&16;i++)
str[i] = LcdReadData();
LcdWriteString(0x88,str);
//第四行 空白 LcdWriteString(0x98,& &);
//十六个空格 }
读出下一行数据,写入上一行,最后一行写入空格即可。
到此putchar函数全部完成,printf移植的程序部分完成,使用方法详见使用示例。
scanf和printf类似,其只负责格式化输入的字符,字符来源是从getchar函数获取;同样,在使用scanf函数之前,要针对字符输入源自行编写getchar函数
最简getchar:
int getchar()
return (putchar(UartReadChar()));
这是最简单的getchar函数,直接调用读取字符函数,输出并返回。
但是人的输入过程会偶尔犯错误的,为了支持退格键等,需要开辟一个缓存区。
详细代码如下:
#define LINE_LENGTH 80
//行缓冲区大小,决定每行最多输入的字符数 /*标准终端设备中,特殊ASCII码定义,请勿修改*/ #define InBACKSP 0x08
//ASCII &-- (退格键) #define InDELETE 0x7F
//ASCII &DEL& (DEL 键) #define InEOL &#39;\r&#39; //ASCII &CR& (回车键) #define InSKIP &#39;\3&#39; //ASCII control-C #define InEOF &#39;\x1A&#39; //ASCII control-Z #define OutDELETE &\x8 \x8& //VT100 backspace and clear #define OutSKIP &^C\n& //^C and new line #define OutEOF &^Z& //^Z and return EOF
int getchar()
static char inBuffer[LINE_LENGTH + 2];
//Where to put chars static char
//Pointer in buffer char c;
if(inBuffer[ptr])
//如果缓冲区有字符 return (inBuffer[ptr++]);
//则逐个返回字符 ptr = 0;
//直到发送完毕,缓冲区指针归零 while(1)
//缓冲区没有字符,则等待字符输入 {
c = UartReadChar();
//等待接收一个字符 if(c == InEOF && !ptr)
//==EOF== Ctrl+Z {
//只有在未入其他字符时才有效 printf(OutEOF);
//终端显示EOF符 return EOF;
//返回 EOF(-1) }
if(c==InDELETE || c==InBACKSP)
//==退格或删除键== {
//缓冲区有值 {
//从缓冲区移除一个字符 printf(OutDELETE);
//同时显示也删掉一个字符 }
else if(c == InSKIP)
//==取消键 Ctrl+C == {
printf(OutSKIP);
//终端显示跳至下一行 ptr = LINE_LENGTH + 1;
//==0 结束符== break;
else if(c == InEOL)
//== &#39;\r&#39; 回车== {
putchar(inBuffer[ptr++] = &#39;\n&#39;);//终端换行 inBuffer[ptr] = 0;
//末尾添加结束符(NULL) ptr = 0;
//指针清空 break;
else if(ptr & LINE_LENGTH)
//== 正常字符 == {
if(c &= &#39; &#39;)
//删除 0x20以下字符 {
//存入缓冲区 putchar(inBuffer[ptr++] = c);
else //缓冲区已满 {
putchar(&#39;\7&#39;);
//== 0x07 蜂鸣符,PC回响一声 }
注释已经很详细了,这里不再详细解释。
scanf的移植程序部分已经完成,如果需要从键盘读入字符,可以仿照上述函数写getchar函数。具体使用和设置见使用示例。
另外,iar的安装文件夹下,430文件夹下有一个src文件夹,lib/clib文件夹下(我的具体文件夹是:D:\Program Files\IAR Systems\Embedded Workbench 6.0 Evaluation\430\src\lib\clib\getchar.c),有一个getchar.c文件,这是getchar的函数,内容如下:
#include &stdio.h& extern char _low_level_get(void);
/* Read one char from I/O */ /* Should be supplied by user */ static void put_message(char *s)
while (*s)
putchar(*s++);
#define LINE_LENGTH 80
/* Change if you need */ #define In_DELETE 0x7F
/* ASCII &DEL& */ #define In_EOL &#39;\r&#39; /* ASCII &CR& */ #define In_SKIP &#39;\3&#39; /* ASCII control-C */ #define In_EOF &#39;\x1A&#39; /* ASCII control-Z */ #define Out_DELETE &\x8 \x8& /* VT100 backspace and clear */ #define Out_SKIP &^C\n& /* ^C and new line */ #define Out_EOF &^Z& /* ^Z and return EOF */ int getchar(void)
static char io_buffer[LINE_LENGTH + 2];
/* Where to put chars */ static int
/* Pointer in buffer */ char c;
if (io_buffer[ptr])
return (io_buffer[ptr++]);
if ((c = _low_level_get()) == In_EOF && !ptr)
put_message(Out_EOF);
return EOF;
if (c == In_DELETE)
put_message(Out_DELETE);
else if (c == In_SKIP)
put_message(Out_SKIP);
ptr = LINE_LENGTH + 1;
/* Where there always is a zero... */ break;
else if (c == In_EOL)
putchar(io_buffer[ptr++] = &#39;\n&#39;);
io_buffer[ptr] = 0;
else if (ptr & LINE_LENGTH)
if (c &= &#39; &#39;)
putchar(io_buffer[ptr++] = c);
putchar(&#39;\7&#39;);
_low_level_get(void); 这个函数需用户定义,不过这个getchar函数不支持退格键,可以更改以支持;_low_level_get(void);这个函数可以直接调用UartReadChar();这个函数,使用时,把getchar.c加入项目,同时在项目中添加_low_level_get(void);函数,函数体只有一句:return UartReadChar();即可。
程序调用示例:
程序使用方式,项目中添加printf.c文件和scanf.c文件(用printf函数则加printf.c文件,用scanf函数就添加scanf.c文件),在要使用函数的地方包含stdio.h(编译器自带库&&标准输入输出库)
还要设置使用库和printf的大小:
如果不进行这项设置,使用scanf时将报错:
Error[e27]: Entry &getchar& in module Scanf ( G:\work\程序库\Printf\Debug\Obj\Scanf.r43 ) redefined in module ?getchar ( D:\Program Files\IAR Systems\Embedded;用的是C语言,这里选择CLIB。
然后设置库选项:
这里选择大尺寸,目的是支持所有的格式,因为所用单片机有64kb的程序存储空间,足够使用,如果程序存储空间不够大,推荐选择中尺寸或小尺寸。大尺寸printf占用空间 4.8kb、scanf :2.3kb,中尺寸 printf:2.5kb、scanf:1.6kb,小尺寸 printf:1.6kb。实际使用时根据需要进行选择。
同时要加入Lcd12864的使用(c文件,h文件(要调用lcd12864的初始化函数))Uart和液晶一样要调用初始化函数。
#include &msp430x16x.h& #include &stdio.h& #include &Uart.h& #include &Lcd12864.h&
头文件包含。
void main( void )
// Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD;
ClkInit();
LcdInit();
UartInit(38400,&#39;n&#39;,8,1);//串口初始化,设置成38400bps,无校验,8位数据,1位停止 // _EINT();
//scanf(&%d&,&a); //printf(&刘中原%d\n&,a); printf(&刘中原%f\n&,23.6);
printf(&刘中原%1.2f\n&,23.6);
使用时,先调用液晶和串口的初始化函数,然后开中断;就可以正常的调用scanf和printf函数了。
至此,printf和scanf的移植全部完成,使用这两个函数将给单片机的输入输出带来极大方便。另外,Lcd12864的液晶使用是4行显示,空间较小,可能需要定位至具体位置,以使界面看起来更合理,为此,在Printf中再添加一个定位函数(GotoXY):
void GotoXY(char x,char y)
addr = 0x80 + x / 2;
else if(y==1)
addr = 0x90 + x / 2;
else if(y==2)
addr = 0x88 + x / 2;
addr = 0x98 + x / 2;
LcdWriteComm(addr);
//是奇数,后移一位(写入空格) {
LcdWriteData(0x20);
这样就方便了液晶程序的编写。
又加入一个函数,在printf.c里,目的是支持退格键,内容如下:
void BackSpace()
char addr,
addr = LcdReadAddr();
//当前地址 LcdWriteData(0x20);
//写入一个空字符,根据地址判断是否为前半字 if(addr == LcdReadAddr())
//前半字 {
if(addr == 0x80)
else if(addr == 0x90)
addr = 0x87;
else if(addr == 0x88)
addr = 0x97;
else if(addr == 0x98)
addr = 0x8F;
else addr = addr - 1;
LcdWriteComm(addr);
LcdReadData();
//空读取 dat = LcdReadData();
LcdWriteComm(addr);
if(dat & 0x80)
LcdWriteData(dat);
LcdWriteComm(addr);
好好学习,天天向上。
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
状元15806分
给你个参考,
******************************************************
#include &.h&
#include &stdarg.h&
#include &string.h&
#include &uart.h&
/ ********************************************************************
&*静态函数声明
&* ********************************************************************/
static void Vs_Printf(char *s,char *format,va_list arg);
static void IntToString(int temp,char *pchar);
/ ********************************************************************
&* 函数名 & : & UartInit
&* 函数功能 &: &初始化的USCI寄存器,使其工作在UART模式
&* 形参 & & : &无
&* 返回值 & : &无
&* ********************************************************************/
void UartInit()
& & / ****************************************************************************
& & &* P1.1设为输入作为uart的数据输入口
& & &* P1.2设为输出作为UART的数据输出口
& & &****************************************************************************/
& & P1DIR &=~BIT1;
& & P1DIR |=(BIT2 );
& & / ****************************************************************************
& & &* 将P1.1和P1.2口配置为第三功能口,UART功能
& & &****************************************************************************/
& & P1SEL |= &BIT1 + BIT2 ;
& & P1SEL2 |= BIT1 + BIT2;
& & / ****************************************************************************
& & &* 配置U0CTL1寄存器,在UCSWRST置位的情况下(即保持USCI软件复位的情况下配置各
& & &* 个寄存器的各标志位)置位UCSSEL_2配置时钟源为SMCLK。其他位为0
& & &****************************************************************************/
& & U0CTL1 |= UCSWRST; & & & & & & & & & & &// Set SW Reset
& & U0CTL1 = UCSSEL_2+ UCSWRST; & & & & & & & // Use SMCLK, keep SW reset
& & / ****************************************************************************
& & &* 配置波特率大小,公式:(U0BR1&&8+U0BR0)=(int)(source_clk/baud rate)
& & &* U0MCTL为(source_clk/baud rate)的余数乘以8之后的值对应表中的值,实现控
& & &* 制调制系数
& & &* 大小如表所示:
& & &* _______________________________________________________________
& & &* |余数*8 &|1 & & |2 & & |3 & & |4 & & |5 & & |6 & & |7 & & |
& & &* |U0MCTL |0x08 &|0x88 &|0x2A &|0x55 &|0x6B &|0xdd &|0xef | &&
& & &****************************************************************************/
& & U0BR0 = 0x04; & & & & & & & & & & & & &&
& & U0BR1 = 0x01;
& & U0MCTL = 0x2A;
& & / ****************************************************************
& & * 解除软件复位,使USCI开始工作
& & ****************************************************************/
& & U0CTL1 &= ~UCSWRST;
& & / ****************************************************************
& & &* 允许接收中断
& & &****************************************************************/
& & UC0IE |= UCA0RXIE; & & & & & & & & & & & & & & &// Enable RX int
/ ********************************************************************
&* 函数名 & : & UartPutchar
&* 函数功能 &: &向串口终端发送一个字符
&* 形参 & & : &Txdata为待发送的字符
&* 返回值 & : &无
*******************************************************************/
void UartPutchar(char Txdata)
& & if(Txdata==&#39;\n&#39;){
& & & &while(UCA0STAT & UCBUSY);
& & & &UCA0TXBUF=&#39;\r&#39;;
& & while(UCA0STAT & UCBUSY);
& & UCA0TXBUF=T
/ ********************************************************************
&* 函数名 & : & UartSendString
&* 函数功能 &: &向串口终端发送一个字符串
&* 形参 & & : &pt为字符串指针。
&* 返回值 & : &无
&*******************************************************************/
void UartSendString(char *pt)
& & while(*pt)
& & & & UartPutchar(*pt++);
/ *******************************************************************
&* 函数名 & &: & IntToString
&* 函数功能 &: &将一个整形的书转化成为一个表现形式一样的字符串
&* 说明 & & &: &举例说明功能,若有一个整数为65535,该函数作用就是将
&* & & & & & & &&65535&其转化为字符串
&* 形参 & & &: &temp为待装换的整数,pchar为转化成的字符串所存储的地址
&* 返回值 & &: &无
********************************************************************/
void IntToString(int temp,char *pchar)
& & char ch,*p=
& & while(temp!=0){
& & & &*pchar++=(char)(temp+0x30);
& & & &temp/=10;
& & *pchar--=&#39;\0&#39;;
& & while(pchar&p){
& & & &ch=*p;
& & & &*p++=*
& & & &*pchar--=
/ ********************************************************************
&* 函数名 & : & Vs_Printf
&* 函数功能 &: &将参数指针arg所指的不定参数按照格式字符串format中的一一对应的格
* & & & & & &式转化后生成一个新的字符串存于地址s中。
&* 形参 & & : &s为最终形成的字符串存储地址,format为格式字符串,arg为不定参数指
* & & & & & &针。
&* 返回值 & : &无
********************************************************************/
void Vs_Printf(char *s,char *format,va_list arg)
& & char *
& & char *
& & for(pchar=*pchar++){
& & & &if(*pchar !=&#39;%&#39;){
& & & & & &*s++=*
& & & & & &
& & & &switch(*++pchar){
& & & & & &case &#39;d&#39; & :{
& & & & & & & IntToString(va_arg(arg,int),s);
& & & & & & & while(*s++);
& & & & & & & *--s=&#39;0&#39;;
& & & & & & &
& & & & & &}
& & & & & &case &#39;s&#39; & :{
& & & & & & & temp=va_arg(arg,char *);
& & & & & & & while(*s++=*temp++);
& & & & & & & *--s=&#39;0&#39;;
& & & & & & &
& & & & & &}
& & & & & &case &#39;c&#39; & :{
& & & & & & & *s++=va_arg(arg,char);
& & & & & & &
& & & & & &}
& & & & & &default & & & :
& & *s=&#39;\0&#39;;
/ ********************************************************************
&* 函数名 & : & Printf
&* 函数功能 &: &格式化输出
&* 形参 & & : &fmt为格式字符串,&为不定(类型不定、个数不定)形参
&* 返回值 & : &无
*******************************************************************/
void Printf(char *fmt,...)
& & / ********************************************************
& & &* va_list类型声明一个参数指针ap,该变量将依次引用各个参数
& & &* ******************************************************/
& & char string[256];
& & / ********************************************************
& & &* va_start(ap,fmt),该函数将ap指针指向参数列表中的最后一个
& & &* 有名参数fmt
& & &* ******************************************************/
& & va_start(ap,fmt);
& & / ********************************************************
& & &* Vs_Printf,该函数将ap指向的无名参数按照fmt固定的格式转化
& & &* 成为字符串存于string中
& & &* ******************************************************/
& & Vs_Printf(string,fmt,ap);
& & UartSendString(string);
& & / ********************************************************
& & &* 最后调用va_end(ap)释放指针
& & &* ******************************************************/
& & va_end(ap);
/ ************************ end of file ******************************/
将文件uart.c添加到工程中去,并建立主函数进行验证。笔者的写的测试主函数如下所示:
#include &.h&
#include &clock.h&
#include &uart.h&&
void main()
& & int year=2012;
& & WDTCTL = WDTPW + WDTHOLD;
& & Init_Clk();
& & UartInit();
& & char *str=&Hello World!&;
& & Printf(&year=%d\n str=%s\n&,year,str);
好好学习,天天向上。
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
榜眼26410分
& CCS里面是支持printf来调试的,关于设置方面,你可以参考下面的链接:
http://processors./index.php/Printf_support_for_MSP430__compiler
You have posted to a forum that requires a moderator to approve posts before they are publicly available.}

我要回帖

更多关于 vsnprintf函数 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信