【CC2530入門教程-02】CC2530的通用I/O端口輸入和輸出控制

第2課  CC2530的通用I/O端口輸入和輸出控制html

XMF393 / 廣東職業技術學院  歐浩源編程

【通用I/O端口視頻教程:https://v.qq.com/x/page/x0793aol7us.html函數

1、CC2530的引腳概述spa

        CC2530微控制器採用QFN40封裝,有40 個引腳。其中,有21個數字I/O端口,其中P0P18 位端口P2僅有5位可使用。這21個端口都可以經過編程進行配置。實際上,在P2端口的5個引腳中,有2個須要用做仿真,有2個須要用做晶振,你在CC2530的開發中真正可以使用的只有17個引腳設計

        在微控制器內部,有一些特殊功能的存儲單元,這些單元用來存放控制微控制器內部器件的命令、數據或運行過程當中的一些狀態信息,這些寄存器統稱爲「特殊功能寄存器(SFR)」。操做微控制器的本質,就是對這些特殊功能寄存器進行讀寫操做,而且某些特殊功能寄存器能夠位尋址3d

        每個特殊功能寄存器本質上就是一個內存單元,而標識每一個內存單元的是內存地址,不容易記憶。爲了便於使用,每一個特殊功能寄存器都會起一個名字,在程序設計時,只要引入頭文件「ioCC2530.h」,就能夠直接使用寄存器的名稱訪問內存地址了。調試

        CC2530的通用I/O端口相關的經常使用寄存器有下面4個:code

        <1> PxSEL:端口功能選擇,設置端口是通用I/O仍是外設功能視頻

        <2> PxDIR:做爲通用I/O時,用來設置數據的傳輸方向。htm

        <3> PxINP:做爲通用輸入端口時,選擇輸入模式是上拉下拉仍是三態

        <4> Px:數據端口,用來控制端口的輸出或獲取端口的輸入。

 

2、設置寄存器中某些位的方法

        <1> 對寄存器的某些位清0而不影響其餘位。

        例如:寄存器P1TM的當前值是0x6c,現須要將該寄存器的第1位、第3 位和第5位設置爲0,同時不能影響該寄存器其餘位的值,那麼,在C語言中應該怎麼編寫代碼呢?

        使用「&=」將寄存器指定位清0,同時不影響其餘位的值。

        正確寫法:P1TM &= ~0x2A;

        由於:邏輯「與」操做的特色是,該位有0結果就爲0,若爲1則保存原來值不變。

        首先將字節 0000 0000要操做的位設置爲1,即0010 1010,在將該數值取反,即1101 0101,也就是~0x2A。再將該值與寄存器P1TM「相與」,那麼有0的位,即一、三、5位將被清0,其他的位會保持原來的值不變。

        因此:P1TM的當前值爲0x6c,即0110 1100,

        0110 1100 && 1101 0101 = 0100 0100,即一、三、5位清0,其餘位不變。

        <注意>:該方法只能操做多位同時清0,或者某一位清0的狀況,若是要將寄存器的位既要清0又要置1,則不能採用這種寫法。(其中緣由本身思考一下)

        在很多嵌入式應用的源碼程序中,對於寄存器的第n位的清0操做也能夠寫成:寄存器 &= ~(0x01<<(n));其道理是同樣的。

        <2> 對寄存器的某些位置1而不影響其餘位。

        例如:寄存器P1TM的當前值是0x6c,現須要將該寄存器的第1位、第4位和第5位設置爲1,同時不能影響該寄存器其餘位的值,那麼,在C語言中應該怎麼編寫代碼呢?

        使用「|=」將寄存器指定位置1,同時不影響其餘位的值。

        正確寫法:P1TM |= 0x32;

        由於:邏輯「或」操做的特色是,該位有1結果就爲1,若爲0則保存原來值不變。

        首先將字節 0000 0000 要操做的位設置爲1,即0011 0010,也就是0x32。 再將該值與寄存器P1TM「相或」,那個有1的位,即一、四、5位將被設置爲1,其他的位會保持原來的值不變。

        因此:P1TM的當前值爲0x6c,即0110 1100,

        0110 1100 || 0011 0010 = 0111 1110,即一、四、5位置1,其餘位不變。

        一樣要注意:該方法只能操做多位同時置1,或者某一位置1的狀況。

        對於寄存器的第n位的清0操做也能夠寫成:寄存 |= (0x01<<(n));

 

