atmega16的串口和主机通讯
我现在用atmega16的串口和主机通讯。下面是我发送字符串的函数:
void Uart_Printf(char *fmt,...)
{
va_list ap;
char string[256];
va_start(ap,fmt);
sprintf(string,fmt,ap);
Uart_sentstr(string);
va_end(ap);
}
eg:Uart_Printf("\n\nI love you \n");
在超级终端上可以正常显示。比如我要显示一个变量x=348,然后我用Uart_Printf("\nx=%d",x);输出它,但是在终端上面显示的不是我想要的,在这里就产生矛盾了。因为以前学过vsprintf这个函数均可以按照上面的两种方法输出,可不知道为什么sprintf不可以呢
希望有人指点我一下,怎样可以发送一个变量到终端,
谢谢。。。
[解决办法]
sprintf是C语言标准库里的函数,应该是可以向你上面那样用的,不知道你的输出是什么,如果不对,你可以调试跟踪一下,保证入口参数正确,看sprintf解析的是否正确,如果不正确的话,只能说你的编译器的C语言标准库可能有问题,你就自己写一个类sprintf的函数吧,这个网上有很多的例子。
[解决办法]
标准写法是用vsprintf(string,fmt,ap);
vsprintf和sprintf是不一样的
看两者的代码就知道了,vsprintf接收的第三个参数是将参数结构体化后的指针,而sprintf是不限于第三个参数的
下面给你个例子可以帮助你理解
如果要用sprintf的话要这样写:
pp = (unsigned int *)≈sprintf(string,fmt,*((int *)*pp));
[解决办法]
vsprintf和sprintf的区别在第三个参数,也就是你Uart_Printf函数的第二个以后的参数,你这样调用根本没第二个参数,自然就没区别了
Uart_Printf标准的写法就是用vsprintf的,不知道你用sprintf是哪里看来的。
vsprintf函数是三个参数,而sprintf参数是不定个数的,这样的话想想也知道不可能直接把本来应该赋给vsprintf的参数照搬给sprintf
你看下vsprintf和sprintf的源码就知道了,最大的区别就是sprintf一开头又做了次va_start(arglist, format);而vsprintf没有,结合我上面给的例子,就应该能想通为什么了
[解决办法]
如果你只需要固定个数的固定类型参数,可以用我之前给的方法
unsigned int * pp = (unsigned int *)≈
sprintf(string,fmt,*((int *)*pp));
用这两句替换你的sprintf(string,fmt,ap);这句,就可以实现输出“一个”int类型的参数了
但这样并不通用,最好的方式是你可以自己写一个vsprintf函数,你首先把sprintf源码复制过来,然后把第三个参数从“...”改成“va_list ap”,然后函数里的
va_list arglist; 和 va_start(arglist, format); 两句注销掉,应该就可以了
其实sprintf比vsprintf就是多了一次对不定个数参数的封装(也就是va_start(arglist, format);这句),而你的Uart_Printf函数其实已经做过一遍了