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

任務4 信號燈的設計與實現

本任務重點學習微處理器的通用輸入/輸出接口(GPIO),以及GPIO的位操作,掌握GPIO的基本原理和功能,以及使用C語言驅動CC2530的GPIO的方法,從而實現對信號燈的控制。

4.1 開發場景:如何控制信號燈

當常見的自動化設備具備多種功能時,往往會用不同的信號指示燈(信號燈)來表示系統的功能和工作狀態,圖4.1所示的安防設備控制器上具有電源、報警、設置、電話4個系統指示燈,通過這4個LED指示燈,用戶可以方便、直觀地設置與管理設備。

圖4.1 安防設備控制器上的系統指示燈

4.2 開發目標

(1)知識目標:了解GPIO基本概念、電路驅動和工作模式;熟悉CC2530微處理器GPIO基本構成;掌握利用位操作實現CC2530微處理器GPIO基本操作。

(2)技能目標:會設置CC2530微處理器GPIO的工作模式;掌握基于CC2530微處理器GPIO基本驅動方法;實現基于CC2530微處理器的信號燈驅動開發。

(3)任務目標:使用CC2530微處理器上的發光二極管(LED)模擬信號指示燈,先檢測連接在CC2530微處理器GPIO引腳上按鍵電平狀態并識別其開關狀態,然后根據檢測結果讀取LED指示燈的狀態并進行實時控制,LED狀態(亮或者滅)可以表示設備的功能和工作狀態。

4.3 原理學習:微處理器的GPIO功能與應用

4.3.1 微處理器GPIO

1.微處理器GPIO基本概念

GPIO(General Purpose Input Output, GPIO)是微處理器的通用輸入/輸出接口。微處理器可以通過向GPIO控制寄存器寫入數據來控制GPIO的模式,實現對某些設備的控制或信號采集功能;也可以對GPIO進行組合配置,實現較為復雜的總線控制接口和串行通信接口。下面將通過GPIO的電氣屬性與基本工作模式來對GPIO進行講解。

2.微處理器GPIO電路驅動

GPIO電路可分為很多種,GPIO電路不同,效果也不同。根據GPIO電路的區別,可將電路分為弱驅動GPIO、強驅動GPIO、高壓GPIO、低壓GPIO,同時電壓與驅動能力可以相互組合。

(1)弱驅動GPIO。弱驅動電路指GPIO引腳輸出的電流較小,無法對相關的控制設備提供足夠的驅動電流,因此電路在設計時需要額外添加上拉電阻以提高GPIO的驅動能力。例如,CC2530微處理器中除了P1_0、P1_1為強驅動,其他引腳驅動能力均無法滿足LED驅動的需要,因此需要通過添加額外的電路以達到控制外接設備的目的。

(2)強驅動GPIO。顧名思義,強驅動GPIO是指驅動能力較強的GPIO。通常情況下,當輸入與芯片電源相同的電壓時,強驅動GPIO可以驅動功率更大的外接設備。例如,STM32系列微處理器基本上都屬于強驅動GPIO。

(3)高壓GPIO與低壓GPIO。目前微處理器GPIO輸出電壓有兩種,一種為早期傳統8051微處理器的5 V的GPIO,另一種為通用型的3.3 V的GPIO。5 V的GPIO接口是由于微處理器輸入電壓為5 V,因此微處理器引腳輸出的電平同樣為5 V;而低壓GPIO的芯片的輸入電源為3.3 V,因此微處理器引腳輸出的電平為3.3 V。高壓GPIO與低壓GPIO相比,低壓GPIO的工藝更加先進,引腳的開關效率也更高,可以滿足高速總線的引腳電平跳變需求,因此高性能微處理器的GPIO引腳通常為低壓GPIO。

3.微處理器GPIO工作模式

GPIO在工作時有三種工作模式,即輸入、輸出和高阻態,這三種狀態的使用和功能都有所不同,在設置時需要根據實際的外接設備來對引腳進行配置。下面對GPIO的這三種狀態進行簡單的敘述。

