官术网_书友最值得收藏!

1.6 有符號與無符號數應用、數位分解、位操作

Keil C51的數據類型如表1-8所示。大量案例中會使用到無符號數,對于255以內的整數,可定義為u8類型(相當于字節類型BYTE);對于0~65 535范圍內的整數,可定義為u16類型(相當于字類型WORD)。涉及正負數(有符號數)處理的案例,例如,溫度控制程序中有零上溫度與零下溫度,由于其溫度傳感器實際上可處理范圍為溫55~125℃,為使程序對溫度值進行正確比較,程序中將溫度數據類型定義為char類型(Keil C默認char為signed char類型,即有符號字符型,其取值范圍為其128~127)。

表1-8 Keil C51的數據類型

另外,大量案例用到的延時程序中可能有u8類型,也可能有u16類型。編寫C程序時,例如,給某延時參數x賦值2000(0x07D0),如果參數x定義為u8類型而不是u16類型,編譯時并不會報錯,但x實際所獲得的值將為0x07D0的低字節0xD0(208),編寫的語句為x=2000,而實際上x=208。這一點在單片機C語言程序設計過程中要特別注意。

大量設計涉及用數碼管顯示整數或浮點數,這就要對顯示數據進行數位分解,例如:

又如:

如果要得到x的各個數位,可以先將x乘以100,然后再分解各數位:

上面for循環中的循環條件本來要寫成i>=0,但當i=0時,如果將i再減1,i變為0xFF,這個無符號數仍被認為大于或等于0,這樣就不能保證5次循環了,因此要改寫成i !=0xFF。如果將i定義成char類型而不是u8類型,使用i>=0時才能得到正確結果,這是因為前面已提到Keil C默認char為signed char類型。

上述數位分解常用于數碼管數字顯示,這是因為數碼管顯示時要根據各數位提取數碼管段碼。

在設計一般的C語言程序時,位操作較少被使用,但在單片機應用系統設計過程中,位操作將被大量使用。在有關發光二極管(LED)流水燈、數碼管位掃描控制、串行收/發信息、鍵盤掃描等大量案例中,位的各相關操作符及相關函數均會頻繁出現。因此,要熟練掌握字節位循環左移函數(_crol_)、字節位循環右移函數(_cror_)、位左移(<<)、位右移(>>)、與(&)、或(|)、取反(~)、異或(^)、非(!)等。要注意,對于單個位,非(!)操作與取反(~)操作是等價的;但對于單個位以外的其他類型或定義,其操作則不等價。

下面是有關位操作的幾個簡單應用。

例如,將P1的P1.7~P1.0引腳逐個循環輪流置1,可先設字節變量c=0x01,然后在循環語句中執行c=_cror_(c,1),并使P1=c,這樣即可使P1依次為10000000,01000000,00100000,…, 00000001,如此重復。如果要將P1.7~P1.0引腳逐個循環輪流置0,可先設c=0xFE,然后使用同樣的循環移位操作即可。對于這兩項操作,如果已經有循環語句及控制變量i(取值為0~7),還可以有P1=0x80>>i及P1=~(0x80>>i)語句。這類位操作在LED流水燈或集成式數碼管位掃描中時常會被用到。

又如,已知P2.3連接外部LED或蜂鳴器,如果要使LED閃爍或蜂鳴器發聲,可先定義sbit LED=P2^3或sbit BEEP=P2^3,然后在循環語句中執行語句LED=~LED或BEEP=~BEEP即可。對于獨立的位定義,執行取反(~)與非(!)操作效果是一樣的,但對于字節變量則是不同的。對于這里的LED閃爍或蜂鳴器發聲操作,可以使用等效語句LED=!LED及BEEP=!BEEP。

如果熟悉“異或”操作符,還可以用P2 ^=(1<<3)這樣的寫法。這個寫法可以省略位定義。

另外,在本書4×4鍵盤矩陣掃描程序中,假設P1端口高4位引腳連接矩陣行,低4位引腳連接矩陣列。為判斷16個按鍵中是否有鍵被按下,通常會先在矩陣行上發送4位掃描碼0000,即P1=0x0F,然后檢查矩陣列上是否出現0。這時,使用位操作語句:

由于“!=”的優先級高于“&”,因此要給該語句中的“與操作”表達式加括號。

在本書涉及的多個字符液晶顯示器案例中,當向連接在P0端口的液晶屏發送顯示數據時,要先判斷液晶屏是否忙。因此,又有類似語句:

主站蜘蛛池模板: 福贡县| 尚义县| 普宁市| 香格里拉县| 宁强县| 游戏| 肥城市| 奇台县| 长春市| 九台市| 荣昌县| 靖宇县| 平谷区| 扬中市| 仙桃市| 安多县| 乐平市| 兰考县| 信宜市| 邯郸市| 杭州市| 博乐市| 宜黄县| 威远县| 深水埗区| 桂阳县| 剑阁县| 巴里| 宝兴县| 呼玛县| 迁安市| 兰坪| 龙山县| 来宾市| 阳春市| 周口市| 延安市| 满洲里市| 通州市| 鄄城县| 海盐县|