CC2530 具有一個(gè)IEEE 802.15.4 兼容無(wú)線收發(fā)器。RF 內(nèi)核控制模擬無(wú)線模塊。另外,它提供了MCU 和無(wú)線設(shè)備之間的一個(gè)接口,這使得可以發(fā)出命令,讀取狀態(tài),自動(dòng)操作和確定無(wú)線設(shè)備事件的順序。無(wú)線設(shè)備還包括一個(gè)數(shù)據(jù)包過(guò)濾和地址識(shí)別模塊。
CC2530 包括許多不同的外設(shè),允許應(yīng)用程序設(shè)計(jì)者開發(fā)先進(jìn)的應(yīng)用。
調(diào)試接口執(zhí)行一個(gè)專有的兩線串行接口,用于內(nèi)電路調(diào)試。通過(guò)這個(gè)調(diào)試接口,可以執(zhí)行整個(gè)閃存存儲(chǔ)器的擦除、控制使能哪個(gè)振蕩器、停止和開始執(zhí)行用戶程序、執(zhí)行8051 內(nèi)核提供的指令、設(shè)置代碼斷點(diǎn),以及內(nèi)核中全部指令的單步調(diào)試。使用這些技術(shù),可以很好地執(zhí)行內(nèi)電路的調(diào)試和外部閃存的編程。
設(shè)備含有閃存存儲(chǔ)器以存儲(chǔ)程序代碼。閃存存儲(chǔ)器可通過(guò)用戶軟件和調(diào)試接口編程。閃存控制器處理寫入和擦除嵌入式閃存存儲(chǔ)器。閃存控制器允許頁(yè)面擦除和4 字節(jié)編程。
cc2530定時(shí)器
CC2530的時(shí)鐘模塊
振蕩器和時(shí)鐘
CC2530設(shè)備有一個(gè)內(nèi)部系統(tǒng)時(shí)鐘,或者主時(shí)鐘。系統(tǒng)時(shí)鐘源可以是從16MHz RC振蕩器或一個(gè)32M晶體振蕩器中的一個(gè)提供。系統(tǒng)時(shí)鐘源是由CLKCONCMD SRF控制寄存器。
還有一個(gè)32KHz的時(shí)鐘源,來(lái)源可以是從RC 振蕩器或者32KHz的晶體振蕩器中過(guò)來(lái),同樣是由CLKCONCMD寄存器控制。
CLKCONSTA寄存器是一個(gè)制度寄存器,用來(lái)獲得當(dāng)前系統(tǒng)時(shí)鐘的狀態(tài)。
時(shí)鐘源可以在一個(gè)精度高的晶體振蕩器和一個(gè)功耗低的RC振蕩器中交替選擇使用。注意一點(diǎn):RF的收發(fā)操作是要以32MHz的晶體振蕩器為時(shí)鐘源才行。
振蕩器
圖中給出了時(shí)鐘系統(tǒng)中可用的時(shí)鐘源的一個(gè)全貌圖。
設(shè)備中存在的兩個(gè)高頻振蕩器:
* 32MHz晶體振蕩器
* 16MHz的RC振蕩器
32MHz的晶體振蕩器啟動(dòng)時(shí)間對(duì)于某些應(yīng)用來(lái)說(shuō)可能太長(zhǎng)了;因此設(shè)備可以先運(yùn)行在16MHz的RC振蕩器中運(yùn)行直到晶體振蕩器穩(wěn)定后在使用32MHz晶體振蕩器。16MHz的RC振
蕩器功耗低但是不是很準(zhǔn),所以不能為RF模塊提供服務(wù),只能用32MHz的晶體振蕩器。
設(shè)備中存在的兩個(gè)低頻振蕩器:
* 32 KHz晶體振蕩器
* 32 KHz RC振蕩器
32KHz的XOSC被設(shè)計(jì)的工作頻率頻率是32.768KHz并且可以為一些要求時(shí)鐘準(zhǔn)確子系統(tǒng)提供一個(gè)穩(wěn)定的時(shí)鐘信號(hào)。32KHz的RCOSC當(dāng)校準(zhǔn)后可以運(yùn)行在32.753KHz頻率下。校準(zhǔn)
只能發(fā)生在當(dāng)32MHz XOSC使能的情況下,可以通過(guò)使能SLEEPCMD.OSC32K_CALDIS位來(lái)關(guān)閉校準(zhǔn)。32KHz RC振蕩器相對(duì)于32KHz XOSC晶體振蕩器功耗低,應(yīng)該用在可以降
低成本情況下。兩個(gè)振蕩器不能同時(shí)工作。
系統(tǒng)時(shí)鐘
系統(tǒng)時(shí)鐘是由32MHz XOSC或者16MHz RCOSC兩個(gè)時(shí)鐘源驅(qū)動(dòng)的。CLKCONCMD.OSC位用來(lái)選擇系統(tǒng)時(shí)鐘源。注意:使用RF模塊時(shí),32MHz晶體振蕩器必須被選上并且運(yùn)行穩(wěn)定。
注意:改變CLKCONCMD.OSC位并不能立即導(dǎo)致系統(tǒng)時(shí)鐘源的改變。當(dāng)CLKCONSTA.OSC = CLKCONCMD.OSC時(shí)時(shí)鐘源的改變才會(huì)發(fā)揮作用。這是因?yàn)樵O(shè)備在實(shí)際改變時(shí)鐘源之前
需要穩(wěn)定的時(shí)鐘。還有就是注意CLKCONCMD.CLKSPD位反應(yīng)著系統(tǒng)時(shí)鐘頻率,因此是CLKACONCMD.OSC位的鏡子。一旦32MHz的XOSC被選中和穩(wěn)定,例如,當(dāng)CLKCONSTA.OSC
位從1切換到0時(shí)。
注意:從16MHz到32MHz時(shí)鐘源的改變符合CLKCONCMD.TICKSPD設(shè)置。CLKCONCMD.TICKSPD設(shè)置的緩慢一些的話,當(dāng)CLKCONCMD.OSC改變的話會(huì)導(dǎo)致實(shí)際的時(shí)鐘源起作用的
時(shí)間會(huì)很長(zhǎng)。當(dāng)CLKCONCMD.TICKSPD
等于000時(shí)會(huì)獲得最快的切換速度。
32KHz的振蕩器
默認(rèn)的或者復(fù)位后32KHz RCOSC使能并且被設(shè)置作為32KHz的時(shí)鐘源。其功耗低,但是相對(duì)于32KHz晶體振蕩器而言精度不高,32KHz時(shí)鐘源用來(lái)驅(qū)動(dòng)睡眠定時(shí)器,產(chǎn)生看門狗的滴答值
和作為timer 2計(jì)算睡眠定時(shí)器的一個(gè)閘門。32KHz時(shí)鐘源被寄存器CLKCONCMD.OSC32K位用來(lái)作為選擇振蕩器。CLKCONCMD.OSC32K寄存器可以在任意時(shí)間寫入,但是在16MHz RC
振蕩器是活躍的系統(tǒng)時(shí)鐘源之前是不會(huì)起作用的。當(dāng)系統(tǒng)時(shí)鐘從16MHz改變?yōu)?2MHz的晶體振蕩器(CLKCONCMD.OSC從1到0)一旦32KHz RC振蕩器被選中了它的的校驗(yàn)就啟動(dòng)了并且被執(zhí)行。在校準(zhǔn)期間,32MHz晶體振蕩器的一個(gè)分頻量會(huì)被使用。32KHzRCOSC振蕩器校準(zhǔn)后的結(jié)果是它會(huì)工作在32.753kHz上。32kHz RC振蕩器校準(zhǔn)時(shí)間可能要2ms時(shí)間來(lái)完成??梢栽O(shè)置SLEEPCMD.OSC32K_CALDIS位設(shè)置為1的話,會(huì)關(guān)閉校準(zhǔn)。在校準(zhǔn)結(jié)束時(shí),會(huì)在32KHz時(shí)鐘源上產(chǎn)生一個(gè)額外的脈沖,會(huì)導(dǎo)致睡眠定時(shí)器增加1。
注意:當(dāng)切換到32KHz晶體振蕩器后和從32KHz晶體振蕩器被設(shè)置的PM3模式喚醒時(shí),振蕩器穩(wěn)定到準(zhǔn)確頻率的時(shí)間在500 ms以上。睡眠定時(shí)器、看門狗定時(shí)器和時(shí)鐘損失探測(cè)器在32KHz
晶體振蕩器穩(wěn)定之前不能使用。
振蕩器和時(shí)鐘寄存器
下面是振蕩器和時(shí)鐘寄存器的描述,所有寄存器的位會(huì)在進(jìn)入PM2和PM3時(shí)保持不變,除非有異常情況發(fā)生。
定時(shí)器滴答值產(chǎn)生器
CLKCONCMD.TICKSPD寄存器控制timer1、timer3和timer4的全局預(yù)分頻。預(yù)分頻的值設(shè)置范圍在0.25MHz和32MHz之間。
需要注意的是如果CLKCONCMD.TICKSPD顯示的頻率高于系統(tǒng)時(shí)鐘,則在CLKCONSTA.TICKSPD中的實(shí)際的預(yù)分頻值表明是和系統(tǒng)時(shí)鐘的值是一樣的。
數(shù)據(jù)滯留
在PM2和PM3電源模式中,絕大多數(shù)的內(nèi)部電路關(guān)閉了,然而,SRAM中任保留它的內(nèi)容,內(nèi)部寄存器的值也會(huì)保留。
保留數(shù)據(jù)的寄存器是CPU的寄存器、外部寄存器和RF寄存器,除非另一些位域值設(shè)置的比較特殊。切換到PM2和PM3模式的現(xiàn)象對(duì)于軟件而已是透明的。
注意在PM3模式下睡眠定時(shí)器的值不會(huì)保存。
******************************************************************
/**********************************************************************************************************
* 功 能:實(shí)驗(yàn)一 系統(tǒng)時(shí)鐘源的選擇
*
* CC2530有1個(gè)內(nèi)部的系統(tǒng)時(shí)鐘。時(shí)鐘源可以是1個(gè)16MHz的RC振蕩器,也可以是1個(gè)32MHz的晶體
* 振蕩器。時(shí)鐘控制是通過(guò)使用CLKCON特殊功能寄
存器來(lái)執(zhí)行的。系統(tǒng)時(shí)鐘也提供給所有的8051
* 外設(shè)。
*
* 32MHz晶體振蕩器的啟動(dòng)時(shí)間對(duì)于某些應(yīng)用而言太長(zhǎng)了,因此CC2530可以運(yùn)行在16MHz RC振蕩器
* 直到晶體振蕩器穩(wěn)定。16MHz RC振蕩器的功耗要少于晶體振蕩器,但是由于它沒有晶體振蕩器
* 精確,因此它不適用于射頻收發(fā)器。
*
* CLKCONCMD.OSC位被用來(lái)選擇系統(tǒng)時(shí)鐘源。注意:要使用射頻收發(fā)器,32MHz晶體振蕩器必須被選擇
* 并且穩(wěn)定。
*
* 注意:改變CLKCON.OSC位并不即刻生效。這是因?yàn)樵趯?shí)際改變時(shí)鐘源之前,被選擇的時(shí)鐘源要
* 首先達(dá)到穩(wěn)定。還要注意:CLKCONSTA.CLKSPD位將反映系統(tǒng)時(shí)鐘頻率,因此它是CLKCON.OSC位的
* “鏡子”。
*
* 當(dāng)SLEEPSTA.XOSC_STB為1時(shí),表示系統(tǒng)報(bào)告32MHz晶體振蕩器穩(wěn)定。然而,這可能并不是實(shí)際情況,
× 在選擇32MHz時(shí)鐘作為系統(tǒng)時(shí)鐘源之前,應(yīng)該等待一個(gè)額外的64us的安全時(shí)間,可以通過(guò)增加一
* 條空指令“NOP”來(lái)實(shí)現(xiàn)。如果不等待,可能會(huì)造成系統(tǒng)崩潰。
*
* 未被選擇作為系統(tǒng)時(shí)鐘源的振蕩器,通過(guò)設(shè)置SLEEP.OSC_PD為1(默認(rèn)狀態(tài))將被設(shè)置為掉電模式。
* 因此,當(dāng)32MHz晶體振蕩器被選擇作為系統(tǒng)時(shí)鐘源后,16MHz RC振蕩器可能被關(guān)閉,反之亦然。
* 當(dāng)SLEEPCMD.OSC_PD為0時(shí),這2個(gè)振蕩器都被上電并運(yùn)行。
* 當(dāng)32MHz晶體振蕩器被選擇作為系統(tǒng)時(shí)鐘源并且16MHz RC振蕩器也被上電時(shí),根據(jù)供電電壓和運(yùn)
* 行溫度,16MHZ RC振蕩器將被不斷校準(zhǔn)以確保時(shí)鐘穩(wěn)定。當(dāng)16MHz RC振蕩器被選擇作為系統(tǒng)時(shí)鐘
* 源時(shí),該校準(zhǔn)不被執(zhí)行。
*
* 本實(shí)驗(yàn)將向用戶演示選擇不同的振蕩器作為系統(tǒng)時(shí)鐘源。本文件中有led閃爍的子程序,用戶
* 可以觀察在不同系統(tǒng)時(shí)鐘源下led的閃爍情況。
*
* 在hal.h文件中包含了和系統(tǒng)時(shí)鐘相關(guān)的一些宏,用戶使用這些宏可以簡(jiǎn)化對(duì)系統(tǒng)時(shí)鐘的控制,
* 提高代碼的可讀性,本實(shí)驗(yàn)中就使用了其中的一些宏。
*
* 注 意:本實(shí)驗(yàn)可在以下目標(biāo)板上進(jìn)行:
*
*
*
*
*
* 版 本:V1.0 **************************************************************************************************/
#include “hal.h”
#define ON 0x01 //LED狀態(tài)
#define OFF 0x00
extern void ctrPCA9554LED(UINT8 led,UINT8 operation);
extern void PCA9554ledInit();
/**************************************************************************************************
* 函數(shù)名稱:halWait
*
* 功能描述:延時(shí)
*
* 參 數(shù):wait - 延時(shí)時(shí)間
*
* 返 回 值:無(wú)
**************************************************************************************************/
void halWait(BYTE wait){
UINT32 largeWait;
if(wait == 0)
{return;}
largeWait = ((UINT16) (wait 《《 7));
largeWait += 114*wait;
largeWait = (largeWait 》》 CLKSPD);
while(largeWait--);
return;
}
/**************************************************************************************************
* 函數(shù)名稱:main
*
* 功能描述:反復(fù)選擇不同的振蕩器作為系統(tǒng)時(shí)鐘源,并調(diào)用led控制程序,閃爍LED燈。
*
* 參 數(shù):無(wú)
*
* 返 回 值:無(wú)
**************************************************************************************************/
void main(void)
{
UINT8 i;
PCA9554ledInit();
while(1)
{
SET_MAIN_CLOCK_SOURCE(CRYSTAL); // 設(shè)置系統(tǒng)時(shí)鐘源為32MHz晶體振蕩器(大約用時(shí)150us),關(guān)閉16MHz RC振蕩器
for (i=0;i《10;i++)
{
ctrPCA9554LED(0,ON);
halWait(200);
ctrPCA9554LED(0,OFF);
halWait(200);
}
SET_MAIN_CLOCK_SOURCE(RC); // 選擇16MHz RC振蕩器,關(guān)閉32MHz晶體振蕩器
PCA9554ledInit();
halWait(200);
for (i=0;i《10;i++)
{
ctrPCA9554LED(1,ON);
halWait(200);
ctrPCA9554LED(1,OFF);
halWait(200);
}
}
}
/**********************************************************************************************************
* 文 件 名:iic.C
* 功 能:實(shí)驗(yàn)二 GPIO控制實(shí)驗(yàn)
* 該實(shí)驗(yàn)采用CC2530的I/O口(P1.0和P1.1)模擬IIC總線的SCL和SDA,然后通過(guò)IIC總線形式控制GPIO擴(kuò)展芯片
* PCA9554,最后通過(guò)擴(kuò)展的IO來(lái)控制LED的亮滅。
*
* 硬件連接:將OURS的CC2530RF模塊插入到普通電池板或智能電池板上。
*
* P1.0 ------ SCL
* P1.1 ------ SDA
*
* 版 本:V1.0
**************************************************************************************************************/
#include “ioCC2530.h”
#include “hal_mcu.h”
#define SCL P1_0 //IIC時(shí)鐘線
#define SDA P1_1 //IIC數(shù)據(jù)線
//定義IO方向控制函數(shù)
#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)
#define OSC_32KHZ 0x00 //使用外部32K晶體振蕩器
//時(shí)鐘設(shè)置函數(shù)
#define HAL_BOARD_I
NIT() \
{ \
uint16 i; \
\
SLEEPCMD &= ~OSC_PD; /* 開啟 16MHz RC 和32MHz XOSC */ \
while (?。⊿LEEPSTA & XOSC_STB)); /* 等待 32MHz XOSC 穩(wěn)定 */ \
asm(“NOP”); \
for (i=0; i《504; i++) asm(“NOP”); /* 延時(shí)63us*/ \
CLKCONCMD = (CLKCONCMD_32MHZ | OSC_32KHZ); /* 設(shè)置 32MHz XOSC 和 32K 時(shí)鐘 */ \
while (CLKCONSTA != (CLKCONCMD_32MHZ | OSC_32KHZ)); /* 等待時(shí)鐘生效*/ \
SLEEPCMD |= OSC_PD; /* 關(guān)閉 16MHz RC */ \
}
#define IO_IN 0 //輸入
#define IO_OUT 1 //輸出
uint8 ack; //應(yīng)答標(biāo)志位
uint8 PCA9554ledstate = 0; //所有LED當(dāng)前狀態(tài)
/******************************************************************************
* 函數(shù)名稱:QWait
*
* 功能描述:1us的延時(shí)
*
* 參 數(shù):無(wú)
*
* 返 回 值:無(wú)
*****************************************************************************/
void QWait()
{
asm(“NOP”);asm(“NOP”);
asm(“NOP”);asm(“NOP”);
asm(“NOP”);asm(“NOP”);
asm(“NOP”);asm(“NOP”);
asm(“NOP”);asm(“NOP”);
asm(“NOP”);
}
/******************************************************************************
* 函數(shù)名稱:Wait
*
* 功能描述:ms的延時(shí)
*
* 參 數(shù):ms - 延時(shí)時(shí)間
*
* 返 回 值:無(wú)
*****************************************************************************/
void Wait(unsigned int ms)
{
unsigned char g,k;
while(ms)
{
for(g=0;g《=167;g++)
{
for(k=0;k《=48;k++);
}
ms--;
}
}
/******************************************************************************
* 函數(shù)名稱:Start_I2c
*
* 功能描述:?jiǎn)?dòng)I2C總線,即發(fā)送I2C起始條件。
*
* 參 數(shù):無(wú)
*
* 返 回 值:無(wú)
*****************************************************************************/
void Start_I2c()
{
IO_DIR_PORT_PIN(1, 0, IO_OUT); //設(shè)置P1.0為輸出
IO_DIR_PORT_PIN(1, 1, IO_OUT); //設(shè)置P1.1為輸出
SDA=1; /*發(fā)送起始條件的數(shù)據(jù)信號(hào)*/
asm(“NOP”);
SCL=1;
QWait(); /*起始條件建立時(shí)間大于4.7us,延時(shí)*/
QWait();
QWait();
QWait();
QWait();
SDA=0; /*發(fā)送起始信號(hào)*/
QWait(); /* 起始條件鎖定時(shí)間大于4μs*/
QWait();
QWait();
QWait();
QWait();
SCL=0; /*鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù) */
asm(“NOP”);
asm(“NOP”);
}
/******************************************************************************
* 函數(shù)名稱:Stop_I2c
*
* 功能描述:結(jié)束I2C總線,即發(fā)送I2C結(jié)束條件。
*
* 參 數(shù):無(wú)
*
* 返 回 值:無(wú)
*****************************************************************************/
void Stop_I2c()
{
IO_DIR_PORT_PIN(1, 0, IO_OUT); //設(shè)置P1.0為輸出
IO_DIR_PORT_PIN(1, 1, IO_OUT); //設(shè)置P1.1為輸出
SDA=0; /*發(fā)送結(jié)束條件的數(shù)據(jù)信號(hào)*/
asm(“NOP”); /*發(fā)送結(jié)束條件的時(shí)鐘信號(hào)*/
SCL=1; /*結(jié)束條件建立時(shí)間大于4μs*/
QWait();
QWait();
QWait();
QWait();
QWait();
SDA=1; /*發(fā)送I2C總線結(jié)束信號(hào)*/
QWait();
QWait();
QWait();
QWait();
}
/******************************************************************************
* 函數(shù)名稱:SendByte
*
* 功能描述:將數(shù)據(jù)c發(fā)送出去,可以是地址,也可以是數(shù)據(jù),發(fā)完后等待應(yīng)答,并對(duì)
* 此狀態(tài)位進(jìn)行操作。(不應(yīng)答或非應(yīng)答都使ack=0 假)
* 發(fā)送數(shù)據(jù)正常,ack=1; ack=0表示被控器無(wú)應(yīng)答或損壞。
*
* 參 數(shù):c - 需發(fā)送的數(shù)據(jù)
*
* 返 回 值:無(wú)
*****************************************************************************/
void SendByte(uint8 c)
{
uint8 BitCnt;
IO_DIR_PORT_PIN(1, 0, IO_OUT); //設(shè)置P1.0為輸出
IO_DIR_PORT_PIN(1, 1, IO_OUT); //設(shè)置P1.1為輸出
for(BitCnt=0;BitCnt《8;BitCnt++) /*要傳送的數(shù)據(jù)長(zhǎng)度為8位*/
{
if((c《《BitCnt)&0x80)SDA=1; /*判斷發(fā)送位*/
else SDA=0;
asm(“NOP”);
SCL=1; /*置時(shí)鐘線為高,通知被控器開始接收數(shù)據(jù)位*/
QWait();
QWait(); /*保證時(shí)鐘高電平周期大于4μs*/
QWait();
QWait();
QWait();
SCL=0;
}
QWait();
QWait();
QWait();
SDA=1; /*8位發(fā)送完后釋放數(shù)據(jù)線,準(zhǔn)備接收應(yīng)答位*/
asm(“NOP”);
IO_DIR_PORT_PIN(1, 1, IO_IN);
SCL=1;
QWait();
QWait();
QWait();
QWait();
if(SDA==1)ack=0;
else ack=1; /*判斷是否接收到應(yīng)答信號(hào)*/
SCL=0;
QWait();
QWait();
IO_DIR_PORT_PIN(1, 1, IO_OUT);
}
/******************************************************************************
* 函數(shù)名稱:RcvByte
*
* 功能描述:用來(lái)接收從器件傳來(lái)的數(shù)據(jù),并判斷總線錯(cuò)誤(不發(fā)應(yīng)答信號(hào)),
* 發(fā)完后請(qǐng)用應(yīng)答函數(shù)。
*
* 參 數(shù):無(wú)
*
* 返 回 值:retc - 從器件傳來(lái)的數(shù)據(jù)
*****************************************************************************/
uint8 RcvByte()
{
uint8 retc;
uint8 BitCnt;
IO_DIR_PORT_PIN(1, 0, IO_OUT); //設(shè)置P1.0為輸出
IO_DIR_P
ORT_PIN(1, 1, IO_OUT); //設(shè)置P1.1為輸出
retc=0;
SDA=1; /*置數(shù)據(jù)線為輸入方式*/
IO_DIR_PORT_PIN(1, 1, IO_IN);
for(BitCnt=0;BitCnt《8;BitCnt++)
{
asm(“NOP”);
SCL=0; /*置時(shí)鐘線為低,準(zhǔn)備接收數(shù)據(jù)位*/
QWait();
QWait(); /*時(shí)鐘低電平周期大于4.7μs*/
QWait();
QWait();
QWait();
SCL=1; /*置時(shí)鐘線為高使數(shù)據(jù)線上數(shù)據(jù)有效*/
QWait();
QWait();
retc=retc《《1;
if(SDA==1)retc=retc+1; /*讀數(shù)據(jù)位,接收的數(shù)據(jù)位放入retc中 */
QWait();
QWait();
}
SCL=0;
QWait();
QWait();
IO_DIR_PORT_PIN(1, 1, IO_OUT);
return(retc);
}
/******************************************************************************
* 函數(shù)名稱:Ack_I2c
*
* 功能描述:主控器進(jìn)行應(yīng)答信號(hào),(可以是應(yīng)答或非應(yīng)答信號(hào))
*
*
* 參 數(shù):無(wú)
*
* 返 回 值:無(wú)
*****************************************************************************/
void Ack_I2c(uint8 a)
{
IO_DIR_PORT_PIN(1, 0, IO_OUT); //設(shè)置P1.0為輸出
IO_DIR_PORT_PIN(1, 1, IO_OUT); //設(shè)置P1.1為輸出
if(a==0)SDA=0; /*在此發(fā)出應(yīng)答或非應(yīng)答信號(hào) */
else SDA=1;
QWait();
//QWait();
//QWait();
SCL=1;
QWait();
QWait(); /*時(shí)鐘低電平周期大于4μs*/
QWait();
QWait();
QWait();
SCL=0; /*清時(shí)鐘線,鉗住I2C總線以便繼續(xù)接收*/
QWait();
//QWait();
}
/******************************************************************************
* 函數(shù)名稱:ISendByte
*
* 功能描述:從啟動(dòng)總線到發(fā)送地址,數(shù)據(jù),結(jié)束總線的全過(guò)程,從器件地址sla.
* 如果返回1表示操作成功,否則操作有誤。
*
*
* 參 數(shù):sla - 從器件地址
* c - 需發(fā)送的數(shù)據(jù)
*
* 返 回 值:0 -- 失敗
* 1 -- 成功
*****************************************************************************/
uint8 ISendByte(uint8 sla,uint8 c)
{
Start_I2c(); /*啟動(dòng)總線*/
SendByte(sla); /*發(fā)送器件地址*/
if(ack==0)return(0);
SendByte(c); /*發(fā)送數(shù)據(jù)*/
if(ack==0)return(0);
Stop_I2c(); /*結(jié)束總線*/
return(1);
}
/******************************************************************************
* 函數(shù)名稱:ISendStr
*
* 功能描述:從啟動(dòng)總線到發(fā)送地址,子地址,數(shù)據(jù),結(jié)束總線的全過(guò)程,從器件
* 地址sla,子地址suba,發(fā)送內(nèi)容是s指向的內(nèi)容,發(fā)送no個(gè)字節(jié)。
* 如果返回1表示操作成功,否則操作有誤。
*
*
* 參 數(shù):sla - 從器件地址
* suba - 從器件子地址
* *s - 數(shù)據(jù)
* no - 數(shù)據(jù)字節(jié)數(shù)目
*
* 返 回 值:0 -- 失敗
* 1 -- 成功
*
* 注 意:使用前必須已結(jié)束總線。
*****************************************************************************/
uint8 ISendStr(uint8 sla,uint8 suba,uint8 *s,uint8 no)
{
uint8 i;
Start_I2c(); /*啟動(dòng)總線*/
SendByte(sla); /*發(fā)送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*發(fā)送器件子地址*/
if(ack==0)return(0);
for(i=0;i《no;i++)
{
SendByte(*s); /*發(fā)送數(shù)據(jù)*/
if(ack==0)return(0);
s++;
}
Stop_I2c(); /*結(jié)束總線*/
return(1);
}
/******************************************************************************
* 函數(shù)名稱:IRcvByte
*
* 功能描述:從啟動(dòng)總線到發(fā)送地址,讀數(shù)據(jù),結(jié)束總線的全過(guò)程,從器件地
* 址sla,返回值在c. 如果返回1表示操作成功,否則操作有誤。
*
*
* 參 數(shù):sla - 從器件地址
* *c - 需發(fā)送的數(shù)據(jù)
*
* 返 回 值:0 -- 失敗
* 1 -- 成功
*
*注 意:使用前必須已結(jié)束總線。
*****************************************************************************/
uint8 IRcvByte(uint8 sla,uint8 *c)
{
Start_I2c(); /*啟動(dòng)總線*/
SendByte(sla+1); /*發(fā)送器件地址*/
//SendByte(sla);
if(ack==0)return(0);
*c=RcvByte(); /*讀取數(shù)據(jù)*/
Ack_I2c(1); /*發(fā)送非就答位*/
Stop_I2c(); /*結(jié)束總線*/
return(1);
}
/******************************************************************************
* 函數(shù)名稱:IRcvStr
*
* 功能描述:從啟動(dòng)總線到發(fā)送地址,子地址,讀數(shù)據(jù),結(jié)束總線的全過(guò)程,從器件
* 地址sla,子地址suba,讀出的內(nèi)容放入s指向的存儲(chǔ)區(qū),讀no個(gè)字節(jié)。
* 如果返回1表示操作成功,否則操作有誤。
*
*
* 參 數(shù):sla - 從器件地址
* suba - 從器件子地址
* *s - 數(shù)據(jù)
* no - 數(shù)據(jù)字節(jié)數(shù)目
*
* 返 回 值:0 -- 失敗
* 1 -- 成功
*
* 注 意:使用前必須已結(jié)束總線。
*****************************************************************************/
uint8 IRcvStr(uint8 sla,uint8 suba,uint8 *s,uint8 no)
{
Start_I2c(); /*啟動(dòng)總線*/
SendByte(sla); /*發(fā)送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*發(fā)送器件子地址*/
// if(ack==0)return(0);
// SendByte(sla+1);
if(ack==0)return(0);
while(no 》 0)
{
*s++ = RcvByte();
if(no 》 1) Ack_I2c(0); /*發(fā)送就答位*/
else Ack_I2c(1); /*發(fā)送非應(yīng)位*/
no--;
}
Stop_I2c();
/*結(jié)束總線*/
return(1);
}
/******************************************************************************
* 函數(shù)名稱:ctrPCA9554LED
*
* 功能描述:通過(guò)IIC總線控制PCA9554的輸出,進(jìn)而控制相應(yīng)的LED。
*
*
* 參 數(shù):LED - 所控制的LED
* operation - 開或關(guān)操作
*
* 返 回 值:無(wú)
*
*
* 注 意:PCA9554的地址為:0x40
*****************************************************************************/
void ctrPCA9554LED(uint8 led,uint8 operation)
{
uint8 output = 0x00;
uint8 *data = 0;
if(ISendStr(0x40,0x03,&output,1)) //配置PCA9554寄存器
{
switch(led)
{
case 0: //LED0控制
if (operation)
{
output = PCA9554ledstate & 0xfe;
}
else
{
output = PCA9554ledstate | 0x01;
}
break;
case 1: //LED1控制
if (operation)
{
output = PCA9554ledstate & 0xfd;
}
else
{
output = PCA9554ledstate | 0x02;
}
break;
case 2: //LED2控制
if (operation)
{
output = PCA9554ledstate & 0xf7;
}
else
{
output = PCA9554ledstate | 0x08;
}
break;
case 3: //LED3控制
if (operation)
{
output = PCA9554ledstate & 0xfb;
}
else
{
output = PCA9554ledstate | 0x04;
}
break;
case 4: //LED4控制
if (operation)
{
output = PCA9554ledstate & 0xdf;
}
else
{
output = PCA9554ledstate | 0x20;
}
break;
case 5: //LED5控制
if (operation)
{
output = PCA9554ledstate & 0xef;
}
else
{
output = PCA9554ledstate | 0x10;
}
break;
default:break;
}
if(ISendStr(0x40,0x01,&output,1)) //寫PCA9554輸出寄存器
{
if(IRcvByte(0x40,data)) //讀PCA9554輸出寄存器
{
PCA9554ledstate = *data;
}
}
}
}
/******************************************************************************
* 函數(shù)名稱:PCA9554ledInit
*
* 功能描述:初始化6個(gè)LED,即關(guān)閉所有的LED
*
* 參 數(shù):無(wú)
*
* 返 回 值:無(wú)
*
*****************************************************************************/
void PCA9554ledInit()
{
uint8 output = 0x00;
uint8 *data = 0;
if(ISendStr(0x40,0x03,&output,1)) //配置PCA9554寄存器
{
output = 0xbf;
if(ISendStr(0x40,0x01,&output,1)) //寫輸出寄存器
{
if(IRcvByte(0x40,data)) //讀輸出寄
存器
{
PCA9554ledstate = *data;
}
}
}
}
cc2530-按鍵控制時(shí)鐘啟動(dòng)與停止
2012-07-26 16:24:35| 分類: zigbee 2007 |舉報(bào)|字號(hào) 訂閱
/*功能:
1. 每隔0.065536秒(65536*32/32000000)切換LED顯示
2. S1控制計(jì)時(shí)器開始和暫停
*/
#include 《ioCC2530.h》
#define LED1 P1_0 //定義LED1為P1.0
#define S1 P0_1 //定義S1為P0.1
//函數(shù)實(shí)現(xiàn)
void INIT_LED(void)
{
P1SEL &= ~0x01; //設(shè)P1.0為普通I/O功能
P1DIR |= 0x01; //設(shè)P1.0為輸出方向
LED1 = 0; //將LED1點(diǎn)亮
}
void INIT_IO(void)
{
P0SEL &= ~0x02; //設(shè)P0.1(S1)為普通I/O功能
P0DIR &= ~0x02; //設(shè)P0.1(S1)為輸入
P0INP &= ~0x02; //設(shè)P0.1(S1)為上拉/下拉
P0IFG &= ~0x02; //設(shè)P0.1(S1)狀態(tài)標(biāo)志寄存器清零
P0IEN |= 0x02; //設(shè)P0.1(S1)中斷使能
P2INP |= 0x60; //P0、P1的下拉
EA = 1; //總中斷EA為中斷使能
IEN1 |= 0x20; //開P0中斷
IEN2 |= 0x10; //開P1中斷
PICTL |= 0x07; //P0、P1下降沿觸發(fā)
}
void INIT_Timer1()
{
T1CTL = 0x0C; //128分頻、停止運(yùn)行
T1STAT = 0x21; //通道0 本句可以取消
IRCON &= ~0x02;
}
//P0.1(S1)中斷處理函數(shù)
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void)
{
if((P0IFG&0x02) == 0x02) //P0.1(S1)狀態(tài)標(biāo)志寄存器觸發(fā) (P0IFG的值為0XFF,不解)
{
for(int i =0 ;i《8000 ;i++);
P0IFG &= ~0x02; //P0.1(S1)狀態(tài)標(biāo)志寄存器清零
if(T1CTL == 0x09)
T1CTL = 0x0C; //128分頻 暫停運(yùn)行
else
T1CTL = 0x09; //32分頻 自由運(yùn)行
}
}
void main( void )
{
INIT_IO();
INIT_LED();
INIT_Timer1();
LED1 = 1 ;
while(1)
{
if(IRCON &= 0x02) //約0.065536秒切換LED燈閃爍
{
LED1 = !LED1;
IRCON &= ~0x02 ;
}
}
}
dongfangnh
采納率:51% 10級(jí) 2013.12.14 檢舉
#ifndef ULTRASOUND_H
#define ULTRASOUND_H
#define uchar unsigned char
#define uint unsigned int
#define TRIG P1_3 //P1_2
#define ECHO P0_7 //P0_1
extern uchar RG;
extern uchar H1;
extern uchar L1;
extern uchar H2;
extern uchar L2;
extern uchar H3;
extern uchar L3;
extern uint data;
extern float distance;
extern uchar LoadRegBuf[4];
//void Delay(uint n);
void Delay_1us(uint microSecs);
void Delay_10us(uint n);
void Delay_1s(uint n);
void SysClkSet32M();
void Init_UltrasoundRanging();
void UltrasoundRanging(uchar *ulLoadBufPtr);
__interrupt void P0_ISR(void);
#endif
××××××××××××××××××××××××××××××××××
×××××××××
//×××××××××××Ultrasound.c****************************
#include 《ioCC2530.h》
#include “Ultrasound.h”
uchar RG;
uchar H1;
uchar L1;
uchar H2;
uchar L2;
uchar H3;
uchar L3;
uint data;
float distance;
uchar LoadRegBuf[4];//全局?jǐn)?shù)據(jù),用以存儲(chǔ)定時(shí)計(jì)數(shù)器的值。
void Delay_1us(uint microSecs)
{ while(microSecs--)
{ /* 32 NOPs == 1 usecs 因?yàn)檠訒r(shí)還有計(jì)算的緣故,用了31個(gè)nop*/
asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);
asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);
asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);
asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);
asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);
asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”); asm(“nop”);
asm(“nop”);
}
}
void Delay_10us(uint n)
{ /* 320NOPs == 10usecs 因?yàn)檠訒r(shí)還有計(jì)算的緣故,用了310個(gè)nop*/
uint tt,yy;
for(tt = 0;tt《n;tt++);
for(yy = 310;yy》0;yy--);
{asm(“NOP”);}
}
void Delay_1s(uint n)
{ uint ulloop=1000;
uint tt;
for(tt =n ;tt》0;tt--);
for( ulloop=1000;ulloop》0;ulloop--)
{
Delay_10us(100);
}
}
void SysClkSet32M()
{
CLKCONCMD &= ~0x40; //設(shè)置系統(tǒng)時(shí)鐘源為32MHZ晶振
while(CLKCONSTA & 0x40); //等待晶振穩(wěn)定
CLKCONCMD &= ~0x47; //設(shè)置系統(tǒng)主時(shí)鐘頻率為32MHZ
//此時(shí)的CLKCONSTA為0x88。即普通時(shí)鐘和定時(shí)器時(shí)鐘都是32M。
}
void Init_UltrasoundRanging()
{
P1DIR = 0x08; //0為輸入1為輸出 00001000 設(shè)置TRIG P1_3為輸出模式
TRIG=0; //將TRIG 設(shè)置為低電平
P0INP &= ~0x80; //有上拉、下拉 有初始化的左右
P0IEN |= 0x80; //P0_7 中斷使能
PICTL |= 0x01; //設(shè)置P0_7引腳,下降沿觸發(fā)中斷
IEN1 |= 0x20; // P0IE = 1;
P0IFG = 0;
}
void UltrasoundRanging(uchar *ulLoadBufPtr)
{
SysClkSet32M();
Init_UltrasoundRanging();
EA = 0;
TRIG =1;
Delay_1us(10); //需要延時(shí)10us以上的高電平
TRIG =0;
T1CNTL=0;
T1CNTH=0;
while(!ECHO);
T1CTL = 0x09; //通道0,中斷有效,32分頻;自動(dòng)重裝模式(0x0000-》0xffff);
L1=T1CNTL;
H1=T1CNTH;
*ulLoadBufPtr++=T1CNTL;
*ulLoadBufPtr++=T1CNTH;
EA = 1;
Delay_10us(60000);
Delay_10us(60000);
}
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void)
{
EA=0;
T1CTL = 0x00;
LoadRegBuf[2]=T1CNTL;
LoadRegBuf[3]=T1CNTH;
L2=T1CNTL;
H2=T1CNTH;
if(P0IFG&0x080) //外部ECHO反饋信號(hào)
{
P0IFG = 0;
}
T1CTL = 0x09;
T1CNTL=0;
T1CNTH=0;
P0IF = 0; //清中斷標(biāo)志
EA=1;
}
××××××××××××××××××××××××××××××××××××××
#include 《ioCC2530.h》
#include “Ultrasound.h”
void main(void)
{
while(1)
{
UltrasoundRanging(LoadRegBuf);
Delay_1s(1);
data=256*H2+L2-L1-256*H1;
distance=(float)data*340/10000;
Delay
_1s(2);
};
}
評(píng)論