(1)輸入模式。輸入模式是指GPIO被配置為接收外接電平信息的模式,通常讀取的信息為電平信息,即高電平為1,低電平為0。這時讀取的高低電平是根據微處理器的電源高低來劃分的,相對于5 V電源的微處理器,判斷為高電平時的檢測電壓為3.3~5 V;小于2 V時則微處理器判斷為低電平。相對于3.3 V電源的微處理器,判斷為高電平時的檢測電壓為2~3.3 V;小于0.8 V時則微處理器判斷為低電平。

(2)輸出模式。輸出模式是指GPIO被配置為主動向外部輸出電壓的模式,通過向外輸出電壓可以實現對一般開關類設備的實時主動控制。當程序中向相應引腳寫1時,GPIO會向外輸出高電平,通常這個電平為微處理器的電源電壓;當程序中向相應引腳寫0時,GPIO會向外輸出低電平,通常這個低電平為電源地的電壓。

(3)高阻態模式。高阻態模式是指GPIO引腳內部電阻的阻值無限大,大到幾乎占有外接輸出的全部電壓。這種模式通常在微處理器采集外部模擬電壓時使用,通過將相應GPIO引腳配置為高阻態模式和輸入模式,通過配合微處理器的ADC可以實現準確的模擬量電平讀取。

4.3.2 CC2530與GPIO

1.CC2530的GPIO

微處理器的GPIO引腳可以組成3個8位端口,即端口0、端口1和端口2,分別表示為P0、P1和P2,其中P0和P1是8位端口,而P2只有5位可用,所有端口均可以通過SFR寄存器來進行P0、P1、P2位尋址和字節尋址。

寄存器PxSEL中的x表示端口標號0~2,用來設置端口的每個引腳為GPIO或者外部設備I/O信號,在默認情況下,當復位之后,所有數字輸入/輸出引腳都設置為通用輸入引腳。

寄存器PxDIR用來改變一個端口引腳的方向,可設置為輸入或輸出,設置PxDIR的指定位為1時,對應的引腳口則為輸出;設置為0時,對應的引腳口則為輸入。

當讀取寄存器P0、P1和P2的值時,不管引腳如何配置,輸入引腳的邏輯值都被返回,但在執行讀-修改-寫期間不適用。當讀取的是寄存器P0、P1和P2中一個獨立位時,寄存器的值(而不是引腳上的值)可以被讀取、修改并寫回端口寄存器。CC2530引腳分布如圖4.2所示。

圖4.2 CC2530引腳分布

2.CC2530的GPIO寄存器

CC2530微處理器內核為增強型8051內核,同時芯片在內部總線上有較大的優化和改進,因此CC2530的GPIO配置寄存器眾多,如表4.1所示。

表4.1 GPIO配置寄存器

GPIO的控制寄存器眾多,但用于輸入/輸出配置的寄存器只有特定的幾個,所以驅動GPIO時只需要配置P1DIR(端口1方向寄存器)和P1SEL(端口1功能選擇寄存器)。P1DIR寄存器功能分配如表4.2所示,P1ESL寄存器功能分配如表4.3所示。

表4.2 P1DIR寄存器功能分配

表4.3 P1SEL寄存器功能分配

如表4.2所示,P1DIR寄存器用于配置GPIO的方向,即輸入/輸出方向,當某一位置1時表示對應的引腳為Output,即輸出模式,反之則為Input,即輸入模式。P1SEL用于設置GPIO引腳的功能,表示GPIO是GPIO模式還是外設模式,當某一位置1時表示對應的引腳配置為外設模式,反之則為GPIO模式,因此對GPIO的配置其實就是對控制寄存器的配置。

4.3.3 GPIO的位操作

GPIO一般是通過位操作完成寄存器設置的,常用的位操作運算符有按位與“&”、按位或“|”、按位取反“~”、按位異或“^”,以及左移運算符“<<”和右移運算符“>>”。

