一、引腳概述
CC2530有40 個引腳。其中,有21個數字I/O端口,其中P0和P1是8 位端口,P2僅有5位可以使用。P2端口的5個引腳中,有2個需要用作仿真,有2個需要用作晶振。所以可供我們使用的就只有17個引腳了。

操作微控制器的本質,就是對這些特殊功能寄存器(SFR)進行讀寫操作,並且某些特殊功能寄存器可以位尋址。
每一個特殊功能寄存器本質上就是一個內存單元,為了便於使用,每個特殊功能寄存器都會起一個名字,在程序設計時,只要引入頭文件“ioCC2530.h”,就可以直接使用寄存器的名稱訪問內存地址了。
CC2530的通用I/O端口相關的常用寄存器有下面4個:
<1> PxSEL:端口功能選擇,設置端口是通用I/O還是外設功能。
<2> PxDIR:作為通用I/O時,用來設置數據的傳輸方向。
<3> PxINP:作為通用輸入端口時,選擇輸入模式是上拉、下拉還是三態。
<4> Px:數據端口,用來控制端口的輸出或獲取端口的輸入。
具體的寄存器功能和應用下面會說到。
二、設置寄存器的方法
<1> 對寄存器的某些位清0而不影響其他位。
使用“&=”將寄存器指定位清0,同時不影響其他位的值。
因為:邏輯“與”操作的特點是,該位有0結果就為0,若為1則保存原來值不變。
Tip:該方法只能操作多位同時清0,或者某一位清0的情況,如果要將寄存器的位既要清0又要置1,則不能采用這種寫法。
對於寄存器的第n位的清0操作也可以寫成:寄存器 &= ~(0x01<<(n))
<2> 對寄存器的某些位置1而不影響其他位。
使用“|=”將寄存器指定位置1,同時不影響其他位的值。
因為:邏輯“或”操作的特點是,該位有1結果就為1,若為0則保存原來值不變。
對於寄存器的第n位的清0操作也可以寫成:寄存器 |= (0x01<<(n));
題目:實現2個按鍵分別控制2個LED燈開關的功能,即SW1按下后松開,LED5亮,SW1再次按下后松開, LED5滅。SW2以同樣的方式控制LED6。本題中的引腳圖

涉及到的寄存器
端口功能選擇寄存器。

端口傳輸方向設置寄存器。

輸入端口需要設置其輸入方式的寄存器
端口能夠提供“上拉”、“下拉”和“三態”三種輸入模式


例子:將P1_2端口為按鍵輸入,設置為輸入上拉模式。
1 P1INP &=~0x04 //0000 0100->1111 1011 首先需要將P1_2設置為上/下拉模式 2 P2INP &=~0x40 //0100 0000 ->1011 1111 在將P1_2確定為上拉模式
通用I/O端口寄存器配置的基本思路。

設計思路:
1.設計一個端口初始化函數,對端口的功能進行配置,LED相關的端口設置為輸出,按鍵相關的端口設置為輸入,並且配置成上拉模式。
設計端口初始化函數InitPort()。
<1>設置P1SEL寄存器,將P1_2、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設置為上拉模式,也可以不設置。
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不亮 }
2.主函數中掃描按鍵端口的變化,默認是高電平。當按鍵按下的時候,為低電平。當出現低電平的時候,需要進行去抖的處理。
<1>沒有按鍵下時,端口的輸入為高電平,當發現該端口有低電平產生時,則有可能會是按鍵按下,需要經過去抖動處理,如果該端口還是低電平,則確認為按鍵按下。
<2>在進行按鍵處理時,先等待按鍵松開,然后再將相關的LED進行開關狀態的取反控制。
void main() { InitPort(); while(1) { ScanKeys(); } }
最終代碼展示
1 #include "ioCC2530.h" 2 3 #define LED5 P1_3 4 #define LED6 P1_4 5 #define SW1 P1_2 6 #define SW2 P0_1 7 /*===================延時函數=========================*/ 8 void Delay(unsigned int t) 9 { 10 while(t--); 11 } 12 /*================端口初始化函數======================*/ 13 void InitPort() //輸入輸出需要單獨設置,不可能一下設置完全 14 { 15 P1SEL &= ~0x18; //將P1_3和P1_4設置為通用I/O端口功能 0001 1000->1110 0111 將P1_3和P1_4設置普通IO口 16 P1DIR |= 0x18; //將P1_3和P1_4的端口傳輸方式設置為輸出 0001 1000 將P1_3和P1_4設置為輸出模式 17 P1SEL &= ~0x04; //將P1_2設置為通用I/O端口功能 0000 0100->1111 1011 將P1_2設置為普通IO口 18 P1DIR &= ~0x04; //將P1_2的端口傳輸方式設置為輸入 1111 1011 將P1_2的設置為輸入模式。還會有P1INP與P2INP寄存器設置 19 P0SEL &= ~0x02; //將P0_1設置為通用I/O端口功能 0000 0010 ->1111 1101 將P0_1設置為普通IO口 20 P0DIR &= ~0x02; //將P0_1的端口傳輸方式設置為輸入 1111 1101 將P0_1設置為輸入 21 P0INP &= ~0x02; //將P0_1的端口輸入方式設置為:上拉/下拉 0000 0010->1111 1101 先設置上拉或者下拉模式 P0_1設置為、 22 P1INP &= ~0x04; //將P1_2的端口輸入方式設置為:上拉/下拉 1111 1011 P1_2設置上拉或者下拉模式 23 P2INP &= ~0x60; //將P0端口和P1端口引腳設置為:上拉 0110 0000 -> 1001 1111 可看寄存器 5與6對應的P0和P1 0為上拉模式 24 LED5 = 0; //上電的時候,LED5不亮 25 LED6 = 0; //上電的時候,LED6不亮 26 } 27 /*=================按鍵掃描函數=======================*/ 28 void ScanKeys() 29 { 30 if(SW1 == 0) 31 { //發現SW1有低電平信號 32 Delay(100); //按鍵去抖動 延時去抖 33 if(SW1 == 0) 34 { //確實是有按鍵動作 35 while(SW1 == 0); //等待按鍵1松開 36 //將LED5的燈光開關狀態取反 37 LED5 = ~LED5; 38 } 39 if(SW2 == 0) 40 { //發現SW2有低電平信號 41 Delay(100); //按鍵去抖動 42 if(SW2 == 0) 43 { //確實是有按鍵動作 44 while(SW2 == 0); //等待按鍵2松開 45 LED6 = ~LED6; 46 } 47 } 48 } 49 /*=====================主函數=========================*/ 50 void main() 51 { 52 InitPort(); 53 while(1) 54 { 55 ScanKeys(); //按鍵掃描函數里面包含了點燈 56 } 57 }
