关于数据类型的问题

每一次失败都是为了更好的成长,嗯!!!


省赛失败总结一:关于实现ADC输出电压保留两位小数这一功能,我,,,挣扎了很长时间,但是数据类型还是溢出(表现就是电压显示到255就自动归零然后重新加),赛后重写代码时,发现了问题所在,看代码,,,,,

int val;
val = I2CReadNAK();//读到一个u8类型的数据(0-255)
I2CStop();
val = (val * 500) / 255;

这里我虽然把val定义成了u16类型(范围0-65535),按理说应该够了,但是,,,,(val * 500),当val对应最大值也就是255时,对应的电压是500,而255*500是多少呢?127500,远远大于65535,,,溢!出!了!,在这里就已经发生了数据的溢出,,所以才一直得不到正确结果,,,然后自己想偏了,,,唉,,,自己赛前也没有关于数据类型问题的概念,emmm,准备不足,这次要好好弥补一下自己知识上的漏洞(对自己还是蛮无语的,额,,,数据还是溢出难道不应该是想着再扩大一下数据类型嘛???怎么回事儿小老弟???)


下面是实现ADC保留两位小数方法:
1.先将val定义为浮点数,然后再强制转换成u16类型的整数(或者把val定义成u32类型,这样不需要强制转换):

#define VCC 500//定义电压系统的电压是5.00v
/*读取当前的ADC转换值,chn为ADC的通道号0-3*/
float GetADCValue(u8 chn)
{
	float val;
	
	I2CStart();
	if(!I2CWrite(0x48<<1))//寻址PCF8591,如未应答,则停止操作并返回0
	{
		I2CStop();
		return 0;
	}
	I2CWrite(0x40 | chn);//写入控制字节,选择转换通道
	I2CStart();
	I2CWrite((0x48<<1) | 0x01);
	I2CReadACK();//先读取一个空字节,提供转换时间
	val = I2CReadNAK();//这里转换完的值只是n个分辨率,即n个刻度
	I2CStop();
	
	val = 1.0*((val*VCC) / 255);//将读取的数值转换为电压值(浮点数),val*分辩率
	return val;
}

/*刷新数据时再强制转换为u16类型*/
void RefreshVal()
{
	u8 i;
	
	u16 val;
	val = (u16)GetADCValue(3);//强制转换为整形,这里必须要强制转换!!!
	//因为我们定义的电压是扩大100之后的,然后再人为加上小数点,所以我们只需要整数部分就可以了
	
	for(i = 6; i>2; i--)
	{
		LedBuff[i] = 0xFF;//关闭不需要显示的数码管
	}
	LedBuff[0] = LedChar[val % 10];//电压的个位
	LedBuff[1] = LedChar[(val / 10) % 10];//十位
	LedBuff[2] = LedChar[(val / 100) % 10];//百位
	LedBuff[2] &= 0x7F;//第二个数码管人为加上小数点
	LedBuff[7] &= 0xC1;//第7个数码管显示u
}

2.还有一种写法就是,我们还是定义u16类型的val,但是在转换电压的时候,要把val强制转换成u32类型


u16 GetADCValue(u8 chn)
{
	u16 val;
	
	I2CStart();
	if(!I2CWrite(0x48<<1))//寻址PCF8591,如未应答,则停止操作并返回0
	{
		I2CStop();
		return 0;
	}
	I2CWrite(0x40 | chn);//写入控制字节,选择转换通道
	I2CStart();
	I2CWrite((0x48<<1) | 0x01);
	I2CReadACK();//先读取一个空字节,提供转换时间
	val = I2CReadNAK();//这里转换完的值只是n个分辨率,即n个刻度
	I2CStop();
	
	val = ((u32)val*VCC) / 255;//将读取的数值转换为电压值,val*分辩率
	return val;
}

解释一下原因:这个问题是不同数据类型间的相互转换的问题,51支持不同数据类型之间的混合运算,但是在进行混合运算之前,会先转换成同一类型的数据,转换原则是:短字节数据向长字节数据转换举个例子:

unsigned char a;
unsigned int b;
unsigned int c;

a = 70;
b = 1000;

c = a * b;

运行之后c的值是多少呢?70000吗?答案是否定的,u16类型的范围是0-65535,显然已经溢出了,此时c的值是:70000-65536 = 4464
那如果把c改成 unsigned long 型的变量呢?如果你试验一下就会发现,结果还是4464,为什么呢?这是因为在做a*b的乘法运算时数据就已经溢出了,在进行不同类型数据运算时,每一步运算都会进行识别判断,而不会进行一个总的分析判断!!!! 这一点一定要记清楚!!!!


数据转换部分延伸:

  1. 不同变量类型之间的赋值问题:短字节类型向长字节赋值时,值保持不变(例:u8 a = 100,u16 b = 500)将a赋值给b,b的值为100;
  2. 长字节向短字节赋值时:还是上面的例子,如果把b赋值给a,那么a只取b的低8位,要先把b转换成16进制表示的数据,然后取低8位,转换成二进制再赋值给a
  3. 特殊的:bit类型的强制转换(例:a = (bit)b),是判断b是0还是非0,如果b为0,那么a为0,b非0,a为1

你可能感兴趣的:(蓝桥备赛)