(1)按位或運算符“|”。參加運算的兩個運算量的位至少有一個是1時,結果為1,否則為0,按位或運算常用來對一個數據的某些特定的位置1,例如,“P1DIR |=0X02”,0X02為十六進制數,轉換成二進制數為00000010,若P1DIR原來的值為00110000,或運算后P1DIR的值為00110010。根據上面給出的取值表可知,按位或運算后P1_1的方向改為輸出,其他I/O口方向保持不變。

(2)按位與運算符“&”。參加運算的兩個運算量相應的位都是1時,則結果為1,否則為0,按位與運算常用于清除一個數中的某些特定位。

(3)按位異或運算符“^”。參加運算的兩個運算量相應的位相同,即均為0或者均為1時,結果值中該位為0,否則為1,按位異或運算常用于將一個數中某些特定位翻轉。

(4)按位取反“~”。用于對一個二進制數按位取反,即0變1,1變0。

(5)左移運算符“<<”。左移運算用于將一個數的各個二進制全部左移若干位,移到左端的高位被舍棄,右邊的低位補0。

(6)右移運算符“>>”。用于對一個二進制數位全部右移若干位,移到右端的低位被舍棄。

例如,“P1DIR &=~0x02”, &表示按位與運算,~運算符表示取反,0x02為00000010,~0x02為11111101。若P1DIR原來的值為00110010,進行與運算后P1DIR的值為00110000。

4.4 任務實踐:信號燈的軟/硬件設計

4.4.1 開發設計

1.硬件設計

本任務的硬件架構設計如圖4.3所示。

圖4.3 硬件架構設計圖

要通過CC2530微處理器實現對按鍵動作的檢測和信號燈的控制,第一要了解信號燈的控制原理,第二要掌握按鍵動作的捕獲原理,將捕獲按鍵動作和信號燈控制結合起來就可以實現兩者的聯動控制,從而達到項目設計效果。

1)連接到GPIO的LED控制

將信號燈的控制轉化成對GPIO的主動控制:高電平輸出和低電平輸出,信號燈LED接口電路如圖4.4所示,圖中D1與D2一端接電阻,另一端接在CC2530微處理器上,電阻的另一端連接在3.3 V的電源上,D1與D2采用的是正向連接導通的方式,當P1_0和P1_1為高電平(3.3 V)時,D1與D2兩電壓相同,無法形成壓降,因此D1與D2不導通,D1與D2熄滅;反之當P1_0和P1_1為低電平時,D1與D2兩端形成壓降,則D1與D2點亮。

圖4.4 LED接口電路圖

按鍵的狀態檢測方式主要是使用CC2530微處理器GPIO的引腳電平讀取功能,相關引腳為高電平時引腳讀取的值為1,反之則為0。而按鍵是否按下,以及按下前后的電平狀態則需要按照實際的按鍵原理圖來確認,按鍵接口電路如圖4.5所示。圖中,按鍵K1的引腳2接GND,引腳1接電阻和CC2530微處理器的引腳P1_2,電阻的另一端連接3.3 V電源,當按鍵沒有按下時K1的引腳1和引腳2斷開,由于CC2530微處理器引腳在輸入模式時為高阻態,所以引腳P1_2采集的電平為高電平;當K1按鍵按下后K1的引腳1和引腳2導通,此時引腳P1_2導通接地,所以此時引腳檢測電平為低電平。

圖4.5 按鍵接口電路圖

2)按鍵控制

通常按鍵所用的開關都是機械彈性開關,當機械觸點斷開、閉合時,由于彈性作用,一個按鍵開關在閉合時不會馬上就穩定地接通,在斷開時也不會一下子就徹底斷開,而是在閉合和斷開的瞬間伴隨著一連串的抖動,按鍵抖動電信號波形如圖4.6所示。

圖4.6 按鍵抖動電信號波形

