久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Zigbee之旅(十):綜合小實驗——基于CC2430的溫度監(jiān)測系統(tǒng)(轉(zhuǎn))

 newencn 2012-01-08

 在3月3日寫完“zigbee之旅(九)”后,,筆者本打算立即著手“溫度監(jiān)測系統(tǒng)”小實驗的編寫,,以作為對之前一系列零散知識點的總結(jié)。然而我又意識到,,前面的幾個小實驗雖然每一篇都講得較為詳細,,但是其代碼的規(guī)范性、結(jié)構(gòu)性,,可以說是不堪入目的,。既然是小結(jié),就應(yīng)當在原來的基礎(chǔ)上有所進步,,而不是機械地把前面的小知識點拼湊起來了事,。因此,我暫停了原來的計劃,,抽出時間去學習了一下嵌入式開發(fā)的通用技巧,,寫下了兩篇隨筆《嵌入式C51編程規(guī)范》和《嵌入式項目代碼結(jié)構(gòu)的分層》。本篇日志,,既是Zigbee首次旅行的一個階段性小結(jié),,也融入了筆者近幾天的學習心得,希望能對Zigbee初學者有所幫助,。

  全文按軟件開發(fā)的基本流程來組織:需求分析,、概要設(shè)計、詳細設(shè)計、編碼實現(xiàn),、測試,。

一、需求分析

  經(jīng)“客戶”與“開發(fā)者”共同商討,,確定了如下的系統(tǒng)功能描述:

   使用基于CC2430的節(jié)點采集當前室溫,,并可通過PC監(jiān)測其溫度數(shù)值

   CC2430節(jié)點本身需具備一定的穩(wěn)定性,可自動恢復正常狀態(tài)

   可通過PC來控制節(jié)點的采樣間隔與電源管理

二,、概要設(shè)計

  根據(jù)上述需求分析,,我們可以把系統(tǒng)分為兩大模塊:CC2430節(jié)點 與 PC機

  [CC2430節(jié)點]  

    可定時采集外部參數(shù),,并發(fā)送至PC端

    停機時自動復位

    可接收來自PC機的指令,,并作出相應(yīng)處理:改變采樣間隔/電源管理

  [PC機]  

    PC機通過串口工具接收數(shù)據(jù)并顯示

    可通過串口工具向單片機發(fā)送指令,控制其采樣速度,,電源管理

三,、詳細設(shè)計

(1)代碼結(jié)構(gòu)

  本系統(tǒng)代碼結(jié)構(gòu)的分層,其實已在隨筆《嵌入式項目代碼結(jié)構(gòu)的分層》中提到了,,現(xiàn)copy如下:

 ?。?)硬件抽象層

      [ioCC2430.h](系統(tǒng)自帶)定義了CC2430的所有SFR ,、中斷向量    

      [hal.h] 包括常用類型定義,、常用賦值宏、以及CC2430片上資源的通用配置(I/O,、串口通訊,、ADC、定時器,、電源管理等)

  (2)功能模塊層

      [module.h] 定義了片內(nèi)資源(定時器,、I/O)片外擴展模塊(LED),以及相關(guān)函數(shù)的聲明

      [module.c] 實現(xiàn)各模塊(LED)的初始化

  (3)應(yīng)用程序?qū)?/STRONG>

      [main.c] 引用 hal.h,、ioCC2430.h 與 module.h,,實現(xiàn)溫度采集、與PC互通信,、停機復位等具體的應(yīng)用需求

(2)各模塊實現(xiàn)方法

  根據(jù)概要設(shè)計中所劃分的模塊包括,,本性系統(tǒng)可分為兩大模塊:CC2430節(jié)點 和 PC機

  由于PC機上已有串口通信工具,,其功能已能滿足要求,,所以PC這一部分我們不需要做,沒必要對其分析,。下面談一下CC2430節(jié)
點的各子功能的實現(xiàn)方法:

   利用定時器的計數(shù)溢出中斷,,來觸發(fā)定時采樣

   使用串口的 UART0 模式將溫度數(shù)據(jù)傳送至PC

   利用CC2430自帶的看門狗電路,實現(xiàn)系統(tǒng)的停機自動復位功能

   利用串口接收中斷,,來實現(xiàn)對來自PC端的控制指令的捕獲與響應(yīng)

    1) 若接收到 @ 字符,,則為采樣間隔控制命令,,后面緊跟的一個數(shù)字表示采樣間隔:0——0.5s、1——1s,、2——2s
     如:@0,,表示每隔0.5秒采樣一次。
    2) 若接收到 $  字符,,則為睡眠控制命令,,后面緊跟的一個數(shù)字表示電源模式
     如:$3,表示使系統(tǒng)進入電源模式3,。

(3)程序流程圖

四,、編碼實現(xiàn)

(1)硬件抽象層

  硬件抽象層包括 ioCC2430.h 和 hal.h。由于前者系統(tǒng)自帶,,就不列出來了,。

  下面把 hal.h 的全部內(nèi)容列出來(由于這個文件太長,看起來不方便,,我就分模塊展示):

