和记娱乐


网站导航

联系我们

和记娱乐

联系人: 

电 话:021-64057486

公司网址:http://www.happy123456789.com

   址:成都市松江区漕河泾松江新兴产业园区研展路丰产支路55号B座803室

邮编:201165


通信知识

您的当前位置: 和记娱乐主页 > 通信知识 >

单片机中无符号数运算出现的问题

发布日期:2019-11-25 10:08 来源:和记h88 发布人:和记娱乐 点击:

  在单片机编程中,我们经常会用到一些无符号数与有符号数的混合运算,另外我们所用的单片机很有可能是16位或者8位的,这样,编程时所用的一些变量的取值范围会对我们的 运算有所.比如说8位的单片机无符号数最大值为255,有符号最大数为127;16位单片机无符号数最大值为65535,有符号数最大值为32767.对于32的单片机来说,因为我们一般所处理的值很少能超过有符号数的最大取值,所以比较少遇到下面出现的问题.

  在一些运算中,我们希望有些数能表示正负,这就得用有符号数,而有些数的取值会超过有符号数的最大值,这时我们就得用无符数来表示.下面是我编程时遇到的两个问题(用的是MC9S12XS128处理器,16位的单片机).

  在调试的过程中发现这个iError的值有时候会特别大,最后才发现是的这句语句出错了!然后修改成下面两句结果就对了:

  不同类型的数据在进行混合运算时会有一个隐试的类型转换过程,有符号数与无符号数混合运算,有符号数会被转换成无符号数后再参加运算.

  在的第一个语句中,如果uiExpectSpeed 比uiCurrentSpeed的值大,也就是uiExpectSpeed - uiCurrentSpeed结果为一正值,那不会出现啥问题,但当uiExpectSpeed 比uiCurrentSpeed的值小时就出现问题了,此时uiExpectSpeed - uiCurrentSpeed的临时结果存放在16位的寄存器中,且最高位1,对于有符号数来说会把这一个位解释为符号位,1表示负数,而对于无符号来说这个位就表示数值,接着这个临时的结果除以3后,所得到的结果的最高位变为了0此时该结果会转换为一个有符合数(不管是有符号数,还是无符号数,最高位为0时,所表示的数值就是一样的),赋给iError.本应该得到一个负数的,但最终却得到了一个比较大的正数!在第一个语句中,如果没有除以3,而是两个数作差后直接赋给iError则是不会出错的,虽然uiExpectSpeed - uiCurrentSpeed运算的结果是一个很大的正数(寄存器的最高位为1),但在这个临时结果赋给iError这个变量时,会先把这个值转换为一个有符号数赋给iError.其实,在把uiExpectSpeed - uiCurrentSpeed运算的结果赋给iError时是把所有的位原封不动的复制到iErrorr所表示的内存单元中的,只是我们是以有符号数来解释这个内存单元中的内容,所以这个很大的正数就变成了一个负数!(数据在处理器内是以补码表示的,对于数据是正还是负只是人们的解释不同而已).所以我就用后面的两句替换了第一句,这样不管uiExpectSpeed - uiCurrentSpeed的差值是正还是负都能得到正确的结果了.

  这块由于是分步计算的,所以会有比较大的误差(主要是由于error/625后的余数被丢弃了) 于是我改成如下语句:

  但改后distance = (17*error)/625; 这句就错了,因为error的值可能很大,最大可以达到65535,所以17*error结果很有可能会超过65535,但这个处理器是16位的,也就是说这个处理器的数据寄存器为16位,最大的表示数值也就65535,所以17*error大于65535后就会被截断存入寄存器中.也就是说存入寄存器中的值为(17*error)%65536,当再用这个值除以625时得到的很有可能就是0或者个位数的值,不管怎样,此时得到的结果都是错误的值了!!

      和记娱乐,和记h88,h88平台官网