1. 程式人生 > >嵌入式系統技術——實現對GPIO晶片的相關控制

嵌入式系統技術——實現對GPIO晶片的相關控制

嵌入式系統技術
實現對GPIO晶片的相關控制
一、實驗目的
1、LED燈的輪詢除錯
2、模擬串列埠收發資料的過程
3、模擬生活中的按鍵控制操作
二、實驗環境
1、硬體:通用節點或任意感測器節點一個、USB模擬器、USB電纜、PC機;
2、軟體:IAR Embedded Workbench for MCS-51、串列埠除錯工具;
三、實驗內容
1、熟悉Zigbee硬體模組相關介面;
2、使用IAR 開發環境設計程式,利用CC2530 的IO口進行LED發光二極體的亮滅操作;
3、使用IAR 開發環境設計程式,利用CC2530 的串列埠0 進行資料收發通訊;
4、使用IAR 開發環境設計程式,利用CC2530 的GPIO讀取按鍵值並相應對進行LED發光二極體的亮滅操作;
四、實驗原理
1)硬體介面原理
①LED發光二極體實驗
在CC2530中,我們總共有3個可用的GPIO介面:P0、P1和P2。其中P0和P1的全部8位都有對應的引腳,而P2只有0-4幾個引腳可用。這裡我們主要對P0和P1共16個引腳進行操作,每個引腳都連線到一個發光二極體的驅動端,這樣通過控制P0和P1的每一位,我們可以控制所有的16個發光二極體的亮滅。
首先我們需要了解CC2530 的IO口相關暫存器:
在這裡插入圖片描述


圖5-1-1 P0和P1 暫存器
在這裡插入圖片描述
圖5-1-2 P0SEL和P1SEL暫存器
在這裡插入圖片描述
在這裡插入圖片描述
圖5-1-3 P0DIR和P1DIR暫存器
以上圖表列出了我們需要用到的和P0、P1相關的暫存器,其中P0、P1暫存器為IO資料暫存器,P0SEL、P1SEL為外設功能選擇暫存器,P0DIR、P1DIR為IO 輸入輸出選擇暫存器,例程中我們需要對這幾個暫存器進行IO配置相關設定和操作。此處如想深入瞭解請自行參考CC2530 的晶片手冊。
在這裡插入圖片描述
圖5-1-4 LED燈部分原理圖
在這個例程中,我們需要點亮通用節點上的LED燈,上圖給出了P0口控制D1~D8燈的原理圖,P1口控制另8個燈原理類似。
在這裡插入圖片描述
圖5-1-5 SN74LVC245原理框圖
我們檢視晶片SN74LVC245的器件手冊,可以看到其工作原理框圖如上所示。由圖中描述可知,OEn訊號控制所有引腳的輸出使能,DIR訊號控制訊號驅動方向。我們的原理圖中OEn接地,所以相應引腳是輸出使能的。DIR(圖中的T/Rn)是接高電平的,所以根據其原理框圖,訊號方向是由A到B。也就是A端的訊號(P0.0-P0.7)經過SN74LVC245晶片後控制著B端輸出訊號(用來驅動D1~D8)。
R1和R2是330歐姆的排阻,每個LED燈串接一個,用來限制通過LED燈的電流,使LED燈工作在正常大小電流下,防止燒燬。
②串列埠收發資料實驗
在CC2530中,我們總共有2個可用的序列介面,這些序列介面可被配置為標準串列埠或者SPI介面。這個例程中我們只使用USART0,並且工作在UART標準串列埠模式下。由於每種設定都有2套可用的IO對映,這裡根據我們的硬體設定,我們應該使用其預設設定,UART0的TX和RX對應於P0_3和P0_2。
在這裡插入圖片描述

圖5-2-1 部分外設複用IO對應圖
首先我們需要了解CC2530 的IO口相關暫存器:
在這裡插入圖片描述
圖5-2-2 P0 暫存器
在這裡插入圖片描述
圖5-2-3 P0SEL 暫存器
在這裡插入圖片描述
圖5-2-4 P0DIR 暫存器
以上圖表列出了關於CC2530 處理器的P0 IO口相關的暫存器,其中P0 暫存器為IO資料暫存器,P0SEL為外設功能選擇暫存器,P0DIR 為IO 輸入輸出選擇暫存器,例程中我們需要對這3個暫存器進行IO配置相關設定,其他相關暫存器使用預設配置。如想深入瞭解請自行參考CC2530 的晶片手冊。
其次,我們要對晶片的時鐘操作有所瞭解,因為程式的啟動部分,需要先對晶片時鐘進行配置。
在這裡插入圖片描述
圖5-2-5 CLKCONCMD 暫存器
在這裡插入圖片描述