/***********************************************************
*文件名稱: hal.h
*作 者: hustlzp
*日 期: 2011/3/8
*版 本: 1.1
*功能說明: 硬件抽象層
*修改記錄:
**********************************************************
*/
 

#ifndef HAL_H
#define HAL_H
 

#include
<ioCC2430.h>
 

/***********************************************************
常用類型定義
**********************************************************
*/
typedef unsigned
char BYTE;
typedef unsigned
int WORD;
typedef unsigned
long DWORD;


/***********************************************************
常用宏定義
**********************************************************
*/

//高8位
#define HIGH_BYTE(a) ((BYTE) (((WORD)(a)) >> 8))
 

//低8位
#define LOW_BYTE(a) ((BYTE) ((WORD)(a)))
 

//賦值
#define SET_WORD(regH,regL,word) \
do{ \
(regH)
=HIGH_BYTE(word); \
(regL)
=LOW_BYTE(word); \
}
while(0)
/***********************************************************
I/O口
**********************************************************
*/
/*配置I/O口方向
-----------------------------------------
*/
#define IO_DIR_PORT_PIN(port, pin, dir) \
do { \
if (dir == IO_OUT) \
P##port##DIR
|= (0x01<<(pin)); \
else \
P##port##DIR
&=~(0x01<<(pin)); \
}
while(0)


//其中參數(shù) dir 的取值為:
#define IO_IN 0
#define IO_OUT 1
 

/*配置I/O口的輸入模式
-----------------------------------------
*/
#define IO_IMODE_PORT_PIN(port, pin, imode) \
do { \
if (imode == IO_IMODE_TRI) \
P##port##INP
|= (0x01<<(pin)); \
else \
P##port##INP
&=~(0x01<<(pin)); \
}
while (0)


 

#define IO_PUD_PORT(port, pud) \
do { \
if (pud == IO_PULLDOWN) \
P2INP
|= (0x01<< (port+5)); \
else \
P2INP
&=~(0x01<< (port+5));\
}
while (0)


//其中參數(shù) pud 的取值為:
#define IO_PULLUP 0 //上拉
#define IO_PULLDOWN 1 //下拉
 

/*配置I/O口的功能
-----------------------------------------
*/

#define IO_FUNC_PORT_PIN(port, pin, func) \
do { \
if((port ==2) && (pin ==3)){ \
if (func) { \
P2SEL
|=0x02; \
}
else { \
P2SEL
&=~0x02; \
} \
} \
elseif((port ==2) && (pin ==4)){ \
if (func) { \
P2SEL
|=0x04; \
}
else { \
P2SEL
&=~0x04; \
} \
} \
else{ \
if (func) { \
P##port##SEL
|= (0x01<<(pin)); \
}
else { \
P##port##SEL
&=~(0x01<<(pin));\
} \
} \
}
while (0)


//其中參數(shù) func 的取值為:
#define IO_FUNC_GIO 0 // 通用I/O
#define IO_FUNC_PERIPH 1 // 外設(shè)I/O
 

// 配置外設(shè)I/O的位置
#define IO_PER_LOC_TIMER1_AT_PORT0_PIN234() do { PERCFG = (PERCFG&~0x40)|0x00; } while (0)
#define IO_PER_LOC_TIMER1_AT_PORT1_PIN012() do { PERCFG = (PERCFG&~0x40)|0x40; } while (0)

#define IO_PER_LOC_TIMER3_AT_PORT1_PIN34() do { PERCFG = (PERCFG&~0x20)|0x00; } while (0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN67() do { PERCFG = (PERCFG&~0x20)|0x20; } while (0)

#define IO_PER_LOC_TIMER4_AT_PORT1_PIN01() do { PERCFG = (PERCFG&~0x10)|0x00; } while (0)
#define IO_PER_LOC_TIMER4_AT_PORT2_PIN03() do { PERCFG = (PERCFG&~0x10)|0x10; } while (0)

#define IO_PER_LOC_SPI1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x08)|0x00; } while (0)
#define IO_PER_LOC_SPI1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x08)|0x08; } while (0)

#define IO_PER_LOC_SPI0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x00; } while (0)
#define IO_PER_LOC_SPI0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x04; } while (0)

#define IO_PER_LOC_UART1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x02)|0x00; } while (0)
#define IO_PER_LOC_UART1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x02)|0x02; } while (0)

#define IO_PER_LOC_UART0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x00; } while (0)
#define IO_PER_LOC_UART0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x01; } while (0)
 
//其中參數(shù) imode 的取值為:
#define IO_IMODE_PUD 0 // 上拉/下拉
#define IO_IMODE_TRI 1 // 三態(tài)
/***********************************************************
中斷
**********************************************************
*/
// 用于開/關(guān)中斷
#define INT_ON 1
#define INT_OFF 0
 

