中级会员
 
- 积分
- 205
- 金钱
- 205
- 注册时间
- 2013-6-8
- 在线时间
- 2 小时
|
最近在做8位单片机的程序,真的是郁闷了,查了半天才查出这个问题,
现分享给大家,也提醒自己一定要注意MCU的位数和编译器和标准C之间的类型问题。
就是这个表达式15*60*50=45000, 0xAFC8
PC机上测试:
unsigned long cnt=15*60*50;
printf("cnt=%d,%#x",cnt,cnt);
//输出 45000,0xAFC8 结果正确没问题
8位单片机PIC16F1509上测试:sizeof(unsigned long)是等于4;
unsigned long cnt=15*60*50;
itoa(cnt, buf, 10); dputs(buf);//转为10进制字符串
itoa(cnt, buf, 16); dputs(buf);//转为16进制字符串
//输出结果:-20536, -5038
//-20536(10进制)=-5038(16进制)
//这结果碉堡了,我说我的程序老是不对劲
原因:
表达式结果是45000绝对没错,但是8位单片机居然会对这个数
做溢出处理,从32767溢出到-32768,再向上继续溢出,所以最终
结果就成了-20536。
解决方法,使用标准给每一个数都指明一下类型就OK了:
unsigned long cnt=15UL*60UL*50UL;
char *itoa(long val, char *buf, int radix)
{
char *high, *low, tmp;
int digit;
high = buf;
if (val < 0) //判断符号
{
*high++ = '-';
val = -val;
}
low = high; //记录数字的低位所处的位置
do //从个位开始分离,数字是反转的
{
digit = val % radix; //个位
val /= radix; //val向个位移动
if (digit > 9)
*high++ = (char)(digit - 10 + 'A'); //16进制
else
*high++ = (char)(digit + '0'); //10进制
}
while(val > 0);
*high-- = '\0'; //添加结束符, high指向数字的高位,开始进行反转
for (; low < high; low++, high--)
{
tmp = *high;
*high = *low;
*low = tmp;
}
return buf;
}
|
|