zigbbe實驗
- zigbee是什么
- zigbee模塊的選擇
- 1.實驗一:點燈
- **代碼演示**
- 實驗現象
- 2.實驗二:按鍵控制燈
- 代碼演示
- 實驗現象
- 3.實驗三:外部中斷
- 代碼演示
- 實驗現象
- 4.實驗四:定時器中斷
- 代碼演示
- 實驗現象
- 5.實驗五:串口通信
- 代碼演示
- 實驗現象
zigbee是什么
類似于藍牙或者lora等等,屬于物聯網終端得一種無線通信技術,
藍牙:距離較短,功耗低,組網數量不錯,資料傳輸不大,
WiFi:資料量比較大,功耗比較大,比較耗電,無線局域網得數量不大,
zigbee:功耗低,休眠幾個ua,也可以進行組網,單網路組網數目比較大,
這三種無線模塊的載波都是2.4G頻率,穿透能力較差
zigbee模塊的選擇
一般來說,TI公司和silicon公司的zigbee模塊做得比較好
TI:
芯片特點是比較便宜,但是組網沒有slilicon穩定,一般學習都使用TI公司生產的
TI方案 zigbee協議堆疊(ZSTACK)
silicon公司模塊:
特點 組網目前來說是最穩定的,但是比較貴
我們通常使用zigbee是用TI公司生產的CC253X系列的模塊,我們可以把它當成一個普通的單片機來進行學習,對后面的協議堆疊分析打下鋪墊,
CC2530F256 CPU:8051 RAM:8K Byte Flash: 256K Byte, 作業頻率無線通信32M,資料通信量是非常少
250K bps(bit 每秒)芯片的供電電壓通常是3.3V
1.實驗一:點燈
CC2530 的I/O 控制口一共有21 個,分成3 組,分別是P0、P1 和P2;由圖可知,P1_0 與P1_1 分別控制LED1和LED2

相關暫存器
P1DIR(P1 方向暫存器,P0DIR 同理)

P1SEL(P1 功能選擇暫存器,P0SEL 同理)

我們只需要配置該引腳的輸出方向和功能即可
代碼演示
#define LED0 P1_0
#define LED1 P1_1
void GPIO_init()
{
P1SEL = P1SEL & ~0x03;
P1DIR = P1DIR | 0x03;
LED0 = 0;
LED1 = 0;
}
void DelayMs(unsigned int msec)//大約1ms延時
{
for(unsigned int x = msec;x > 0;x --)
{
for(unsigned int y = 620;y > 0;y --)
{
asm("NOP");
}
}
}
void main(void)
{
GPIO_init();
while(1)
{
DelayMs(500);
LED0 = 1;
DelayMs(500);
LED0 = 0;
DelayMs(500);
LED1 = 1;
DelayMs(500);
LED1 = 0;
}
}
實驗現象
兩個燈互動閃爍
2.實驗二:按鍵控制燈
從原理圖可知,按鍵沒有按下時是高電平,按下之后是低電平,因為接地了,我們需要對P00和P01引腳進行操作

代碼演示
#include <iocc2530.h>
#define LED0 P1_0
#define LED1 P1_1
#define K1 P0_0
#define K2 P0_1
void GPIO_init()
{
P1SEL = P1SEL & ~0x03;//設定P1_0,P1_1為普通IO口
P1DIR = P1DIR | 0x03;//設定P1_0,P1_1為輸出模式
P0SEL = P0SEL & ~0x03;//設定P1_0,P1_1為普通IO口
P0DIR = P0DIR & ~0x03;//設定P1_0,P1_1為輸入模式
LED0 = 0;
LED1 = 0;
}
void DelayMs(unsigned int msec)//大約1ms延時
{
for(unsigned int x = msec;x > 0;x --)
{
for(unsigned int y = 620;y > 0;y --)
{
asm("NOP");
}
}
}
void main(void)
{
GPIO_init();
while(1)
{
if(K1 == 0)
LED0 = 1;
else
LED0 = 0;
if(K2 == 0)
{
DelayMs(100);//延時消斗
if(K2 == 0)
{
LED1 = ~LED1;
}
while(K2 == 0);
}
}
}
實驗現象
K1按鍵控制led0的亮滅,k2按鍵控制led1的亮滅
3.實驗三:外部中斷
相關暫存器
P0IEN:各個控制口的中斷使能,0 為中斷禁止,1 為中斷使能,