// 用于置位/清除中斷標志
#define INT_SET 1
#define INT_CLR 0
 

// 全局中斷設(shè)置
#define INT_GLOBAL_ENABLE(on) EA=(!!on)
 

//定義中斷
#define INUM_RFERR 0
#define INUM_ADC 1
#define INUM_URX0 2
#define INUM_URX1 3
#define INUM_ENC 4
#define INUM_ST 5
#define INUM_P2INT 6
#define INUM_UTX0 7
#define INUM_DMA 8
#define INUM_T1 9
#define INUM_T2 10
#define INUM_T3 11
#define INUM_T4 12
#define INUM_P0INT 13
#define INUM_UTX1 14
#define INUM_P1INT 15
#define INUM_RF 16
#define INUM_WDT 17
 

/*中斷允許
-----------------------------------------
*/
#define INT_ENABLE(inum, on) \
do { \
if (inum==INUM_RFERR) { RFERRIE = on; } \
elseif (inum==INUM_ADC) { ADCIE = on; } \
elseif (inum==INUM_URX0) { URX0IE = on; } \
elseif (inum==INUM_URX1) { URX1IE = on; } \
elseif (inum==INUM_ENC) { ENCIE = on; } \
elseif (inum==INUM_ST) { STIE = on; } \
elseif (inum==INUM_P2INT) { (on) (IEN2 |=0x02) : (IEN2 &=~0x02); } \
elseif (inum==INUM_UTX0) { (on) (IEN2 |=0x04) : (IEN2 &=~0x04); } \
elseif (inum==INUM_DMA) { DMAIE = on; } \
elseif (inum==INUM_T1) { T1IE = on; } \
elseif (inum==INUM_T2) { T2IE = on; } \
elseif (inum==INUM_T3) { T3IE = on; } \
elseif (inum==INUM_T4) { T4IE = on; } \
elseif (inum==INUM_P0INT) { P0IE = on; } \
elseif (inum==INUM_UTX1) { (on) (IEN2 |=0x08) : (IEN2 &=~0x08); } \
elseif (inum==INUM_P1INT) { (on) (IEN2 |=0x10) : (IEN2 &=~0x10); } \
elseif (inum==INUM_RF) { (on) (IEN2 |=0x01) : (IEN2 &=~0x01); } \
elseif (inum==INUM_WDT) { (on) (IEN2 |=0x20) : (IEN2 &=~0x20); } \
}
while (0)


/*設(shè)置中斷優(yōu)先級
-----------------------------------------
*/
#define INT_PRIORITY(group, pri) \
do { \
if (pri ==0) { IP0 &=~group; IP1 &=~group; } \
if (pri ==1) { IP0 |= group; IP1 &=~group; } \
if (pri ==2) { IP0 &=~group; IP1 |= group; } \
if (pri ==3) { IP0 |= group; IP1 |= group; } \
}
while (0)

// 其中參數(shù) pri 的取值為:0/1/2/3(最高優(yōu)先級)


// 其中參數(shù) group 的取值為:
#define RFERR_RF_DMA 0x01 // Group IP0
#define ADC_P2INT_T1 0x02 // Group IP1
#define URX0_UTX0_T2 0x04 // Group IP2
#define URX1_UTX1_T3 0x08 // Group IP3
#define ENC_P1INT_T4 0x10 // Group IP4
#define ST_WDT_P0INT 0x20 // Group IP5
 

/*獲取中斷標志
-----------------------------------------
*/
#define INT_GETFLAG(inum) ( \
(inum
==INUM_RFERR) RFERRIF : \
(inum
==INUM_ADC) ADCIF : \
(inum
==INUM_URX0) URX0IF : \
(inum
==INUM_URX1) URX1IF : \
(inum
==INUM_ENC) ENCIF_0 : \
(inum
==INUM_ST) STIF : \
(inum
==INUM_P2INT) P2IF : \
(inum
==INUM_UTX0) UTX0IF : \
(inum
==INUM_DMA) DMAIF : \
(inum
==INUM_T1) T1IF : \
(inum
==INUM_T2) T2IF : \
(inum
==INUM_T3) T3IF : \
(inum
==INUM_T4) T4IF : \
(inum
==INUM_P0INT) P0IF : \
(inum
==INUM_UTX1) UTX1IF : \
(inum
==INUM_P1INT) P1IF : \
(inum
==INUM_RF) S1CON &=~0x03 : \
(inum
==INUM_WDT) WDTIF : \
0 \
)