按鍵穩定閉合時間長短是由操作人員決定的,通常都會在100 ms以上,刻意快速按的話能達到40~50 ms,很難再低了。抖動時間是由按鍵的機械特性決定的,一般都會在10 ms以內,為了確保程序對按鍵的一次閉合或者一次斷開只響應一次,必須進行按鍵的消抖處理。當檢測到按鍵狀態變化時,不是立即去響應動作,而是先等待閉合或斷開穩定后再進行處理。按鍵消抖可分為硬件消抖和軟件消抖。

本任務使用軟件消抖,當檢測到按鍵狀態變化后,先等待一段時間,讓抖動消失后再進行按鍵狀態檢測,如果與剛才檢測的狀態相同,就可以確認按鍵已經穩定了。

2.軟件設計

掌握硬件設計之后,再來分析軟件設計。首先需要將CC2530微處理器的GPIO配置為輸入模式和輸出模式,配置輸入模式和輸出模式時涉及兩個寄存器,分別為PxSEL(模式選擇寄存器)和PxDIR(輸入/輸出方向控制寄存器)。其次,在按鍵輸入檢測時需要使用延時消抖和松手檢測方法,通過延時消抖可以屏蔽開關動作時的電平抖動,防止誤操作;使用松手檢測作為對LED控制的觸發條件。程序設計流程如下。

(1)配置LED和按鍵對應的GPIO,初始化LED和按鍵外設。

(2)初始化完成后程序進入主循環,主循環中不斷檢測按鍵的狀態。

(3)當檢測到按鍵按下時,延時10 ms,待電平穩定后如果按鍵依舊處于按下狀態則確定按鍵被按下,等待按鍵抬起。

(4)檢測到按鍵抬起后執行LED的反轉控制操作,完成對LED的控制。

程序設計流程如圖4.7所示。

圖4.7 軟件設計流程圖

注意:本任務中所講到的按鍵和信號燈在接下來的任務開發中都會用到,相關內容在此處進行詳細解釋后,其他任務將不再對按鍵和信號燈等相關內容進行介紹。

4.4.2 功能實現

通過原理學習可知,要實現D1、D2的亮滅,只需配置P1_0、P1_1引腳即可,然后輸出高/低電平,即可實現D1、D1的閃爍控制,這兩個引腳只需配置為輸入模式讀取電平即可。下面是源代碼實現的解析過程。

1.主函數模塊

首先實現LED端口和按鍵端口的初始化,然后進入循環以檢測按鍵狀態,當按鍵按下時,進行LED狀態控制。

    /****************************************************************************************
    * 名稱:main()
    * 功能:LED驅動邏輯代碼
    ****************************************************************************************/
    void main(void)
    {
        led_io_init();                               //LED端口初始化
        key_io_init();                               //按鍵端口初始化
        LED2=ON;                               //打開LED0
        while(1){
          if(KEY1==ON){                        //按鍵按下,改變兩個LED的狀態
              delay_ms(10);                        //按鍵防抖10 ms
              if(KEY1==ON){                     //按鍵按下,改變兩個LED的狀態
                  while(KEY1==ON);               //松手檢測
                  LED2=~LED2;                  //LED翻轉閃爍
                  LED1=~LED1;                  //LED翻轉閃爍
              }
          }
        }
    }

2.LED初始化模塊

LED初始化需要先配置P1SEL寄存器為GPIO模式,然后配置P1DIR寄存器為輸出模式,并先關閉兩個LED,源代碼如下。

    /****************************************************************************************
    * 名稱:led_init()
    * 功能:LED控制引腳初始化
    ****************************************************************************************/
    void led_io_init(void)
    {
        P1SEL&=~0x03;                       //配置控制引腳(P1_0和P1_1)為GPIO模式
        P1DIR|=0x03;                         //配置控制引腳(P1_0和P1_1)為輸出模式
        LED1=OFF;                           //初始狀態為關閉
        LED2=OFF;                           //初始狀態為關閉
    }