P0INP:設定各個I/O 口的輸入模式,0 為上拉/下拉,1 為三態模式,

PICTL:D0~D3 設定各個埠的中斷觸發方式,0 為上升沿觸發,1 為下降沿x發,

IEN1:中斷使能1,0 為中斷禁止,1 為中斷使能,

P0IFG:中斷狀態標志暫存器,當輸入埠有中斷請求時,相應的標志位將置1,

代碼演示
#include "exit.h"
#include "exit.h"
#define LED0 P1_0
#define LED1 P1_1
#define KEY0 P0_0
#define KEY1 P0_1
void DelayMs(unsigned int msec)//大約1ms延時
{
for(unsigned int x = msec;x > 0;x --)
{
for(unsigned int y = 620;y > 0;y --)
{
asm("NOP");
}
}
}
void led_init(void)
{
P1SEL &= ~0x03 ; //清0第一次 第一為0,代表作業在普通模式
P1DIR |= 0x03; //第一位為1,輸出,否則輸入
P1_0= 0; //關LED
P1_1= 0;
}
//外部中斷
void exit_init(void)
{
//按鍵暫存器的操作,設定為普通模式和輸入模式
P0SEL &= ~0x03;
P0DIR &= ~0x03;
//P0IEN:各個控制口的中斷使能,0 為中斷禁止,1 為中斷使能,
P0IEN |= 0x03;
//P0INP:設定各個I/O 口的輸入模式,0 為上拉/下拉,1 為三態模式
P0INP &= ~0x03;
//PICTL:D0~D3 設定各個埠的中斷觸發方式,0 為上升沿觸發,1 為下降沿觸發
PICTL |= 0x01;//下降沿觸發
//IEN1:中斷使能1,0 為中斷禁止,1 為中斷使能,
//P0IFG:中斷狀態標志暫存器,當輸入埠有中斷請求時,相應的標志位將置1,
P0IFG &= ~0x03; //P0.0中斷標志清0
P0IE = 1; //P0中斷使能
EA = 1; //總中斷使能
}
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void)
{
EA=0;
if((P0IFG & 0x02 ) >0 ) //按鍵中斷 ,p0_1
{
P0IFG &= ~0x02; //P0.1中斷標志清0
LED1 = !LED1;
}
P0IF = 0; //P0中斷標志清0
EA = 1; //開中斷
if((P0IFG & 0x01 ) >0 ) //按鍵中斷 ,p0_0
{
P0IFG &= ~0x01; //P0.0中斷標志清0
LED1 = !LED1;
}
P0IF = 0; //P0中斷標志清0
EA = 1; //開中斷
void main(void)
{
led_init();
ext_init();
while(1);//通過while回圈等待中斷,
}
}
實驗現象
主要用到了中斷,該中斷可以需要配置多個暫存器,假設配置p01,需要開啟總中斷,然后是設定p0的中斷位,后面通過讀取P0IFG 這個暫存器的值來判斷是否產生了中斷
連續按下CC2530主板上K1按鍵,會發現當按鍵被按下時,LED的亮滅狀態會發生改變,
4.實驗四:定時器中斷
定時器1 是一個16 位定時器,具有定時器/計數器/脈寬調制功能,它有3 個單獨可編程 輸入捕獲/輸出比較 信道,每一個信道都可以用來當做PWM 輸出或用來捕獲輸入信號的邊沿時間,
定時器有一個很重要的概念:操作模式,
操作模式包含:自由運行模式(free-running)、 模模式(modulo)和 正計數/倒計數模式(up-down),本次實驗學習到的新暫存器:
T1CTL:定時器1 的控制,D1D0 控制運行模式,D3D2 設定分頻劃分值,
T1STAT:定時器1 的狀態暫存器,D4~D0 為通道4~通道0 的中斷標志,D5 為溢位標志位,當計數到最終技術值是自動置1,
T1CCTL0:D1D0 為捕捉模式選擇:00 為不捕捉,01 為上升沿捕獲,10 為下降沿捕獲,11 為上升或下降沿都捕獲,
IRCON:中斷標志4,;0 為無中斷請求,1 為有中斷請求,
在配置暫存器之前還需要配置時鐘頻率相關的暫存器
CLKCONCMD:時鐘頻率控制暫存器,
D7 位為32KHZ 時間振蕩器選擇,0 為32KRC 震蕩,1 為32K 晶振,
D6 位為系統時鐘選擇,0 為32M 晶振,1 為16M RC 震蕩,當D7 位為0 時D6 必須為1,
D5~D3 為定時器輸出標記,000 為32MHZ,001 為16MHZ,010 為8MHZ,011 為4MHZ,100 為2MHZ,101 為 1MHZ,110 為500KHZ,111 為250KHZ,默認為001,需要注意的是:當D6 為1 時,定時器頻率最高可采用頻率為16MHZ,
D2~D0:系統主時鐘選擇:000 為32MHZ,001 為16MHZ,010 為8MHZ,011 為4MHZ,100 為2MHZ,101 為1MHZ,110 為500KHZ,111 為250KHZ,當D6 為1 時,系統主時鐘最高可采用頻率為16MHZ,
CLKCONSTA:時間頻率狀態暫存器,
D7 位為當前32KHZ 時間振蕩器頻率,0 為32KRC 震蕩,1 為32K 晶振,
D6 位為當前系統時鐘選擇,0 為32M 晶振,1 為16M RC 震蕩,
D5~D3 為當前定時器輸出標記,000 為32MHZ,001 為16MHZ,010 為8MHZ,011 為4MHZ,100 為2MHZ,101 為 1MHZ,110 為500KHZ,111 為250KHZ,
D2~D0 為當前系統主時鐘,000 為32MHZ,001 為16MHZ,010 為8MHZ,011 為4MHZ,100 為2MHZ,101 為1MHZ,110 為500KHZ,111 為250KHZ,
代碼演示
#include "time.h"
#include <iocc2530.h>
#define LED0 P1_0
#define LED1 P1_1
#define K1 P0_0
unsigned char counter;
void SysClockInit(void)
{
unsigned int i;
SLEEPCMD &= ~0x04; //都上電
while(!(CLKCONSTA & 0x40)); //晶體振蕩器開啟且穩定
for (i=0; i<504; i++) asm("NOP");//適當延時
CLKCONCMD &= ~0x47; //選擇32MHz晶體振蕩器
SLEEPCMD |= 0x04;
}
//IRCON:中斷標志4,;0 為無中斷請求,1 為有中斷請求,
void time1_init(void)
{
//T1CTL:定時器1 的控制,D1D0 控制運行模式,D3D2 設定分頻劃分值,
T1CTL = 0x05 ;//自由運行和8分頻
//T1STAT:定時器1 的狀態暫存器,D4~D0 為通道4~通道0 的中斷標志,D5 為溢位標志位,當計數到最終技術值是自動置1,
T1STAT =0x21; //
//T1CCTL0:D1D0 為捕捉模式選擇:00 為不捕捉,01 為上升沿捕獲,10 為下降沿捕獲,11 為上升或下降沿都捕獲,
T1CCTL0 |=0x01; //上升沿捕捉
IEN1 |=0X02;
EA = 1;//開啟中斷
}
#pragma vector = T1_VECTOR
__interrupt void T1_ISR(void)
{
EA = 0;
if(counter>30)
{
counter=0;
LED0 = !LED0;
LED1 = !LED1;
}
counter++;
T1IF = 0;//清除中斷位
EA = 1;//開啟中斷
}
void main(void)
{
SysClockInit();
led_init();
time1_init();
while(1);
}
實驗現象