/*設(shè)置中斷標志
-----------------------------------------
*/
#define INT_SETFLAG(inum, f) \
do { \
if (inum==INUM_RFERR) { RFERRIF= f; } \
elseif (inum==INUM_ADC) { ADCIF = f; } \
elseif (inum==INUM_URX0) { URX0IF = f; } \
elseif (inum==INUM_URX1) { URX1IF = f; } \
elseif (inum==INUM_ENC) { ENCIF_1 = ENCIF_0 = f; } \
elseif (inum==INUM_ST) { STIF = f; } \
elseif (inum==INUM_P2INT) { P2IF = f; } \
elseif (inum==INUM_UTX0) { UTX0IF= f; } \
elseif (inum==INUM_DMA) { DMAIF = f; } \
elseif (inum==INUM_T1) { T1IF = f; } \
elseif (inum==INUM_T2) { T2IF = f; } \
elseif (inum==INUM_T3) { T3IF = f; } \
elseif (inum==INUM_T4) { T4IF = f; } \
elseif (inum==INUM_P0INT) { P0IF = f; } \
elseif (inum==INUM_UTX1) { UTX1IF= f; } \
elseif (inum==INUM_P1INT) { P1IF = f; } \
elseif (inum==INUM_RF) { (f) (S1CON |=0x03) : (S1CON &=~0x03); } \
elseif (inum==INUM_WDT) { WDTIF = f; } \
}
while (0)
/***********************************************************
串口
**********************************************************
*/
// 不同波特率對應(yīng)的BAUD_E的值
#define BAUD_E(baud, clkDivPow) ( \
(baud
==2400) 6+clkDivPow : \
(baud
==4800) 7+clkDivPow : \
(baud
==9600) 8+clkDivPow : \
(baud
==14400) 8+clkDivPow : \
(baud
==19200) 9+clkDivPow : \
(baud
==28800) 9+clkDivPow : \
(baud
==38400) 10+clkDivPow : \
(baud
==57600) 10+clkDivPow : \
(baud
==76800) 11+clkDivPow : \
(baud
==115200) 11+clkDivPow : \
(baud
==153600) 12+clkDivPow : \
(baud
==230400) 12+clkDivPow : \
(baud
==307200) 13+clkDivPow : \
0 )


// 不同波特率對應(yīng)的BAUD_M的值
#define BAUD_M(baud) ( \
(baud
==2400) 59 : \
(baud
==4800) 59 : \
(baud
==9600) 59 : \
(baud
==14400) 216 : \
(baud
==19200) 59 : \
(baud
==28800) 216 : \
(baud
==38400) 59 : \
(baud
==57600) 216 : \
(baud
==76800) 59 : \
(baud
==115200) 216 : \
(baud
==153600) 59 : \
(baud
==230400) 216 : \
(baud
==307200) 59 : \
0)


/* UART模式下的串口配置
-----------------------------------------
*/
#define UART_SETUP(uart, receiveEnable, baudRate, options) \
do { \
if((uart) ==0){ \
if(PERCFG &0x01){ \
P1SEL
|=0x30; \
}
else { \
P0SEL
|=0x0C; \
} \
} \
else { \
if(PERCFG &0x02){ \
P1SEL
|=0xC0; \
}
else { \
P0SEL
|=0x30; \
} \
} \
\
U##uart##GCR
= BAUD_E((baudRate),CLKSPD); \
U##uart##BAUD
= BAUD_M(baudRate); \
\
U##uart##CSR
|=0x80; \
\
U##uart##CSR
|= receiveEnable; \
\
U##uart##UCR
|= ((options) |0x80); \
}
while(0)

//其中參數(shù) receiveEnable 的取值:
#define UART_RECEIVE_ENABLE 0x40 //接收允許
#define UART_RECEIVE_DISABLE 0x00

// 其中參數(shù) options 的取值:
#define FLOW_CONTROL_ENABLE 0x40 //流控制
#define FLOW_CONTROL_DISABLE 0x00
 

#define EVEN_PARITY 0x20 //偶校驗
#define ODD_PARITY 0x00 //奇校驗
 

#define NINE_BIT_TRANSFER 0x10 //9字節(jié)傳輸
#define EIGHT_BIT_TRANSFER 0x00 //8字節(jié)傳輸
 

#define PARITY_ENABLE 0x08 //奇偶校驗使能
#define PARITY_DISABLE 0x00

#define TWO_STOP_BITS 0x04 //2位停止位
#define ONE_STOP_BITS 0x00 //1位停止位
 

#define HIGH_STOP 0x02 //停止位高電平
#define LOW_STOP 0x00 //停止位低電平

#define HIGH_START 0x01 //起始位電平高
#define LOW_START 0x00 //起始位電平低
 