圖5-2-6 CLKCONSTA 暫存器
在這裡插入圖片描述
圖5-2-7 SLEEP 控制暫存器
本例程中,程式通過配置以上暫存器將系統主時鐘設定為片外32M晶振。
然後是序列介面外設相關暫存器,通過設定這些暫存器,我們將序列介面設定為預想的模式。
在這裡插入圖片描述
圖5-2-8 PERCFG 暫存器
在這裡插入圖片描述
圖5-2-9 U0CSR 暫存器
在這裡插入圖片描述
圖5-2-10 U0GCR 暫存器
在這裡插入圖片描述
圖5-2-11 U0BUF 暫存器
在這裡插入圖片描述
圖5-2-12 U0BAUD 暫存器
以上圖表列舉了和CC2530串列埠操作定相關的暫存器,其中包括CLKCONCMD控制暫存器,用來控制系統時鐘源,SLEEP 暫存器用來控制各種時鐘源的開關和狀態。PERCFG 暫存器為外設功能控制暫存器,用來控制外設功能模式。U0CSR、U0GCR、U0BUF、U0BAUD 等位串列埠相關暫存器。
在這裡插入圖片描述
圖5-2-13 USB轉串列埠部分原理圖
上圖是節點的串列埠相關電路原理圖。在這個圖中,我們可以看到CH340晶片完成了USB轉串列埠的工作,通過USB電纜連線節點和計算機後,CH340晶片會在計算機中虛擬一個串列埠,這個串列埠訊號對於圖中的CH340_TXD和CH340_RXD,通過J2上的跳線帽與CC2530的P0.2和P0.3引腳相連。
通過之前的IO映射覆用圖我們可以發現,P0.2和P0.3對應的是USART0在UART模式下的RXT和TXD引腳。
③按鍵控制實驗
如圖所示,按鍵部分的電路圖比較簡單。UserINT訊號連線的是晶片的P2.0引腳,在按鍵沒有被按下時(處於斷開狀態),經過電阻R9的上拉作用,UserINT訊號是處於高電平的,而當按鍵按下時,UserINT訊號直接和地相連,這樣處於低電平。在晶片內通過檢測P2.0口的輸出狀態就可以知道按鍵的狀態。電容C4在按鍵鬆開的時候起到對輸出訊號的緩衝作用,這樣可以過濾掉部分干擾訊號,使得輸出訊號較為平滑。
在這裡插入圖片描述
圖5-3-1 按鍵部分電路原理圖
2)軟體設計
①LED發光二極體實驗
#include <ioCC2530.h>
#define D_COUNT 50 //通用延時時間計數
/***************************************
延時函式,n為延時週期計數
/
void Delay(unsigned int n)
{
unsigned int t,tt;
for(tt=0;tt<n;tt++)
for(t=0;t<1000;t++)
;
}
/

程式主函式
/
void main( void )
{
unsigned int i;
P0DIR = 0xff; //設定P0口全部為輸出
P1DIR = 0xff; //設定P1口全部為輸出
P0 = 0xff; //點亮所有燈
P1 = 0xff;
Delay(D_COUNT);Delay(D_COUNT);Delay(D_COUNT);
P0 = 0; //熄滅所有燈
P1 = 0;
Delay(D_COUNT);Delay(D_COUNT);Delay(D_COUNT);
while(1)
{
for(i=0;i<8;i++)
{
P0 = 0x01<<i; //P0的第i位為1,其它位為0
//P1_0 ^= 1; //P1.0取反
Delay(D_COUNT); //設定IO狀態後需要一個延時來讓我們看到效果
}
P0 = 0;
for(i=0;i<8;i++)
{
P1 = 0x01<<i; //P1的第i位為1,其它位為0
//P0_0 ^= 1; //P0.0取反
Delay(D_COUNT); //設定IO狀態後需要一個延時來讓我們看到效果
}
P1 = 0;
}
}
我們主要看main()函式中的程式碼,程式首先通過配置CC2530相關控制暫存器P0DIR、P1DIR來設定P0、P1工作於普通GPIO的輸出模式。然後點亮所有燈,經過一個長延時後再熄滅所有燈,再經過一個長延時後進入程式主迴圈。在迴圈中首先依次將P0的某一位置1(從低到高,其他位為0,每次置位後在進行一個標準延時)。然後對P0所有位清0,接著對P1口執行以上類似操作。P1口操作結束後清0,再回到上面迴圈對P0口進行操作……
由以上分析我們可以得到以下程式流程圖:
在這裡插入圖片描述
圖5-1-6 程式流程圖
②串列埠收發資料實驗
#include “ioCC2530.h”
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
//定義控制燈的埠
#define led1 P1_0
#define led2 P1_1
void InitIO(void); //IO初始化
void InitUart(void); //串列埠初始化
void SendString(char
string,uint legth); //傳送字串
uchar temp; // 存放接受的資料
char wch[] = “Welcome to test this program!\n”;
/
***************************************
功能描述: 延時
Count: 延時單位數量
/
void DelayXms(unsigned int Count)
{
unsigned int i;
unsigned int j;
for(i = 0; i < Count; i++)
{
for( j=10000; j>0; j–);
}
}
/

功能描述: IO初始化
*****************************************************************************/
void InitIO(void)
{
SLEEPCMD &= ~0X04;
CLKCONCMD = 0X10; //32k和32M時鐘使用外部晶體,timer分頻8M
while(CLKCONSTA!=0X10); //等待時鐘切換
SLEEPCMD = 0X04;

P2DIR = 0x00;              //高兩位零   若設則最高優先USART0
P1DIR|= 0X03;              //P1.0 P1.1 LEDs 燈埠配置
P0DIR|= 0X00;              //input

PERCFG = 0x00;              //UART0 預設埠
P1SEL = 0X00;
P0SEL = 0X0c;               //P0<3:2>設定成外圍應用

}
/*****************************************************************************
功能描述: 串列埠初始化
/
void InitUart(void)
{
U0CSR |= 0x80; //UART方式
U0GCR = 11; //baud_e 波特率設為115200
U0BAUD |= 216; //baud_m = BaudRate*2^(28-buad_e)/32M-256
//BaudRate=(256+baud_m)/2^(28-buad_e)x32MHz
UTX0IF = 1; //接收中斷標記
U0CSR |= 0X40; //允許接收
URX0IE = 1; //接收中斷使能
EA =1; //總中斷開關開啟
}
/

功能描述: 串列埠傳送字串
string: 字串指標
lenth: 長度
*/
void SendString(char*string,uint lenth)
{
uint j;
for (j=0; j<lenth; j++)
{
U0DBUF = string++; //將要傳送字元送入U0DBUF傳送暫存器
while(UTX0IF == 0); //等待發送完成
UTX0IF = 0; //清0標誌位
}
}
/

