• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > C51編程中的自定義“位”及其保存方案

    C51編程中的自定義“位”及其保存方案

    作者: 時(shí)間:2013-02-17 來源:網(wǎng)絡(luò) 收藏

      引言

      在現(xiàn)有的教課書及相關(guān)文章中,都難得提到在單片機(jī)C語言編程中對(duì)于“位”的狀態(tài)進(jìn)行保存的理念。

      當(dāng)單片機(jī)C語言編程中提及“位”的概念時(shí),人們自然會(huì)想到狀態(tài)字PSW中PSW.5的F0與PSW.1的F1兩個(gè)用戶通用。這兩個(gè)均可參與布爾運(yùn)算、“位”控操作,也可隨狀態(tài)字PSW一起保存。但是,往往會(huì)忽視這一點(diǎn):在一些特定的情況下,如在C語言編程的中斷服務(wù)程序中,對(duì)狀態(tài)字PSW中PSW.5的F0與PSW.1的F1這兩個(gè)用戶的操作可能是無效的。如:

      void EX1_ISR() interrupt 2 {//外部中斷1

      static unsigned int tempaddr;//定義接收地址緩存

      static unsigned int tempkey;//定義接收數(shù)據(jù)緩存

      unsigned int timecnt;

      timecnt=TH1*256+TL1;

      TH1=0;

      TL1=0;

      TR1=1;//定時(shí)器1啟動(dòng)

      F0=~F0;//取反F0

      if(F0) {

      tempaddr=tempaddr1;

      }

      else {

      tempkey=tempkey1;

      }

      }

      以上是一段單片機(jī)外部中斷1的中斷服務(wù)程序,乍看似乎沒什么問題,仿真調(diào)試時(shí)也能通過“編輯”。但實(shí)際上這是一段錯(cuò)誤的程序——其中對(duì)“F0”用戶標(biāo)志位的“取反”操作是達(dá)不到其預(yù)期效果的。因?yàn)閷?duì)“F0”用戶標(biāo)志位的“取反”操作是在中斷服務(wù)程序中進(jìn)行的。在進(jìn)入中斷時(shí),C語言自動(dòng)會(huì)保護(hù)“中斷現(xiàn)場”——將程序指針PC、累加器ACC、狀態(tài)字PSW等壓入堆棧保護(hù)起來……直到中斷返回時(shí)彈出堆棧并覆蓋了中斷服務(wù)時(shí)的變值,恢復(fù)到壓入堆棧之前的原樣。因此,狀態(tài)字PSW中的F0也不例外,如果壓入堆棧之前F0是處于邏輯“0”狀態(tài),中斷返回后還是復(fù)原成邏輯“0”狀態(tài)——不管中斷服務(wù)程序中怎么取反改變——也就是說,在中斷服務(wù)程序中試圖改變F0之值的操作是有失偏頗的。對(duì)于上文例舉的那段中斷服務(wù)程序來說,若F0的初始狀態(tài)為邏輯“0”,即進(jìn)入中斷服務(wù)之前和中斷返回之后總是邏輯“0”,那么進(jìn)入執(zhí)行“F0=~F0”指令后F0總是邏輯“1”,因而接下運(yùn)行的是“if(F0)”下花括號(hào)中“tempaddr=tempaddr1;”指令,而“else”下花括號(hào)中“tempkey=tempkey1”指令永遠(yuǎn)也運(yùn)行不到。所以,若要中斷服務(wù)程序達(dá)到預(yù)期的效果——“if(F0)”下花括號(hào)中的指令與“else”下花括號(hào)中的指令輪番運(yùn)行,必須設(shè)立一個(gè)不受中斷現(xiàn)場保護(hù)等影響的標(biāo)志位。

      1標(biāo)志“位”的保存

      在C語言編程中,自定義標(biāo)志位的運(yùn)用概率很大,有的一個(gè)程序中就會(huì)有好多的自定義標(biāo)志位,且其中幾個(gè)可能是必須要保存的。譬如有些控制器件中對(duì)一些控制狀態(tài)進(jìn)行保持,即使是停電之后再來電了這種控制狀態(tài)依然能保持不變——這就牽涉到保存問題。

      例舉2:我們?cè)氵^一個(gè)鐳射投影屏幕升降的無線遙控裝置。這個(gè)以單片機(jī)為核心的控制裝置與屏幕升降的卷動(dòng)電機(jī)等都安裝固定在一個(gè)直徑不足50 mm的狹長鐵桶里面,因此裝入或拆卸都非常麻煩。為了一次性成功——避免再次拆卸裝入的麻煩,在用C語言編程時(shí)我特意多用了一個(gè)自定義的標(biāo)志位——翻轉(zhuǎn)標(biāo)志位“switch_sign”。因?yàn)闊o線遙控手柄上的向上“▲”、暫停“■”、向下“▼”的鍵標(biāo)志都已是做定的,因此,如果由于接線等失誤導(dǎo)致按向下“▼”鍵時(shí)投影屏幕向上卷、按向上“▲”鍵時(shí)投影屏幕卻向下伸……有了“switch_sign”自定義的標(biāo)志位就不用怕這些了。相關(guān)的C語言程序段如下:

      #defineuint unsigned int

      #defineuchar unsigned char

      uint Decode_addr,Decode_key,addr;

      sbit JD1_out=P0^4;//定義繼電器1控制輸出端

      sbit JD2_out=P0^5;//定義繼電器2控制輸出端

      sbit BEEP=P0^3;//定義蜂鳴聲響輸出

      bit bdata switch_sign;//自定義的翻轉(zhuǎn)標(biāo)志位(應(yīng)作全局變量定義)

      voidTelecontrol_Data() {

      ……

      if(Decode_addr==0x5535) {//地址碼核對(duì)

      if(Decode_key==0x00C0) {//“▲”鍵碼核對(duì)

      BEEP=1;//蜂鳴聲響輸出

      if(switch_sign) {//翻轉(zhuǎn)標(biāo)志位

      JD1_out=0;//繼電器1控制輸出端

      JD2_out=1; //繼電器2控制輸出端

      }

      else {

      JD1_out=1;//繼電器1控制輸出端

      JD2_out=0;//繼電器2控制輸出端

      }

      }

      if(Decode_key==0x0030) {//“■”鍵碼核對(duì)

      BEEP=1;//蜂鳴聲響輸出

      JD1_out=0;//繼電器1控制輸出端

      JD2_out=0;//繼電器2控制輸出端

      }


    上一頁 1 2 3 下一頁

    關(guān)鍵詞: C51編程 自定義 標(biāo)志位

    評(píng)論


    相關(guān)推薦

    技術(shù)專區(qū)

    關(guān)閉
    主站蜘蛛池模板: 青川县| 客服| 元朗区| 黎城县| 区。| 弋阳县| 雅江县| 射洪县| 营山县| 海宁市| 金寨县| 陈巴尔虎旗| 阜城县| 册亨县| 睢宁县| 三江| 合山市| 中西区| 绥宁县| 黎平县| 盐山县| 永嘉县| 白山市| 香河县| 乳源| 玛纳斯县| 邯郸县| 龙南县| 泽普县| 鹤壁市| 朝阳县| 河源市| 会宁县| 汾阳市| 石城县| 天台县| 鄄城县| 汾阳市| 天峻县| 竹北市| 平武县|