3.按鍵初始化模塊

按鍵初始化時先配置P1SEL寄存器為GPIO模式,然后配置P1DIR寄存器為輸入模式,源代碼如下。

    /****************************************************************************************
    * 名稱:key_init()
    * 功能:按鍵初始化
    ****************************************************************************************/
    void key_init(void)
    {
        P1SEL&=~0x0C;                   //配置按鍵檢測引腳(P1_2和P1_3)為GPIO模式
        P1DIR&=~0x0C;                   //配置按鍵檢測引腳(P1_2和P1_3)為通輸出模式
    }

4.延時模塊

    /****************************************************************************************
    * 名稱:delay_ms()
    * 功能:硬件延時,大于250 ms
    * 參數:times—延時時間
    ****************************************************************************************/
    void delay_ms(u16 times)
    {
        u16 i, j;                                   //定義臨時參數
        i=times/250;                              //獲取要延時時長的250 ms倍數部分
        j=times % 250;                             //獲取要延時時長的250 ms余數部分
        while(i--)hal_wait(250);                       //延時250 ms
        hal_wait(j);                                //延時剩余部分
    }
    /****************************************************************************************
    * 名稱:hal_wait(u8 wait)
    * 功能:硬件延時函數
    * 參數:wait—延時時間(wait<255)
    ****************************************************************************************/
    void hal_wait(u8 wait)
    {
        unsigned long largeWait;                       //定義硬件計數的臨時參數
        if(wait==0)return;                          //如果延時參數為0,則跳出
        largeWait=((u16)(wait<<7));                  //將數據擴大64倍
        largeWait+=114*wait;                        //將延時數據擴大114倍并求和
        largeWait=(largeWait>>CLKSPD);              //根據系統時鐘頻率對延時進行縮放
        while(largeWait--);                          //等待延時自減完成
    }

4.5 任務驗證

使用IAR開發環境打開任務設計工程,程序通過編譯后,由SmartRF下載到CC2530微處理器中,執行程序后,開發平臺上D2點亮,D1熄滅。按下K1按鍵后D2熄滅,D1點亮。再次按下K1按鍵后D2點亮,D1熄滅,如此循環往復。

4.6 任務小結

GPIO是微處理器最常用的基本接口,本任務先學習了GPIO的概念、工作模式,然后進一步學習了GPIO的基本功能和控制,并介紹了GPIO的位操作,最后完成該任務的硬件設計和軟件設計,實現了通過CC2530微處理器的GPIO接口控制相關儀表的信息和狀態。

4.7 思考與拓展

(1)GPIO的三種狀態有什么功能?可以應用在哪些方面?

(2)常見的GPIO的位操作有哪些?

(3)CC2530的GPIO方向寄存器和功能選擇寄存器有什么功能?如何配置?

(4)如何驅動CC2530微處理器的GPIO?

(5)手機接收到短消息時,信號燈就會像人的呼吸一樣閃爍,信號燈逐漸變亮,達到最亮后又逐漸熄滅,通過這樣一種有反差的閃爍效果,既能體現科技時尚感,又能達到很好的來電消息提醒效果。以手機信號燈為項目目標,如何基于CC2530實現LED閃爍的“呼吸”效果?

主站蜘蛛池模板: 巴东县| 昆山市| 洮南市| 育儿| 阳西县| 秦安县| 井陉县| 望谟县| 彰化市| 洪泽县| 崇阳县| 广南县| 财经| 洛宁县| 沂源县| 涪陵区| 辛集市| 镇原县| 安宁市| 汉中市| 甘洛县| 贵港市| 乐安县| 唐海县| 宜兰市| 博罗县| 西充县| 兰西县| 同德县| 东丰县| 大洼县| 楚雄市| 高碑店市| 通河县| 射洪县| 清苑县| 平昌县| 凤阳县| 东平县| 义乌市| 普定县|