//串口發(fā)送字符
#define UART_SEND(uart,data) \
do{ \
while(U##uart##CSR &0x01); \
U##uart##DBUF
= data; \
}
while (0)
#define UART0_SEND(data) UART_SEND(0,data)
#define UART1_SEND(data) UART_SEND(1,data)
 

//串口接收字符
#define UART_RECEIVE(uart,data) \
do{ \
while(!(U##uart##CSR&0x04)); \
data
=U##uart##DBUF; \
}
while(0)
#define UART0_RECEIVE(data) UART_RECEIVE(0,data)
#define UART1_RECEIVE(data) UART_RECEIVE(1,data)
/***********************************************************
電源及時鐘管理
**********************************************************
*/
// 獲取時鐘分頻
#define CLKSPD (CLKCON & 0x07)
 

// 設(shè)置電源模式
#define SET_POWER_MODE(mode) \
do { \
if(mode ==0) { SLEEP &=~0x03; } \
elseif (mode ==3) { SLEEP |=0x03; } \
else { SLEEP &=~0x03; SLEEP |= mode; } \
PCON
|=0x01; \
asm(
"NOP"); \
}
while (0)


// 參數(shù) mode 的取值為:
#define POWER_MODE_0 0x00
#define POWER_MODE_1 0x01
#define POWER_MODE_2 0x02
#define POWER_MODE_3 0x03
 

// 用于檢測高頻RC振蕩器的穩(wěn)定狀況
#define HIGH_FREQUENCY_RC_OSC_STABLE (SLEEP & 0x20)
 

// 用于檢測晶體振蕩器的穩(wěn)定狀況
#define XOSC_STABLE (SLEEP & 0x40)
 

// 獲取定時器的tick頻率值
#define TICKSPD ((CLKCON & 0x38) >> 3)
 

// 設(shè)置主時鐘頻率
#define SET_MAIN_CLOCK_SOURCE(source) \
do { \
if(source) { \
CLKCON
|=0x40; \
while(!HIGH_FREQUENCY_RC_OSC_STABLE); \
if(TICKSPD ==0){ \
CLKCON
|=0x08; \
} \
SLEEP
|=0x04; \
} \
else { \
SLEEP
&=~0x04; \
while(!XOSC_STABLE); \
asm(
"NOP"); \
CLKCON
&=~0x47; \
SLEEP
|=0x04; \
} \
}
while (0)


// 其中參數(shù) source 的取值為:
#define CRYSTAL 0x00 //晶體振蕩器
#define RC 0x01 //RC振蕩器
/***********************************************************
定時器1
**********************************************************
*/
//定時器1允許計數(shù)溢出中斷
#define TIMER1_ENABLE_OVERFLOW_INT(val) \
(TIMIF
= (val) TIMIF |0x40 : TIMIF &~0x40)


//設(shè)置定時器1的溢出中斷標志
#define TIMER1_OVERFLOW_INT_SETFLAG(f) (T1CTL= ((T1CTL & (~0x10)) | f))
 

//定時器1啟動
#define TIMER1_RUN(value) (T1CTL = (value) ? T1CTL|0x02 : T1CTL&~0x03)
 

//設(shè)置定時器的時鐘分頻
#define SET_TIMER_TICK(value) do{ CLKCON = ((CLKCON & (~0x38)) | value);} while(0)
 

//其中value的取值為:
#define TIMER1_TICK_32M 0x00 // 32MHz
#define TIMER1_TICK_16M 0x08 // 16MHz,系統(tǒng)復位默認值
#define TIMER1_TICK_8M 0x10 // 8MHz
#define TIMER1_TICK_4M 0x18 // 4MHz
#define TIMER1_TICK_2M 0x20 // 2MHz
#define TIMER1_TICK_1M 0x28 // 1MHz
#define TIMER1_TICK_500k 0x30 // 500kHz
#define TIMER1_TICK_250k 0x38 // 250kHz

//設(shè)置定時器1的TICK分頻
#define SET_TIMER1_TICKDIV(value) \
do{ \
T1CTL
&=~0x0c; \
T1CTL
|= value; \
}
while (0)

//其中 value 的取值為:
#define TIMER1_TICKDIV_1 0x00 //1分頻
#define TIMER1_TICKDIV_8 0x04 //8分頻
#define TIMER1_TICKDIV_32 0x08
#define TIMER1_TICKDIV_128 0x0c
 

//設(shè)置定時器溢出周期
#define SET_TIMER1_PERIOD(value) \
do{ \
T1CC0H
= HIGH_BYTE(value); \
T1CC0L
= LOW_BYTE(value); \
}
while (0)

//設(shè)置定時器1的運行模式
#define SET_TIMER1_MODE(mode) \
do{ \
T1CTL
= ((T1CTL & (~0x03)) | mode); \
}
while (0)


//其中 mode 的取值為:
#define TIMER1_MODE_STOP 0x00
#define TIMER1_MODE_FREE 0x01
#define TIMER1_MODE_MODULE 0x02
#define TIMER1_MODE_UPDOWN 0x03
/***********************************************************
看門狗
**********************************************************
*/
// 設(shè)置看門狗定時器的溢出周期
#define WDT_SET_TIMEOUT_PERIOD(timeout) \
do { WDCTL &=~0x03; WDCTL |= timeout; } while (0)


// 其中參數(shù) timeout 的取值為:
#define SEC_1 0x00 // after 1 second
#define M_SEC_250 0x01 // after 250 ms
#define M_SEC_15 0x02 // after 15 ms
#define M_SEC_2 0x03 // after 2 ms
 

// 喂狗程序
#define WDT_RESET() do { \
WDCTL
= (WDCTL &~0xF0) |0xA0; \
WDCTL
= (WDCTL &~0xF0) |0x50; \
}
while (0)


// 啟動/停止看門狗定時器
#define WDT_ENABLE() WDCTL |= 0x08
#define WDT_DISABLE() WDCTL &= ~0x08
/***********************************************************
ADC
**********************************************************
*/
// 配置單次ADC
#define ADC_SINGLE_CONVERSION(settings) \
do{ ADCCON3 = settings; }while(0)

// 其中的參數(shù) setting 由下面的組合構(gòu)成
// 參考電壓
#define ADC_REF_1_25_V 0x00 // 內(nèi)部 1.25V 參考電壓
#define ADC_REF_P0_7 0x40 // AIN7 引腳上的外部參考電壓
#define ADC_REF_AVDD 0x80 // AVDD_SOC 引腳
#define ADC_REF_P0_6_P0_7 0xC0 // AIN6-AIN7 差分輸入的外部參考電壓
 

// 采樣速率
#define ADC_8_BIT 0x00 // 8位
#define ADC_10_BIT 0x10 // 10位
#define ADC_12_BIT 0x20 // 12位
#define ADC_14_BIT 0x30 // 14位
 

// 輸入頻道
#define ADC_AIN0 0x00 // P0_0
#define ADC_AIN1 0x01 // P0_1
#define ADC_AIN2 0x02 // P0_2
#define ADC_AIN3 0x03 // P0_3
#define ADC_AIN4 0x04 // P0_4
#define ADC_AIN5 0x05 // P0_5
#define ADC_AIN6 0x06 // P0_6
#define ADC_AIN7 0x07 // P0_7
#define ADC_GND 0x0C //
#define ADC_TEMP_SENS 0x0E // 片內(nèi)溫度傳感器
#define ADC_VDD_3 0x0F // vdd/3
 






// ADC轉(zhuǎn)換完成的標志
#define ADC_SAMPLE_READY() (ADCCON1 & 0x80)

#endif
//啟動ADC轉(zhuǎn)化
#define ADC_START() \
do { ADCCON1 |=0x40; } while (0)
// 選擇ADC的觸發(fā)模式為手動(即ADC_SAMPLE_READY)
#define ADC_STOP() \
do { ADCCON1 |=0x30; } while (0)

(2)功能模塊層

/***********************************************************
*文件名稱: module.h
*作 者: hustlzp
*日 期: 2011/3/6
*版 本: 1.0
*功能說明: 功能模塊層頭文件
*函數(shù)列表: void led_init()
void timer1_init()
void uart0_init(void);
void Uart0SendString(unsigned char *s);
float adc_start(void)
void get_temperature(unsigned char *output,float temp);
void watchdog_init(void);
*修改記錄:
**********************************************************
*/
  
#ifndef MODULE_H
#define MODULE_H
 

#include
"hal.h"
 

/***********************************************************
LED
**********************************************************
*/
//定義LED引腳
#define led1 P1_0
#define led2 P1_1
#define led3 P1_2
#define led4 P1_3

//led亮與滅
#define LED_OFF 1
#define LED_ON 0

//LED初始化
void led_init(void);


/***********************************************************
timer1
**********************************************************
*/
//用于設(shè)置定時器的溢出周期值
#define TIMER1_OVF_2SEC 0xF424 // 2s
#define TIMER1_OVF_1SEC 0x7A12 // 1s
#define TIMER1_OVF_dot5SEC 0x3D09 // 0.5s

//定時器1初始化
void timer1_init(void);

/***********************************************************
UART0
**********************************************************
*/
//UART0初始化
void uart0_init(void);

//串口傳送字符串
void Uart0SendString(unsigned char*s);

/***********************************************************
ADC-14
**********************************************************
*/
//用于將ADC得到的數(shù)據(jù)轉(zhuǎn)化為攝氏溫度
#define ADC_TO_CELSIUS(temp) (temp * 0.06229 - 311.43)

//啟動ADC轉(zhuǎn)換
float adc_start(void);

//轉(zhuǎn)換
void get_temperature(unsigned char*output,float temp);


/***********************************************************
WatchDog
**********************************************************
*/
//看門狗初始化
void watchdog_init(void);

#endif
/***********************************************************
*文件名稱: module.c
*作 者: hustlzp
*日 期: 2011/3/11
*版 本: 1.0
*功能說明: 功能模塊層源文件
*函數(shù)列表: (略)
*修改記錄:
**********************************************************
*/
 

#include
"module.h"


/***********************************************************
*函數(shù)名稱: led_init
*函數(shù)功能: LED初始化
*入口參數(shù): 無    
*出口參數(shù): 無  
**********************************************************
*/
void led_init(void)
{
//配置P1.0 P1.1 P1.2 P1.3 為通用I/O口
IO_FUNC_PORT_PIN(1, 0, IO_FUNC_GIO);
IO_FUNC_PORT_PIN(
1, 1, IO_FUNC_GIO);
IO_FUNC_PORT_PIN(
1, 2, IO_FUNC_GIO);
IO_FUNC_PORT_PIN(
1, 3, IO_FUNC_GIO);

//配置P1.0 P1.1 P1.2 P1.3 為輸出
IO_DIR_PORT_PIN(1, 0, IO_OUT);
IO_DIR_PORT_PIN(
1, 1, IO_OUT);
IO_DIR_PORT_PIN(
1, 2, IO_OUT);
IO_DIR_PORT_PIN(
1, 3, IO_OUT);

led1
= LED_ON;
led2
= LED_OFF;
led3
= LED_OFF;
led4
= LED_OFF;
}


/***********************************************************
*函數(shù)名稱: timer1_init
*函數(shù)功能: 定時器1初始化
*入口參數(shù): 無    
*出口參數(shù): 無  
**********************************************************
*/
void timer1_init(void)
{
INT_GLOBAL_ENABLE(INT_ON);
//開全局中斷

INT_ENABLE(INUM_T1, INT_ON);
//開T1中斷

TIMER1_ENABLE_OVERFLOW_INT(INT_ON);
//開T1計數(shù)溢出中斷

SET_TIMER_TICK(TIMER1_TICK_4M);
//設(shè)置定時器TICK為4MHz

SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
//設(shè)置T1的計數(shù)周期為2s

SET_TIMER1_TICKDIV(TIMER1_TICKDIV_128);
//設(shè)置T1的時鐘分頻為128

SET_TIMER1_MODE(TIMER1_MODE_MODULE);
//設(shè)置T1的運行模式為module
}


/***********************************************************
*函數(shù)名稱: uart0_init
*函數(shù)功能: 串口UART0初始化
*入口參數(shù): 無    
*出口參數(shù): 無  
**********************************************************
*/
void uart0_init(void)
{
//選擇uart位置
IO_PER_LOC_UART0_AT_PORT0_PIN2345();

//配置uart:接收允許,,115200bps,一位停止位,,無奇偶校驗
UART_SETUP(0, UART_RECEIVE_ENABLE, 115200, ONE_STOP_BITS | PARITY_DISABLE);

//開總中斷
INT_GLOBAL_ENABLE(INT_ON);

//開串口0接收中斷
INT_ENABLE(INUM_URX0, INT_ON);
}


/***********************************************************
*函數(shù)名稱: Uart0SendString
*函數(shù)功能: 定時器1初始化
*入口參數(shù): unsigned char *s
想要發(fā)送的字符串    
*出口參數(shù): 無  
**********************************************************
*/
void Uart0SendString(unsigned char*s)
{
while(*s !=0)
UART0_SEND(
*s++);
}


/***********************************************************
*函數(shù)名稱: adc_start
*函數(shù)功能: 啟動ADC轉(zhuǎn)換
*入口參數(shù): 無    
*出口參數(shù): float
片內(nèi)的攝氏溫度值  
**********************************************************
*/
float adc_start(void)
{
unsigned
int temp;

//參考電壓選擇1.25V,,采樣精度為14位,轉(zhuǎn)換目標為片內(nèi)溫度傳感器
ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);

ADC_STOP();
//設(shè)置ADC轉(zhuǎn)化的觸發(fā)方式為手動

ADC_START();
//啟動ADC轉(zhuǎn)化

while(!ADC_SAMPLE_READY()); //等待轉(zhuǎn)化完成

temp
= ADCL >>2; //將轉(zhuǎn)化結(jié)果存入temp中
temp |= (((unsigned int) ADCH) <<6);

return ADC_TO_CELSIUS(temp); //返回轉(zhuǎn)換后的實際溫度值
}


/***********************************************************
*函數(shù)名稱: get_temperature
*函數(shù)功能: 將溫度值處理后存入字符數(shù)組中,,便于串口輸出
*入口參數(shù): unsigned char *output
用于存儲轉(zhuǎn)換后的溫度值
float temp 
攝氏溫度值   
*出口參數(shù): 無  
**********************************************************
*/
void get_temperature(unsigned char*output,float temp)
{
output[
0] = (unsigned char)(temp) /10+48; //十位
output[1] = (unsigned char)(temp) %10+48; //個位
output[2] ='.'; //小數(shù)點
output[3] = (unsigned char)(temp*10) %10+48; //十分位
output[4] = (unsigned char)(temp*100) %10+48; //百分位
output[5] ='\0'; //字符串結(jié)束符
}


/***********************************************************
*函數(shù)名稱: watchdog_init
*函數(shù)功能: 看門狗初始化
*入口參數(shù): 無   
*出口參數(shù): 無  
**********************************************************
*/
void watchdog_init(void)
{
WDT_SET_TIMEOUT_PERIOD(SEC_1);
//設(shè)置超時時間為1s
WDT_ENABLE(); //啟動看門狗
}

(3)應(yīng)用程序?qū)?/SPAN>