功能描述: 主函式
*****************************************************************************/
void main(void)
{
InitIO();
InitUart();
DelayXms(10);

led1=1;                         //點亮2個LED燈
led2=1;
SendString(wch,sizeof(wch));

while(1)
{
  ; //進入無限迴圈等待中斷函式被處觸發
}

}
/*****************************************************************************
功能描述: 串列埠中斷函式
*****************************************************************************/
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void)
{
URX0IF = 0; //清中斷標誌
temp = U0DBUF;
U0DBUF = temp; //將收到的字元傳送回去
while(UTX0IF == 0); //等待發送
UTX0IF = 0; //清發送標誌
led1 = ~led1; //指示中斷活動
led2 = ~led2;
}
程式中主要有這幾個函式:
DelayXms(unsigned int Count):延時函式。
InitIO():完成IO初始化功作。首先將系統切換到32Hz主晶振下工作並配置晶片內部頻率,因為串列埠工作波特率較高,晶片對串列埠資訊的處理要求其工作頻率也較高,所以需要在32M頻率下工作。然後配置相關IO暫存器,包括2個LED燈的控制IO口為輸出模式,2個串列埠收發訊號引腳為特殊功能應用模式。
InitUart():完成串列埠的初始化工作。其中對串列埠暫存器進行設定,最重要的是串列埠的波特率設定。我們找到CC2530使用者手冊的P160頁,其中有對波特率相關計算的詳細描述。這裡歸納其計算公式為:

其中BAUD_M和BAUD_E為相關暫存器中的設定位。下表歸納了在系統時鐘為32MHz頻率下的常用波特率對於設定值。
表5-2-1 系統時鐘為32MHz時的常用波特率配置
在這裡插入圖片描述

這裡通過配置CC2530 處理器的串列埠相關控制暫存器來設定串列埠0 的工作模式為串列埠模式,波特率為115200,使用中斷方式接受串列埠資料並向串列埠輸出。

