專家支招:單片機(jī)中無符號數(shù)運(yùn)算出現(xiàn)的問題
發(fā)布時間:2015-10-05 責(zé)任編輯:susan
【導(dǎo)讀】在單片機(jī)編程中,我們經(jīng)常會用到一些無符號數(shù)與有符號數(shù)的混合運(yùn)算,另外我們所用的單片機(jī)很有可能是16位或者8位的,這樣,編程時所用的一些變量的取值范圍會對我們的運(yùn)算有所限制。
比如說8位的單片機(jī)無符號數(shù)最大值為255,有符號最大數(shù)為127;16位單片機(jī)無符號數(shù)最大值為65535,有符號數(shù)最大值為32767.對于32的單片機(jī)來說,因?yàn)槲覀円话闼幚淼闹岛苌倌艹^有符號數(shù)的最大取值,所以比較少遇到下面出現(xiàn)的問題.
在一些運(yùn)算中,我們希望有些數(shù)能表示正負(fù),這就得用有符號數(shù),而有些數(shù)的取值會超過有符號數(shù)的最大值,這時我們就得用無符數(shù)來表示.下面是我編程時遇到的兩個問題(用的是MC9S12XS128處理器,16位的單片機(jī)).
變量的聲明如下:
int iError;
unsigned int uiExpectSpeed;
unsigned int uiCurrentSpeed;
語句如下:
iError = (uiExpectSpeed - uiCurrentSpeed)/3; //(1) 第一個語句
在調(diào)試的過程中發(fā)現(xiàn)這個iError的值有時候會特別大,最后才發(fā)現(xiàn)是上面的這句語句出錯了!然后修改成下面兩句結(jié)果就對了:
iError = uiExpectSpeed - uiCurrentSpeed; //(2)第二個語句
iError = iError/3; //(3)第三個語句
不同類型的數(shù)據(jù)在進(jìn)行混合運(yùn)算時會有一個隱試的類型轉(zhuǎn)換過程,有符號數(shù)與無符號數(shù)混合運(yùn)算,有符號數(shù)會被轉(zhuǎn)換成無符號數(shù)后再參加運(yùn)算.
在上面的第一個語句中,如果uiExpectSpeed 比uiCurrentSpeed的值大,也就是uiExpectSpeed - uiCurrentSpeed結(jié)果為一正值,那不會出現(xiàn)啥問題,但當(dāng)uiExpectSpeed 比uiCurrentSpeed的值小時就出現(xiàn)問題了,此時uiExpectSpeed - uiCurrentSpeed的臨時結(jié)果存放在16位的寄存器中,且最高位1,對于有符號數(shù)來說會把這一個位解釋為符號位,1表示負(fù)數(shù),而對于無符號來說這個位就表示數(shù)值,接著這個臨時的結(jié)果除以3后,所得到的結(jié)果的最高位變?yōu)榱?此時該結(jié)果會轉(zhuǎn)換為一個有符合數(shù)(不管是有符號數(shù),還是無符號數(shù),最高位為0時,所表示的數(shù)值就是一樣的),賦給iError.本應(yīng)該得到一個負(fù)數(shù)的,但最終卻得到了一個比較大的正數(shù)!在第一個語句中,如果沒有除以3,而是兩個數(shù)作差后直接賦給iError則是不會出錯的,雖然uiExpectSpeed - uiCurrentSpeed運(yùn)算的結(jié)果是一個很大的正數(shù)(寄存器的最高位為1),但在這個臨時結(jié)果賦給iError這個變量時,會先把這個值轉(zhuǎn)換為一個有符號數(shù)賦給iError.其實(shí),在把uiExpectSpeed - uiCurrentSpeed運(yùn)算的結(jié)果賦給iError時是把所有的位原封不動的復(fù)制到iErrorr所表示的內(nèi)存單元中的,只是我們是以有符號數(shù)來解釋這個內(nèi)存單元中的內(nèi)容,所以這個很大的正數(shù)就變成了一個負(fù)數(shù)!(數(shù)據(jù)在處理器內(nèi)是以補(bǔ)碼表示的,對于數(shù)據(jù)是正還是負(fù)只是人們的解釋不同而已).所以我就用后面的兩句替換了第一句,這樣不管uiExpectSpeed - uiCurrentSpeed的差值是正還是負(fù)都能得到正確的結(jié)果了.
下面是我在做超聲波測距時遇到的又一個很隱蔽的問題:
unsigned int start; //表示計時開始時計數(shù)器的值
unsigned int end; //表示計時結(jié)束時計數(shù)器的值
unsigned int error;
unsigned int distance; //表示距離
unsigned int time; //表示從計時開始到結(jié)束所用的時間
unsigned int remainder;//余數(shù)
start = TCNT;// 計時開始, TCNT為16位的計時器寄存器
..............一段時間后(這段時間小于計時器TCNT從0計數(shù)到最大值65535所表示的時間)...........
end = TCNT; //計時結(jié)束
error = end - start; //注意,end有可能比start小,但由于都是無符號數(shù),所以最后得到的差值就是這段時間內(nèi)計數(shù)器TCNT的增量.
time = error/625; //單位為ms TCNT每1ms內(nèi)數(shù)值增加625(這個數(shù)與TCNT所用的時鐘有關(guān))
distance = 17*time; //單位為cm, 距離為速度乘以時間再除以2就是聲波所傳波的距離
這塊由于是分步計算的,所以會有比較大的誤差(主要是由于error/625后的余數(shù)被丟棄了) 于是我改成如下語句:
start = TCNT;// 計時開始, TCNT為16位的計時器寄存器
..............一段時間后(這段時間小于計時器TCNT從0計數(shù)到最大值65535所表示的時間)...........
end = TCNT; //計時結(jié)束
error = end - start; //注意,end有可能比start小,但由于都是無符號數(shù),所以最后得到的差值就是這段時間內(nèi)計數(shù)器TCNT的增量.
distance = (17*error)/625; //單位為cm, 將上面的最后兩句結(jié)合成一句,先乘后除就會減小誤差
但改后上面distance = (17*error)/625; 這句就錯了,因?yàn)閑rror的值可能很大,最大可以達(dá)到65535,所以17*error結(jié)果很有可能會超過65535,但這個處理器是16位的,也就是說這個處理器的數(shù)據(jù)寄存器為16位,最大的表示數(shù)值也就65535,所以17*error大于65535后就會被截斷存入寄存器中.也就是說存入寄存器中的值為(17*error)%65536,當(dāng)再用這個值除以625時得到的很有可能就是0或者個位數(shù)的值,不管怎樣,此時得到的結(jié)果都是錯誤的值了!!
結(jié)合上面兩種情況,最后我改成如下:
start = TCNT;// 計時開始, TCNT為16位的計時器寄存器
..............一段時間后(這段時間小于計時器TCNT從0計數(shù)到最大值65535所表示的時間)...........
end = TCNT; //計時結(jié)束
error = end - start; //注意,end有可能比start小,但由于都是無符號數(shù),所以最后得到的差值就是這段時間內(nèi)計數(shù)器TCNT的增量.
time = error/625; //單位為ms
remainder = error - time*625;//計算上一句中丟棄的余數(shù),沒有用remainder = error%625,是因?yàn)槌ê芎臅r!!
distance = 17*time + (17*remainder + 312)/625; //單位為cm,此處的312(625/2)是考慮到四舍五入的.
特別推薦
- 利用運(yùn)動喚醒功能優(yōu)化視覺系統(tǒng)的功耗
- 宜普電源轉(zhuǎn)換公司勝訴,美國國際貿(mào)易委員會終裁確認(rèn)英諾賽科侵權(quán)
- 功率器件熱設(shè)計基礎(chǔ)(一)——功率半導(dǎo)體的熱阻
- 泰矽微重磅發(fā)布超高集成度車規(guī)觸控芯片TCAE10
- 瑞薩與尼得科攜手開發(fā)創(chuàng)新“8合1”概念驗(yàn)證,為電動汽車驅(qū)動電機(jī)提供高階集成
- Bourns 推出兩款大電流氣體放電管 (GDT) 新品,適用于交流和直流電源設(shè)計
- 多維科技推出用于游戲手柄的新型TMR傳感器芯片TMR2615和TMR2617
技術(shù)文章更多>>
- 利用IMU增強(qiáng)機(jī)器人定位:實(shí)現(xiàn)精確導(dǎo)航的基礎(chǔ)技術(shù)
- 貿(mào)澤電子與Analog Devices聯(lián)手推出新電子書探討電子設(shè)計中的電源效率與穩(wěn)健性
- 下一代汽車微控制器:意法半導(dǎo)體技術(shù)解析
- 安森美與伍爾特電子攜手升級高精度電力電子應(yīng)用虛擬設(shè)計
- 48 V技術(shù)的魅力:系統(tǒng)級應(yīng)用中的重要性、優(yōu)勢與關(guān)鍵要素
技術(shù)白皮書下載更多>>
- 車規(guī)與基于V2X的車輛協(xié)同主動避撞技術(shù)展望
- 數(shù)字隔離助力新能源汽車安全隔離的新挑戰(zhàn)
- 汽車模塊拋負(fù)載的解決方案
- 車用連接器的安全創(chuàng)新應(yīng)用
- Melexis Actuators Business Unit
- Position / Current Sensors - Triaxis Hall
熱門搜索
通訊電源
通用技術(shù)
同步電機(jī)
同軸連接器
圖像傳感器
陀螺傳感器
萬用表
萬用表使用
網(wǎng)絡(luò)電容
微波
微波功率管
微波開關(guān)
微波連接器
微波器件
微波三極管
微波振蕩器
微電機(jī)
微調(diào)電容
微動開關(guān)
微蜂窩
位置傳感器
溫度保險絲
溫度傳感器
溫控開關(guān)
溫控可控硅
聞泰
穩(wěn)壓電源
穩(wěn)壓二極管
穩(wěn)壓管
無焊端子