/*******************************************************************
文件名稱: main.c
作 者: hustlzp
日 期: 2011/3/11
版 本: 1.0
功能說明: 主程序文件
函數(shù)列表: (略)
修改記錄:
******************************************************************
*/


#include


 


/********************************************************************
中斷服務(wù)程序
*******************************************************************
*/
/* 定時器1溢出中斷子程序
-------------------------------------------------------
*/
#pragma vector=T1_VECTOR
__interrupt
void T1_ISR(void)
{
EA
=0; //關(guān)中斷

led2
= LED_ON;

get_temperature(output,adc_start());
//將溫度值轉(zhuǎn)換為待輸出的字符數(shù)組

Uart0SendString(output);
//輸出溫度值
Uart0SendString("℃\r\n");


led2


/* 串口接收中斷子程序
-------------------------------------------------------
*/
#pragma vector=URX0_VECTOR
__interrupt
void RE_ISR(void)
{
EA
=0;

led3
= LED_ON;

receive
= U0DBUF;

if(type==1) // type=1,,表示接收到的字符用于設(shè)置定時器溢出周期
{
type
=0;
switch(receive)
{
case'0': //定時器溢出周期為0.5s
{
SET_TIMER1_PERIOD(TIMER1_OVF_dot5SEC);
break;
}
case'1': //定時器溢出周期為1s
{
SET_TIMER1_PERIOD(TIMER1_OVF_1SEC);
break;
}
case'2': //定時器溢出周期為2s
{
SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
break;
}
}
}
elseif(type==2) // type=2,表示接收到的字符用于睡眠控制
{
type
=0;
led1
= LED_OFF;
led2
= LED_OFF;
led3
= LED_OFF;
switch(receive)
{
case'1': //進入電源模式PM1
{
SET_POWER_MODE(
1);
break;
}
case'2': //進入電源模式PM2
{
SET_POWER_MODE(
2);
break;
}
case'3': //進入電源模式PM3
{
SET_POWER_MODE(
3);
break;
}
}
}
elseif(type==0) // type=0,,表示接收到的字符為控制命令的種類:@ 或 $
{
if(receive=='@')
{
type
=1; //接收到'@',,表示下一個字符用于設(shè)置溢出周期
}
elseif(receive=='$')
{
type
=2; //接收到'$',表示下一個字符用于系統(tǒng)睡眠控制
}
}

led3
= LED_OFF;

EA
=1;
}
=LED_OFF;

TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR);
//清中斷標志