當某個中斷發送后會進入這個向量中斷表執行相對應的函式
精確控制LED 燈的閃爍間隔為2s,即:亮1s → 暗1s → 亮1s→ 暗1s(即從暗轉亮的時刻間隔為1s),
5.實驗五:串口通信
相關暫存器
U0CSR:USART0 控制與狀態,
D7 為作業模式選擇,0 為SPI 模式,1 為USART 模式,
D6 為UART 接收器使能,0 為禁用接收器,1 為接收器使能,
D5 為SPI 主/從模式選擇,0 為SPI 主模式,1 為SPI 從模式,
D4 為幀錯誤檢測狀態,0 為無錯誤,1 為出現出錯,
D3 為奇偶錯誤檢測,0 為無錯誤出現,1 為出現奇偶校驗錯誤,
D2 為位元組接收狀態,0 為沒有收到位元組,1 為準備好接收位元組,
D1 為位元組傳送狀態,0 為位元組沒有被傳送,1 為寫到資料緩沖區的位元組已經被發送,
D0 為USART 接收/傳送主動狀態,0 為USART 空閑,1 為USART 忙碌,
U0GCR:USART0 通用控制暫存器,
D7 為SPI 時鐘極性:0 為負時鐘極性,1 為正時鐘極性;
D6 為SPI 時鐘相位:
D5 為傳送為順序:0 為最低有效位先傳送,1 為最高有效位先傳送,
D4~D0 為波特率設定
代碼演示
對串口進行配置的時候先要配置好系統的時鐘,然后設定相應串口的配置,如波特率 校驗位等等,最后在開啟相關串口的中斷,通過U0DBUF這個暫存器來接受和發送資料,當這個串口收到資料時,會產生接收中斷,并接收一個字符
#include <iocc2530.h>
#define LED0 P1_0
#define LED1 P1_1
unsigned char Flag_RX,temp;
void led_init(void)
{
P1SEL &= ~0x03; //P1.0 P1.1為普通 I/O 口
P1DIR |= 0x03; //輸出
LED0 = 0; //關LED
LED1 = 0;
}
void SysClock_Init(void)
{
SLEEPCMD &= ~0x04; //都上電
while(!(CLKCONSTA & 0x40)); //晶體振蕩器開啟且穩定
CLKCONCMD &= ~0x47; //選擇32MHz晶體振蕩器
SLEEPCMD |= 0x04;
}
//接著初始化串口,代碼為:
void uart0_init(void)
{
PERCFG = 0x00; //位置1 P0口
P0SEL = 0x3c; //P0_2,P0_3,P0_4,P0_5用作串口,第二功能
P2DIR &= ~0XC0; //P0 優先作為UART0 ,優先級
U0CSR |= 0x80; //UART 方式
U0GCR |= 11; //U0GCR與U0BAUD配合
U0BAUD |= 216; // 波特率設為115200
UTX0IF = 0; //UART0 TX 中斷標志初始置位1 (收發時候)
U0CSR |= 0X40; //允許接收
IEN0 |= 0x84; // 開總中斷,接收中斷
}
//串口發送位元組函式
void Uart_Send_char(char ch)
{
U0DBUF = ch;
while(UTX0IF == 0);
UTX0IF = 0;
}
//串口接收一個字符: 一旦有資料從串口傳至CC2530, 則進入中斷,將接收到的資料賦值給變數temp.
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void)
{
LED0 = 1;
URX0IF = 0; // 清中斷標志
temp = U0DBUF;
Flag_RX = 1;
}
void main(void)
{
SysClock_Init();
led_init();
uart0_init();
while(1)
{
LED0 = 0;
if(Flag_RX)
{
LED1 = 1;
Flag_RX = 0;
Uart_Send_char(temp);
LED1 = 0;
}
}
}
實驗現象
發送什么資料給單片機單片機將會回傳給相應的資料給pc端
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/325833.html
標籤:其他





D7 位為32KHZ 時間振蕩器選擇,0 為32KRC 震蕩,1 為32K 晶振,