SendString(char*string,uint legth):完成從串列埠傳送字串。其中2個引數分別為傳送字串地址和字串長度。
main():主函式。完成各種初始化後進入迴圈等待串列埠接收中斷被觸法。
UART0_ISR():串列埠接收中斷函式。將收到的字元從串列埠發回。同時改變LED燈的狀態,指示串列埠收到資料。
主函式和中斷函式的流程圖如下:
在這裡插入圖片描述
圖5-2-14 main函式和中斷函式程式流程圖
③按鍵控制實驗
#include <ioCC2530.h>
#define D_COUNT 50 //標準延時週期計數
#define KEY_INPUT P2_0 //定義按鍵引腳
/*****************************************************************************
功能描述: 延時
Count: 延時單位數量
/
void Delay(unsigned int n)
{
unsigned int t,tt;
for(tt=0;tt<n;tt++)
for(t=0;t<1000;t++)
;
}
/

功能描述: 主函式
*****************************************************************************/
void main( void )
{
unsigned int i;
P0DIR = 0x00; //P0口全部為輸入
P1DIR = 0x03; //P1口低2位輸出,其他輸入
P1 = 0;
Delay(D_COUNT);Delay(D_COUNT);Delay(D_COUNT);
while(1)
{
if(!KEY_INPUT) //判斷按鍵是否按下
{
i++;
P1 = i&0x03; //P1低2位賦值為i的低2位
Delay(100); //延時,加長2次判斷間隔
}
Delay(10);
}
}
程式通過讀取P2.0的資訊來獲得按鍵的狀態,同時對P1上的2個發光二極體進行操作。程式中的長延時是為了使得一定時間內的按下只被識別為一次按下,短延時是為了濾掉可能的干擾訊號。程式的流程圖如下。
在這裡插入圖片描述
圖5-3-2 程式流程圖
五、實驗步驟
①LED發光二極體實驗
實驗步驟
使用USB 模擬器連線PC 機和通用節點模組,模組電源開關處於中間“OFF”檔,使用模擬器給模組供電。
啟動IAR 開發環境,開啟“…\基礎感測器實驗\1-5基礎例程\1-LED”目錄下的實驗工程。
在IAR 開發環境中編譯程式、點選下載、除錯程式。按“F5”使程式執行。
觀察現象,可以看到發光二極體輪流亮起。
使用除錯介面上的停止按鈕使程式停止,觀察現象是否停止。
使用除錯介面上的go按鈕(等同“F5”),觀察現象。
②串列埠收發資料實驗
使用USB 模擬器連線PC 機和ZIGBEE模組。將系統配套USB線一端連線PC 機,一端連線ZIGBEE模組的MINI-USB介面上。
注意:如果使用通用節點執行本例程,請檢查板子上的“TXD”和“RXD”位置跳線帽是否已經插上(右下圖圓圈處),下方的電源開關打到“OFF”檔,節點使用模擬器連線供電。
如果使用感測器節點執行本例程,請檢查板子上的“TXD”和“RXD”位置跳線帽是否已經插上(左下圖圓圈處),下方的電源開關打到“OFF”檔,節點使用模擬器連線供電。
在這裡插入圖片描述在這裡插入圖片描述
圖5-2-15 節點實物圖(左為感測器節點,右為通用節點)
連線USB電纜時,需要安裝USB轉串列埠的驅動程式,在“…\基礎感測器實驗\1-5基礎例程\2-串列埠”目錄下執行程式“CH341SER.EXE”安裝驅動,重新拔插USB電纜,待驅動自動載入好,在“我的電腦右鍵——屬性——裝置管理器”中可以發現如下虛擬串列埠條目“USB-SERIAL CH340(COMXX)”。記住這裡的串列埠號碼“COMXX”。
在這裡插入圖片描述
圖5-2-16 檢視串列埠號
啟動IAR 開發環境,開啟“…\基礎感測器實驗\1-5基礎例程\2-串列埠”目錄下的實驗工程。
在IAR 開發環境中編譯程式、點選下載、除錯程式。按“F5”使程式執行。
開啟“…\基礎感測器實驗\1-5基礎例程\2-串列埠”目錄下的串列埠除錯程式“串列埠除錯程式(支援中文).EXE”。按照下圖設定這幾項:串列埠號選擇剛剛在裝置管理器中記下的串列埠號;波特率選擇“115200”;資料位8位;停止位1位;校驗位none;流控制none等其他均為預設。點選右下角的傳送資料按鈕,可以看到接受文字框中顯示接受到同樣的資料。
更換髮送文字框“字串輸入框”中的內容,點擊發送按鈕。可以看到相同的字串又被返回。
實驗效果如下圖
在這裡插入圖片描述
圖5-2-17 例程執行結果

③按鍵控制實驗
使用USB 模擬器連線PC 機和任意一個感測器節點模組,模組電源開關處於“ON”檔,使用電池給模組供電(如電池電量低插上USB電纜,可一邊充電一邊使用)。
啟動IAR 開發環境,開啟“…\基礎感測器實驗\1-5基礎例程\3-按鍵控制”目錄下的實驗工程。
在IAR 開發環境中編譯程式、點選下載、除錯程式。按“F5”使程式執行。
觀察現象,可以看到2個發光二極體都沒有亮起。
按下模組中間的“KEY”按鍵,觀察2個發光二極體的狀態。
重複按鍵操作,嘗試長按或短按,觀察發光二極體狀態。修改程式中的延時數值(下圖中紅點行)後再重複上面操作,體會不同延時下的效果。
在這裡插入圖片描述
圖5-3-3 延時語句位置

補充:1、LED燈的輪詢除錯
在這裡插入圖片描述
3、實現按鍵控制
在這裡插入圖片描述