EA
=1; //開中斷
}

/* 主函數(shù)
-------------------------------------------------------
*/
void main(void)
{
SET_MAIN_CLOCK_SOURCE(CRYSTAL);
//設(shè)置系統(tǒng)時鐘為32MHz晶振

led_init();
//LED初始化

uart0_init();
//串口UART0初始化

timer1_init();
//定時器1初始化

watchdog_init();
//看門狗初始化

while(1)
{
WDT_RESET();
//不斷喂狗
}
}
/********************************************************************
主程序
*******************************************************************
*/
/* 全局變量
-------------------------------------------------------
*/
unsigned
char output[6]={0}; //存儲溫度數(shù)據(jù)以便于串口輸出
unsigned char receive; //存儲接收到的字符
unsigned char type=0; //接收到的字符的類型標志,,取值為0/1/2
"module.h"

五,、測試

  吁~代碼終于貼完了,真是累死了,,下面我們來測試一下這個小系統(tǒng):

(1)定時采樣

  打開串口,,并啟動IAR調(diào)試,發(fā)現(xiàn) led1 亮,,同時串口工具上不斷有溫度值產(chǎn)生,,采樣間隔經(jīng)測定為2s:

 

(2)采樣間隔控制

  在串口工具中輸入"@1",然后再測試采樣間隔,,發(fā)現(xiàn)已變?yōu)?s,;輸入"@0",采樣間隔已變?yōu)?.5s。

(3)睡眠控制

  在串口工具中輸入"$1",,發(fā)現(xiàn) led 全部熄滅,,溫度采樣也已停止:

  經(jīng)測試,本系統(tǒng)工作正常穩(wěn)定,,基本符合要求,。

  需要源碼的同學點此下載

六、結(jié)語

  本文以一個稍具綜合性的小實驗為例,,展示了如何整合CC2430片上資源,,編寫出一個比較規(guī)范的小系統(tǒng)。過幾天我會抽時間為 hal.h 編寫一個簡單的使用手冊,,方便自己和大家便捷地操控 CC2430,。

  接下來,筆者將會結(jié)束針對 CC2430 片上資源的研究,,全力投入到 TI Z-Stack 協(xié)議棧的學習中~

  本系列的博文寫作暫時結(jié)束了,,但Zigbee的旅行仍將繼續(xù)。前方的風景未知,,但相信筆者和大家一起披荊斬棘,,遍嘗酸甜苦辣,定會有所斬獲,。

  敬請期待:"登臨 TI Z-Stack" 系列博文,!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多