3、本身設計的Zigbee實訓硬件平臺(歡迎選購哦

【1】綜合加強版功能概述

【2】引腳分配與結構框圖 

 

3、實訓案例:按鍵輸入控制燈光輸出狀態

【1】準備工做。

引入CC2530必要的頭文件「ioCC2530.h」,定義相關變量等。

【2】端口功能選擇。

        微控制器的大部分I/O端口都是功能複用的,在使用的時候須要經過功能選擇寄存器來配置端口的功能。

【3】端口傳輸方向設置。

【4】對於輸入的端口要設置其輸入方式。

        輸入方式用來從外界器件獲取輸入的電信號,當CC2530的引腳爲輸入端口時,該端口可以提供「上拉」、「下拉」和「三態」三種輸入模式,能夠經過編程進行設置。在本次實訓中,實際上不須要對P0_1和P1_2引腳進行輸入方式的設置,由於CC2530復位後,各個I/O端口默認使用的就是上拉模式。

 

【5】通用I/O端口寄存器配置的基本思路。

【6】設計端口初始化函數InitPort()。

        <1>設置P1SEL寄存器,將P1_二、P1_3和P1_4設置爲通用I/O端口。

        <2>設置P1DIR寄存器,將P1_3和P1_4設置爲輸出,將P1_2設置爲輸入。

        <3>設置P0SEL寄存器,將P0_1設置爲通用I/O端口。

        <4>設置P0DIR寄存器,將P0_1設置爲輸入。

        <5>設置PxINP寄存器,將P0_1和P1_2設置爲上拉模式,也能夠不設置。

【7】設計鍵盤掃描函數ScanKeys()。

        <1>沒有按鍵下時,端口的輸入爲高電平,當發現該端口有低電平產生時,則有可能會是按鍵按下,須要通過去抖動處理,若是該端口仍是低電平,則確認爲按鍵按下。

        <2>在進行按鍵處理時,先等待按鍵鬆開,而後再將相關的LED進行開關狀態的取反控制。

【8】主函數的實現

至此,大功搞成,鏈接仿真器,進行編譯調試。

【附件】:本實訓源代碼。

#include "ioCC2530.h"

#define LED5 P1_3
#define LED6 P1_4
#define SW1 P1_2
#define SW2 P0_1
/*===================延時函數=========================*/
void Delay(unsigned int t)
{
  while(t--);
}
/*================端口初始化函數======================*/
void InitPort()
{
  P1SEL &= ~0x18;         //將P1_3和P1_4設置爲通用I/O端口功能
  P1DIR |= 0x18;          //將P1_3和P1_4的端口傳輸方式設置爲輸出
  P1SEL &= ~0x04;         //將P1_2設置爲通用I/O端口功能
  P1DIR &= ~0x04;         //將P1_2的端口傳輸方式設置爲輸入
  P0SEL &= ~0x02;         //將P0_1設置爲通用I/O端口功能
  P0DIR &= ~0x02;         //將P0_1的端口傳輸方式設置爲輸入
  P0INP &= ~0x02;         //將P0_1的端口輸入方式設置爲:上拉/下拉
  P1INP &= ~0x04;         //將P1_2的端口輸入方式設置爲:上拉/下拉
  P2INP &= ~0x60;         //將P0端口和P1端口引腳設置爲:上拉
  LED5 = 0;               //上電的時候,LED5不亮
  LED6 = 0;               //上電的時候,LED6不亮
}
/*=================按鍵掃描函數=======================*/
void ScanKeys()
{
  if(SW1 == 0)
  {                       //發現SW1有低電平信號
    Delay(100);           //按鍵去抖動
    if(SW1 == 0)
    {                      //確實是有按鍵動做
      while(SW1 == 0);    //等待按鍵1鬆開
      //將LED5的燈光開關狀態取反
      LED5 = ~LED5;
  }
  if(SW2 == 0)
  {                       //發現SW2有低電平信號
    Delay(100);           //按鍵去抖動
    if(SW2 == 0)
    {                     //確實是有按鍵動做
      while(SW2 == 0);    //等待按鍵2鬆開
      LED6 = ~LED6;
    }
  }
}
/*=====================主函數=========================*/
void main()
{
  InitPort();
  while(1)
  {
    ScanKeys();
  }
}

 

相關文章
相關標籤/搜索