Po napísaní knihy "Zigbee Journey (9)" 3. marca autor pôvodne plánoval okamžite začať písať malý experiment o "systéme monitorovania teploty" ako súhrn série rozptýlených poznatkov predtým. Zároveň som si však uvedomil, že hoci bol každý z predchádzajúcich malých experimentov podrobne opísaný, normatívna a štrukturálna povaha jeho kódu by sa dala označiť za neznesiteľnú. Keďže ide o zhrnutie, mali by sme postupovať na pôvodnom základe, namiesto mechanického skladania predchádzajúcich drobných poznatkov. Preto som svoj pôvodný plán odložil, venoval čas naučeniu sa všeobecných techník embedded vývoja a napísal dve esejeŠpecifikácia embedded C51 programovania" a "Hierarchia štruktúry vloženého projektového kódu》。 Tento denník nie je len zhrnutím Zigbeeho prvej cesty, ale zahŕňa aj autorove skúsenosti s učením z posledných dní, s nádejou, že bude užitočný pre začiatočníkov Zigbee.
Celý text je usporiadaný podľa základného procesu vývoja softvéru: analýza požiadaviek, návrh osnovy, detailný návrh, implementácia kódovania a testovanie.
1. Analýza dopytuPo diskusii medzi "zákazníkom" a "vývojárom" bol určený nasledujúci popis systémovej funkcie:
… Aktuálna izbová teplota je zachytávaná uzlami založenými na CC2430 a jej teplotné hodnoty je možné monitorovať cez PC
… Samotný uzol CC2430 musí mať určitú mieru stability a môže sa automaticky vrátiť do normálneho stavu
… Vzorkovací interval a správu napájania uzla môže ovládať PC
2. Návrh osnovyPodľa vyššie uvedenej analýzy požiadaviek môžeme systém rozdeliť na dva moduly:Uzol CC2430aPC。
[CC2430 uzol]
… Externé parametre je možné pravidelne zbierať a posielať PC
… Automatický reset pri vypnutí stroja
… Príkazy z PC je možné prijímať a spracovávať podľa toho: zmeniť interval vzorkovania/správu napájania
[PC]
… C stroj prijíma a zobrazuje dáta cez nástroj sériového portu
… Inštrukcie môžu byť posielané mikrokontroléru cez nástroj sériového portu na riadenie rýchlosti vzorkovania a správy napájania
3. Detailný dizajn(1) Štruktúra kódu
Vrstvenie štruktúry kódu tohto systému bolo opísané v eseji "Hierarchia štruktúry vloženého projektového kódu", a kópia je nasledovná:
(1) Vrstva hardvérovej abstrakcie
[ioCC2430.h] (Systém zahrnutý):Všetky SFR a prerušovacie vektory CC2430 sú definované
[hal.h] Obsahuje spoločné definície typov, spoločné makrá priraďovania a spoločnú konfiguráciu zdrojov CC2430 na čipe (I/O, sériová komunikácia, ADC, časovač, správa napájania atď.)
(2) Funkčná modulová vrstva
[module.h] definuje zdroje na čipe (časovače, I/O), expanzné moduly mimo čipu (LED) a deklarácie súvisiacich funkcií
[module.cImplementujte inicializáciu každého modulu (LED).
(3) Aplikačná vrstva
[main.cPozrite sa na hal.h, ioCC2430.h a module.h na dosiahnutie špecifických požiadaviek aplikácie, ako je zachytenie teploty, komunikácia s PC a vypnutie a reset
(2) Implementačné metódy každého modulu
Podľa modulov rozdelených podľa osnovného návrhu možno vnútorný systém rozdeliť na dva hlavné moduly:Uzol CC2430aPC。
Keďže na PC sú nástroje na komunikáciu so sériovým portom, jeho funkcie môžu spĺňať požiadavky, takže túto časť PC nemusíme robiť a nie je potrebné ju analyzovať. Poďme sa porozprávať o sekcii CC2430 nižšie
Implementačná metóda každej podfunkcie bodu:
… Použite prerušenie pretečenia počítania časovača na spustenie časovaného vzorkovania
… Režim UART0 so sériovým portom prenáša teplotné údaje do PC
… Vstavaný watchdog obvod CC2430 sa používa na realizáciu funkcie automatického resetu systému
… Sériový port sa používa na prijímanie prerušení na zachytenie a reakciu na riadiace príkazy z PC
1) Ak je prijatý@Znak je riadiaci príkaz vzorkovacieho intervalu, nasledovaný číslom označujúcim vzorkovací interval: 0-0,5s, 1-1s, 2-2s
如:@0,表示每隔0.5秒采样一次。
2) Ak je prijatý$ Znak je príkaz na ovládanie spánku, nasledovaný číslom označujúcim režim napájania
Napríklad: 3 doláre, čo znamená zapnúť systém do režimu napájania 3.
(3) Diagram toku programu
- Schéma toku magisterského programu
- Časovač 1 Diagram prerušenia prerušenia programu
- Diagram postupu prerušenia príjmu sériového portu
4. Implementácia kódovania(1) Vrstva hardvérovej abstrakcie
Vrstva hardvérovej abstrakcie zahŕňa ioCC2430.h a hal.h. Keďže prvý systém je súčasťou tohto systému, nebude uvedený v zozname.
Nasleduje zoznam všetkého obsahu hal.h (keďže tento súbor je príliš dlhý a vyzerá nepríjemne, ukážem ho v moduloch):
- hlava
- I/O porty
- Prerušené
- Sériový port
- Správa napájania a hodín
- Časovač
- Strážny pes
- ADC
[url=]
[/url]
/***********************************************************
*Názov súboru: hal.h
*Autor: hustlzp
*Dátum: 8. marec 2011
*Edícia: 1.1
*Popis funkcie: Vrstva hardvérovej abstrakcie
*Upravené záznamy:
***********************************************************/
#ifndef HAL_H
#defineHAL_H
#include
/***********************************************************
Bežné definície typov
***********************************************************/
Typedef Unsignedchar BYTE;
Typedef Unsignedint WORD;
Typedef Unsigneddlhý DWORD;
/***********************************************************
Bežne používané definície makier
***********************************************************/
//O 8 miest vyššie
#defineHIGH_BYTE(a) ((BYTE) (((WORD)(a)) >> 8))
//O 8 miest nižšie
#defineLOW_BYTE(a) ((BYTE) ((WORD)(a)))
//Priradenie
#defineSET_WORD(regH,regL,word)
robiť{
(regH)=HIGH_BYTE(slovo);
(regL)=LOW_BYTE(slovo);
}zatiaľ čo(0)
[url=] [/url]
[url=] [/url]
/***********************************************************
I/O porty
***********************************************************/
/*Konfigurácia smeru vstupno-výstupného portu
-----------------------------------------*/
#defineIO_DIR_PORT_PIN(port, pin, réžia)
robiť{
ak(dir == IO_OUT)
P##port##DIR |= (0x01<<(pin));
else
P##port##DIR &= ~(0x01<<(pin));
}zatiaľ čo(0)
//Hodnota parametra dir je:
#defineIO_IN 0
#defineIO_OUT 1
/*Nastavte vstupný režim I/O portu
-----------------------------------------*/
#defineIO_IMODE_PORT_PIN(port, pin, imode)
robiť{
ak(imode == IO_IMODE_TRI)
P##port##INP |= (0x01<<(pin));
else
P##port##INP &= ~(0x01<<(pin));
}zatiaľ čo (0)
#define IO_PUD_PORT(portské, pud)
do {
ak (pud == IO_PULLDOWN)
P2INP |= (0x01 << (port+5));
else
P2INP &= ~(0x01 << (port+5));
} zatiaľ čo (0)
Hodnota parametra PUD je:
#define IO_PULLUP 0 // Vytiahni sa
#define IO_PULLDOWN 1 // Stiahnuť dole
/*配置I/O口的功能
-----------------------------------------*/
#define IO_FUNC_PORT_PIN(port, pin, func)
do {
if((port == 2) && (pin == 3)){
ak (func) {
P2SEL |= 0x02;
} inak {
P2SEL &= ~0x02;
}
}
inak ak((port == 2) && (pin == 4)){
ak (func) {
P2SEL |= 0x04;
} inak {
P2SEL &= ~0x04;
}
}
else{
ak (func) {
P##port##SEL |= (0x01<<(pin));
} inak {
P##port##SEL &= ~(0x01<<(pin));
}
}
} zatiaľ čo (0)
Hodnota parametra func je:
#define IO_FUNC_GIO 0 // Všeobecné I/O
#define IO_FUNC_PERIPH 1 // Periférne I/O
Konfigurácia polohy periférneho I/O
#define IO_PER_LOC_TIMER1_AT_PORT0_PIN234() do { PERCFG = (PERCFG&~0x40)|0x00; } zatiaľ čo (0)
#define IO_PER_LOC_TIMER1_AT_PORT1_PIN012() do { PERCFG = (PERCFG&~0x40)|0x40; } zatiaľ čo (0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN34() do { PERCFG = (PERCFG&~0x20)|0x00; } zatiaľ čo (0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN67() do { PERCFG = (PERCFG&~0x20)|0x20; } zatiaľ čo (0)
#define IO_PER_LOC_TIMER4_AT_PORT1_PIN01() do { PERCFG = (PERCFG&~0x10)|0x00; } zatiaľ čo (0)
#define IO_PER_LOC_TIMER4_AT_PORT2_PIN03() do { PERCFG = (PERCFG&~0x10)|0x10; } zatiaľ čo (0)
#define IO_PER_LOC_SPI1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x08)|0x00; } zatiaľ čo (0)
#define IO_PER_LOC_SPI1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x08)|0x08; } zatiaľ čo (0)
#define IO_PER_LOC_SPI0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x00; } zatiaľ čo (0)
#define IO_PER_LOC_SPI0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x04; } zatiaľ čo (0)
#define IO_PER_LOC_UART1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x02)|0x00; } zatiaľ čo (0)
#define IO_PER_LOC_UART1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x02)|0x02; } zatiaľ čo (0)
#define IO_PER_LOC_UART0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x00; } zatiaľ čo (0)
#define IO_PER_LOC_UART0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x01; } zatiaľ čo (0)
//Hodnota parametra imode je:
#defineIO_IMODE_PUD 0 //Ťah hore/ťah dole
#defineIO_IMODE_TRI 1 //Tri štáty[url=] [/url]
[url=] [/url]
/***********************************************************
Prerušené
***********************************************************/
//Pre prerušenia zapnutia/vypnutia
#defineINT_ON 1
#defineINT_OFF 0
//Používa sa na umiestňovanie/vymazávanie príznakov prerušenia
#defineINT_SET 1
#defineINT_CLR 0
//Globálne nastavenia prerušenia
#defineINT_GLOBAL_ENABLE(on) EA=(!! zapnuté)
//Definujte prerušenie
#defineINUM_RFERR 0
#defineINUM_ADC 1
#defineINUM_URX0 2
#defineINUM_URX1 3
#defineINUM_ENC 4
#defineINUM_ST 5
#defineINUM_P2INT 6
#defineINUM_UTX0 7
#defineINUM_DMA 8
#defineINUM_T1 9
#defineINUM_T2 10
#defineINUM_T3 11
#defineINUM_T4 12
#defineINUM_P0INT 13
#defineINUM_UTX1 14
#defineINUM_P1INT 15
#defineINUM_RF 16
#defineINUM_WDT 17
/*Povolené prerušenia
-----------------------------------------*/
#defineINT_ENABLE(inum, zapnuté)
robiť{
ak (inum==INUM_RFERR) { RFERRIE = zapnuté; }
else ak(inum==INUM_ADC) { ADCIE = zapnuté; }
else ak(inum==INUM_URX0) { URX0IE = zapnuté; }
else ak(inum==INUM_URX1) { URX1IE = zapnuté; }
else ak(inum==INUM_ENC) { ENCIE = zapnuté; }
else ak(inum==INUM_ST) { STIE = zapnuté; }
else ak(inum==INUM_P2INT) { (zapnuté) ? (IEN2 |=0x02) : (IEN2 &= ~0x02); }
else ak(inum==INUM_UTX0) { (zapnuté) ? (IEN2 |=0x04) : (IEN2 &= ~0x04); }
else ak(inum==INUM_DMA) { DMAIE = zapnuté; }
else ak(inum==INUM_T1) { T1IE = zapnuté; }
else ak(inum==INUM_T2) { T2IE = on; }
else ak(inum==INUM_T3) { T3IE = on; }
else ak(inum==INUM_T4) { T4IE = on; }
else ak(inum==INUM_P0INT) { P0IE = zapnuté; }
else ak(inum==INUM_UTX1) { (zapnuté) ? (IEN2 |=0x08) : (IEN2 &= ~0x08); }
else ak(inum==INUM_P1INT) { (zapnuté) ? (IEN2 |=0x10) : (IEN2 &= ~0x10); }
else ak(inum==INUM_RF) { (zapnuté) ? (IEN2 |=0x01) : (IEN2 &= ~0x01); }
else ak(inum==INUM_WDT) { (zapnuté) ? (IEN2 |=0x20) : (IEN2 &= ~0x20); }
}zatiaľ čo (0)
/*Nastavte prioritu výpadku
-----------------------------------------*/
#defineINT_PRIORITY(skupina, pri)
robiť{
ak(pri ==0) { IP0 &= ~skupina; IP1 &= ~skupina; }
ak(pri ==1) { IP0 |= skupina; IP1 &= ~skupina; }
ak(pri ==2) { IP0 &= ~skupina; IP1 |= skupina; }
ak(pri ==3) { IP0 |= skupina; IP1 |= skupina; }
}zatiaľ čo (0)
//Hodnota parametra pri je: 0/1/2/3 (najvyššia priorita)
//Hodnota skupiny parametrov je:
#defineRFERR_RF_DMA 0x01//Skupina IP0
#defineADC_P2INT_T1 0x02//Skupina IP1
#defineURX0_UTX0_T2 0x04//Skupina IP2
#defineURX1_UTX1_T3 0x08//Skupina IP3
#defineENC_P1INT_T4 0x10//Skupina IP4
#defineST_WDT_P0INT 0x20//Skupina IP5
/*Získaj príznak prerušenia
-----------------------------------------*/
#defineINT_GETFLAG(inum) (
(inum==INUM_RFERR) ? ODPOVEĎ :
(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
)
/*Nastavte príznak prerušenia
-----------------------------------------*/
#defineINT_SETFLAG(inum, f)
robiť{
ak (inum==INUM_RFERR) { RFERRIF= f; }
else ak(inum==INUM_ADC) { ADCIF = f; }
else ak(inum==INUM_URX0) { URX0IF = f; }
else ak(inum==INUM_URX1) { URX1IF = f; }
else ak(inum==INUM_ENC) { ENCIF_1 = ENCIF_0 = f; }
else ak(inum==INUM_ST) { STIF = f; }
else ak(inum==INUM_P2INT) { P2IF = f; }
else ak(inum==INUM_UTX0) { UTX0IF= f; }
else ak(inum==INUM_DMA) { DMAIF = f; }
else ak(inum==INUM_T1) { T1IF = f; }
else ak(inum==INUM_T2) { T2IF = f; }
else ak(inum==INUM_T3) { T3IF = f; }
else ak(inum==INUM_T4) { T4IF = f; }
else ak(inum==INUM_P0INT) { P0IF = f; }
else ak(inum==INUM_UTX1) { UTX1IF= f; }
else ak(inum==INUM_P1INT) { P1IF = f; }
else ak(inum==INUM_RF) { (f) ? (S1CON |=0x03) : (S1CON &= ~0x03); }
else ak(inum==INUM_WDT) { WDTIF = f; }
}zatiaľ čo (0)
[url=] [/url]
[url=] [/url]
/***********************************************************
Sériový port
***********************************************************/
//Hodnota BAUD_E zodpovedá rôznym rýchlostiam prenosu
#defineBAUD_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 )
//Hodnota BAUD_M zodpovedá rôznym rýchlostiam prenosu
#defineBAUD_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)
/*Konfigurácia sériového portu v režime UART
-----------------------------------------*/
#defineUART_SETUP(uart, receiveEnable, baudRate, options)
robiť{
ak((uart) ==0){
ak(PERCFG &0x01){
P1SEL |=0x30;
}else{
P0SEL |=0x0C;
}
}
else{
ak(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 |= prijímaťUmožniť;
U##uart##UCR |= ((options) |0x80);
}zatiaľ čo(0)
//Hodnota parametra ReceiveEnable:
#defineUART_RECEIVE_ENABLE 0x40 //Získanie povolenia
#defineUART_RECEIVE_DISABLE 0x00
//Hodnota parametrových možností:
#defineFLOW_CONTROL_ENABLE 0x40 //Riadenie toku
#defineFLOW_CONTROL_DISABLE 0x00
#defineEVEN_PARITY 0x20 //Príležitostné overovanie
#defineODD_PARITY 0x00 //Zvláštne overenie
#defineNINE_BIT_TRANSFER 0x10 //9-bajtový prenos
#defineEIGHT_BIT_TRANSFER 0x00 //8-bajtový prenos
#definePARITY_ENABLE 0x08 //Umožnenie kontroly parity
#definePARITY_DISABLE 0x00
#defineTWO_STOP_BITS 0x04 //Poloha 2-polohového registra
#defineONE_STOP_BITS 0x00 //Poloha 1 stop
#defineHIGH_STOP 0x02 //Stopová úroveň je vysoká
#defineLOW_STOP 0x00 //Poloha zastavenia je nízka
#defineHIGH_START 0x01 //Počiatočná úroveň bitu je vysoká
#defineLOW_START 0x00 //Počiatočná úroveň bitu je nízka
//Sériový port posiela postavy
#defineUART_SEND(uart,data)
robiť{
zatiaľ čo(U##uart##CSR &0x01);
U##uart##DBUF = dáta;
}zatiaľ čo (0)
#defineUART0_SEND(data) UART_SEND(0,data)
#defineUART1_SEND(data) UART_SEND(1,data)
//Sériový port prijíma znaky
#defineUART_RECEIVE(uart,data)
robiť{
zatiaľ čo(! (U##uart##CSR&0x04));
data=U##uart##DBUF;
}zatiaľ čo(0)
#defineUART0_RECEIVE(data) UART_RECEIVE(0,data)
#defineUART1_RECEIVE(data) UART_RECEIVE(1,data)
[url=] [/url]
[url=] [/url]
/***********************************************************
Správa napájania a hodín
***********************************************************/
//Zober si hodinový crossover
#defineCLKSPD (CLKCON & 0x07)
//Nastavte režim napájania
#defineSET_POWER_MODE(mode)
robiť{
ak(mód ==0) { SPAŤ &= ~0x03; }
else ak(mód ==3) { SLEEP |=0x03; }
else{ SPAŤ &= ~0x03; SLEEP |= režim; }
PCON |=0x01;
ASM("NOP");
}zatiaľ čo (0)
//Režim parametra je nastavený na nasledujúce hodnoty:
#definePOWER_MODE_0 0x00
#definePOWER_MODE_1 0x01
#definePOWER_MODE_2 0x02
#definePOWER_MODE_3 0x03
//Používa sa na detekciu stability vysokofrekvenčných RC oscilátorov
#defineHIGH_FREQUENCY_RC_OSC_STABLE (SLEEP & 0x20)
//Používa sa na detekciu stabilného stavu kryštálového oscilátora
#defineXOSC_STABLE (SPÁNOK & 0x40)
//Získajte hodnotu frekvencie tiknutí časovača
#defineTICKSPD ((CLKCON & 0x38) >> 3)
//Nastavte frekvenciu hlavného hodinového signálu
#defineSET_MAIN_CLOCK_SOURCE(zdroj)
robiť{
ak(zdroj) {
CLKCON |=0x40;
zatiaľ čo(! HIGH_FREQUENCY_RC_OSC_STABLE);
ak(TICKSPD ==0){
CLKCON |=0x08;
}
SPAK |=0x04;
}
else{
SPAJ &= ~0x04;
zatiaľ čo(! XOSC_STABLE);
ASM("NOP");
CLKCON &= ~0x47;
SPAK |=0x04;
}
}zatiaľ čo (0)
//Hodnota zdroja parametra je:
#defineKRYŠTÁLOVÁ 0x00 //Kryštálový oscilátor
#defineRC 0x01 //RC oscilátor
[url=] [/url]
[url=] [/url]
/***********************************************************
Časovač 1
***********************************************************/
//Časovač 1 umožňuje prerušenie pretečenia počítania
#defineTIMER1_ENABLE_OVERFLOW_INT(val)
(TIMIF = (val) ? ČASOVANIE |0x40: TIMIF & ~0x40)
//Nastavte príznak prerušenia pretečenia pre časovač 1
#defineTIMER1_OVERFLOW_INT_SETFLAG(f) (T1CTL= ((T1CTL & (~0x10)) | f))
//Začína časovač 1
#defineTIMER1_RUN(hodnota) (T1CTL = (hodnota) ? T1CTL|0x02 : T1CTL&~0x03)
//Nastavte časové rozdelenie pre časovač
#defineSET_TIMER_TICK(value) do{ CLKCON = ((CLKCON & (~0x38)) | value); } while(0)
//Hodnota hodnoty je:
#defineTIMER1_TICK_32M 0x00 //32MHz
#defineTIMER1_TICK_16M 0x08 //16MHz, predvolená hodnota pre reset systému
#defineTIMER1_TICK_8M 0x10 //8MHz
#defineTIMER1_TICK_4M 0x18 //4MHz
#defineTIMER1_TICK_2M 0x20 //2MHz
#defineTIMER1_TICK_1M 0x28 //1MHz
#defineTIMER1_TICK_500k 0x30 //500kHz
#defineTIMER1_TICK_250k 0x38 //250kHz
//Nastavte TICK crossover na časovač 1
#defineSET_TIMER1_TICKDIV(hodnota)
robiť{
T1CTL &= ~0x0c;
T1CTL |= hodnota;
}zatiaľ čo (0)
//kde hodnota je:
#defineTIMER1_TICKDIV_1 0x00 //1 divízia
#defineTIMER1_TICKDIV_8 0x04 //8-cestná frekvencia
#defineTIMER1_TICKDIV_32 0x08
#defineTIMER1_TICKDIV_128 0x0c
//Nastavte časovač pretečenia
#defineSET_TIMER1_PERIOD(hodnota)
robiť{
T1CC0H = HIGH_BYTE(hodnota);
T1CC0L = LOW_BYTE(hodnota);
}zatiaľ čo (0)
//Nastavte prevádzkový režim Timer 1
#defineSET_TIMER1_MODE(mode)
robiť{
T1CTL = ((T1CTL & (~0x03)) | režim);
}zatiaľ čo (0)
//Hodnota módu je:
#defineTIMER1_MODE_STOP 0x00
#defineTIMER1_MODE_FREE 0x01
#defineTIMER1_MODE_MODULE 0x02
#defineTIMER1_MODE_UPDOWN 0x03
[url=] [/url]
[url=] [/url]
/***********************************************************
Strážny pes
***********************************************************/
//Nastavte pretečenie pre watchdog časovač
#defineWDT_SET_TIMEOUT_PERIOD(timeout)
robiť{ WDCTL &= ~0x03; WDCTL |= oddychový čas; }zatiaľ čo (0)
//Hodnota časového limitu parametra je:
#defineSEC_1 0x00 //po 1 sekunde
#defineM_SEC_250 0x01 //po 250 ms
#defineM_SEC_15 0x02 //Po 15 ms
#defineM_SEC_2 0x03 //Po 2 ms
//Postupy kŕmenia psov
#defineWDT_RESET() do {
WDCTL = (WDCTL & ~0xF0) |0xA0;
WDCTL = (WDCTL & ~0xF0) |0x50;
} zatiaľ čo (0)
//Spustiť/zastaviť watchdog časovač
#defineWDT_ENABLE() WDCTL |= 0x08
#defineWDT_DISABLE() WDCTL &= ~0x08
[url=] [/url]
[url=] [/url]
/***********************************************************
ADC
***********************************************************/
//Konfigurácia jedného ADC
#defineADC_SINGLE_CONVERSION(nastavenia)
robiť{ ADCCON3 = nastavenia; }zatiaľ čo(0)
//Nastavenie parametrov pozostáva z nasledujúcich kombinácií:
//Referenčné napätie
#defineADC_REF_1_25_V 0x00 //Vnútorné referenčné napätie 1,25 V
#defineADC_REF_P0_7 0x40 //Externé referenčné napätie na pine AIN7
#defineADC_REF_AVDD 0x80 //AVDD_SOC Odznaky
#defineADC_REF_P0_6_P0_7 0xC0 //AIN6-AIN7 Externé referenčné napätie pre diferenciálne vstupy
//Vzorkovacia frekvencia
#defineADC_8_BIT 0x00 //8. miesto
#defineADC_10_BIT 0x10 //10. miesto
#defineADC_12_BIT 0x20 //12. miesto
#defineADC_14_BIT 0x30 //14. miesto
//Vstup do kanála
#defineADC_AIN0 0x00 //P0_0
#defineADC_AIN1 0x01 //P0_1
#defineADC_AIN2 0x02 //P0_2
#defineADC_AIN3 0x03 //P0_3
#defineADC_AIN4 0x04 //P0_4
#defineADC_AIN5 0x05 //P0_5
#defineADC_AIN6 0x06 //P0_6
#defineADC_AIN7 0x07 //P0_7
#defineADC_GND 0x0C //Pôda
#defineADC_TEMP_SENS 0x0E //Teplotný senzor v čipe
#defineADC_VDD_3 0x0F //VDD/3
Konverzia ADC je dokončená
#define ADC_SAMPLE_READY() (ADCCON1 & 0x80)
#endif
//启动ADC转化
#define ADC_START()
do { ADCCON1 |= 0x40; } zatiaľ čo (0)//Vyberte režim spúšte ADC ako manuálny (t. j. ADC_SAMPLE_READY)
#defineADC_STOP()
robiť{ ADCCON1 |=0x30; }zatiaľ čo (0)[url=] [/url]
(2) Funkčná modulová vrstva
[url=] [/url]
/***********************************************************
*Názov súboru: module.h
*Autor: hustlzp
*Dátum: 6. marec 2011
*Verzia: 1.0
*Popis funkcie: Súbor hlavičky funkčnej modulovej vrstvy
*Zoznam funkcií: void led_init()
void timer1_init()
void uart0_init(void);
void Uart0SendString(neznamienkový znak *s);
Float adc_start(prázdno)
void get_temperature(neoznačený char *výstup, float temp);
void watchdog_init(void);
*Upravené záznamy:
***********************************************************/
#ifndef MODULE_H
#defineMODULE_H
#include"hal.h"
/***********************************************************
LED
***********************************************************/
//Definujte LED piny
#defineLED1 P1_0
#defineLED2 P1_1
#defineLED3 P1_2
#defineLED4 P1_3
//LED svetlo a vypnuté
#defineLED_OFF 1
#defineLED_ON 0
//Inicializácia LED
prázdnotaled_init(prázdnota);
/***********************************************************
timer1
***********************************************************/
//Používa sa na nastavenie hodnoty obdobia pretečenia pre časovač
#defineTIMER1_OVF_2SEC 0xF424 //2s
#defineTIMER1_OVF_1SEC 0x7A12 //1
#defineTIMER1_OVF_dot5SEC 0x3D09 //0,5 s
//Časovač 1 inicializuje
prázdnota timer1_init(prázdnota);
/***********************************************************
UART0
***********************************************************/
//Inicializácia UART0
prázdnota uart0_init(prázdnota);
//Sériový portový prenosový reťazec
prázdnota Uart0SendString(unsignedchar*s);
/***********************************************************
ADC-14
***********************************************************/
//Používa sa na prevod dát získaných ADC na teplotu Celzia
#defineADC_TO_CELSIUS(teplota) (teplota * 0,06229 - 311,43)
//Začnite konverziu ADC
Plavákadc_start(prázdnota);
//Prestavba
prázdnota get_temperature(nepodpísanéchar*výstup,Plaváktemp);
/***********************************************************
WatchDog
***********************************************************/
//Inicializácia watchdog
prázdnota watchdog_init(prázdnota);
#endif
[url=] [/url]
[url=] [/url]
/***********************************************************
*Názov súboru: module.c
*Autor: hustlzp
*Dátum: 2011/3/11
*Verzia: 1.0
*Popis funkcie: Zdrojový súbor funkčnej vrstvy modulu
*Zoznam funkcií: (vynechané)
*Upravené záznamy:
***********************************************************/
#include"module.h"
/***********************************************************
*Názov funkcie: led_init
*Funkčná funkcia: LED inicializácia
*Vstupné parametre: Žiadne
*Exportné parametre: Žiadne
***********************************************************/
prázdnotaled_init(prázdnota)
{
//Nastavte P1.0, P1.1, P1.2 a P1.3 ako všeobecné I/O porty
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);
//Nastavte výstupy P1.0, P1.1, P1.2 a 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;
}
/***********************************************************
*Názov funkcie: timer1_init
* Funkčná funkcia: Inicializácia časovača 1
*Vstupné parametre: Žiadne
*Exportné parametre: Žiadne
***********************************************************/
prázdnotatimer1_init(prázdnota)
{
INT_GLOBAL_ENABLE(INT_ON); //Otvorte globálne prerušenie
INT_ENABLE(INUM_T1, INT_ON); //Otvorené T1 prerušenie
TIMER1_ENABLE_OVERFLOW_INT(INT_ON); //Prerušenie pretečenia počítania otvoreného T1
SET_TIMER_TICK(TIMER1_TICK_4M); //Nastavte časovač TICK na 4MHz
SET_TIMER1_PERIOD(TIMER1_OVF_2SEC); //Nastavte počítacie obdobie pre T1 na 2
SET_TIMER1_TICKDIV(TIMER1_TICKDIV_128); //Nastav časový crossover na T1 na 128
SET_TIMER1_MODE(TIMER1_MODE_MODULE); //Nastavte bežiaci režim T1 na modul
}
/***********************************************************
*Názov funkcie: uart0_init
*Funkčná funkcia: Inicializácia sériového portu UART0
*Vstupné parametre: Žiadne
*Exportné parametre: Žiadne
***********************************************************/
prázdnotauart0_init(prázdnota)
{
//Vyberte lokalitu UART
IO_PER_LOC_UART0_AT_PORT0_PIN2345();
//Konfigurácia UART: povolený príjem, 115200bps, jednobitový stop bit, žiadna parita
UART_SETUP(0, UART_RECEIVE_ENABLE,115200, ONE_STOP_BITS | PARITY_DISABLE);
//Otvorte úplné prerušenie
INT_GLOBAL_ENABLE(INT_ON);
//Otvorte sériový port 0 na prijatie prerušení
INT_ENABLE(INUM_URX0, INT_ON);
}
/***********************************************************
*Názov funkcie: Uart0SendString
* Funkčná funkcia: Inicializácia časovača 1
*Vstupný parameter: neoznačený znak *s
Špagát, ktorý chceš poslať
*Exportné parametre: Žiadne
***********************************************************/
prázdnotaUart0SendString(unsignedchar*s)
{
zatiaľ čo(*s !=0)
UART0_SEND(*s++);
}
/***********************************************************
*Názov funkcie: adc_start
*Funkčná funkcia: Spustiť konverziu ADC
*Vstupné parametre: Žiadne
*Exportný parameter: float
Teplotná hodnota v tablete
***********************************************************/
Plavákadc_start(prázdnota)
{
nepodpísanéintteplota;
//Referenčné napätie je 1,25V, presnosť vzorkovania je 14 bitov a cieľom konverzie je teplotný senzor na čipe
ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);
ADC_STOP(); //Nastavte metódu spúšte pre konverziu ADC na manuálnu
ADC_START(); //Začnite konverziu ADC
zatiaľ čo(! ADC_SAMPLE_READY()); //Počkajte, kým sa konverzia dokončí
temp = ADCL >>2; //Uložte výsledky konverzie na teplotu
temp |= (((nepodpísanéint) ADCH) <<6);
návratADC_TO_CELSIUS(dočasná); //Po prevode vráti skutočnú hodnotu teploty
}
/***********************************************************
*Názov funkcie: get_temperature
*Funkčná funkcia: Spracuje teplotnú hodnotu a uloží ju do znakového poľa pre sériový výstup
*Vstupný parameter: neoznačený char *výstup
Používa sa na uloženie konvertovanej hodnoty teploty
Teplota plávania
Teplota Celzia
*Exportné parametre: Žiadne
***********************************************************/
prázdnotaget_temperature(nepodpísanéchar*výstup,Plavákdočasné)
{
Výstup[0] = (nepodpísanéchar(dočasné) /10 + 48; //Desať miest
Výstup[1] = (nepodpísanéchar(dočasná teplota) %10 + 48; //jednociferný počet
Výstup[2] ='.'; //Desatinná čiarka
Výstup[3] = (nepodpísanéchar(dočasná teplota*10) %10 + 48; //Desiata
Výstup[4] = (nepodpísanéchar(dočasná teplota*100) %10 + 48; //Percentil
Výstup[5] =''; //Reťazcové endifikátory
}
/***********************************************************
*Názov funkcie: watchdog_init
*Funkcia funkcie: inicializácia sledovacieho psa
*Vstupné parametre: Žiadne
*Exportné parametre: Žiadne
***********************************************************/
prázdnotawatchdog_init(prázdnota)
{
WDT_SET_TIMEOUT_PERIOD(SEC_1); //Nastavte časový limit na 1 s
WDT_ENABLE(); //Spustite strážneho psa
}
[url=] [/url]
(3) Aplikačná vrstva
[url=] [/url]
/*******************************************************************
Názov súboru: main.c
Autor: hustlzp
Dátum: 2011/3/11
Verzia: 1.0
Popis funkcie: Hlavný programový súbor
Zoznam funkcií: (vynechané)
Záznam o úpravách:
*******************************************************************/
#include
/********************************************************************
Postupy služby prerušení
********************************************************************/
/* 定时器1溢出中断子程序
-------------------------------------------------------*/
#pragma vektor=T1_VECTOR
__interrupt prázdnota T1_ISR(prázdnota)
{
EA=0; Brána je prerušená
led2 = LED_ON;
get_temperature(výstup,adc_start()); Preveďte teplotnú hodnotu na pole znakov, ktoré sa majú vyprodukovať
Uart0SendString(output); Hodnota výstupnej teploty
Uart0SendString("°C");
LED2
/* 串口接收中断子程序
-------------------------------------------------------*/
#pragma vektor=URX0_VECTOR
__interrupt prázdnota RE_ISR(prázdnota)
{
EA=0;
led3 = LED_ON;
receive = U0DBUF;
if(type==1) // type=1, čo znamená, že prijatý znak sa používa na nastavenie obdobia pretečenia časovača
{
typ=0;
Prepínať (prijímať)
{
prípad '0': // Doba pretečenia časovača je 0,5s
{
SET_TIMER1_PERIOD(TIMER1_OVF_dot5SEC);
prestávka;
}
prípad '1': // Doba pretečenia časovača je 1s
{
SET_TIMER1_PERIOD(TIMER1_OVF_1SEC);
prestávka;
}
prípad '2': // Doba pretečenia časovača je 2s
{
SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
prestávka;
}
}
}
inak if(type==2) // type=2, čo znamená, že prijaté znaky sa používajú na riadenie spánku
{
typ=0;
led1 = LED_OFF;
LED2 = LED_OFF;
led3 = LED_OFF;
Prepínať (prijímať)
{
prípad '1': // Vstúpte do režimu napájania PM1
{
SET_POWER_MODE(1);
prestávka;
}
prípad '2': // Vstúpte do režimu napájania PM2
{
SET_POWER_MODE(2);
prestávka;
}
prípad '3': //Enter power mode PM3
{
SET_POWER_MODE(3);
prestávka;
}
}
}
inak if(type==0) // type=0, čo znamená, že prijatý znak je typ riadiaceho príkazu: @ alebo $
{
if(receive=='@')
{
typ=1; '@' sa prijíma na označenie, že ďalší znak sa používa na nastavenie obdobia pretečenia
}
inak ak(prijímať=='$')
{
typ=2; Prijíma sa '$', čo znamená, že ďalší znak sa používa na riadenie systému spánku
}
}
led3 = LED_OFF;
EA=1;
}
=LED_OFF;
TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR); Odstráňte prerušovaciu značku
EA=1; Otvorené prerušenie
}
/* 主函数
-------------------------------------------------------*/
void main(void)
{
SET_MAIN_CLOCK_SOURCE(CRYSTAL); Nastavte systémový takt na kryštálový oscilátor 32MHz
led_init(); Inicializácia LED
uart0_init(); Inicializácia sériového portu UART0
timer1_init(); Časovač 1 inicializuje
watchdog_init(); Inicializácia watchdog
zatiaľ čo (1)
{
WDT_RESET(); Kŕm psa neustále
}
}/********************************************************************
Hlavný program
********************************************************************/
/* 全局变量
-------------------------------------------------------*/
výstup neoznačeného char[6]={0}; Údaje o teplote sa ukladajú pre jednoduchý sériový výstup
nepodpísaný char prijíma; Uložiť prijaté znaky
neoznačený typ postavy=0; Príznak typu prijatého znaku je nastavený na 0/1/2"module.h"[url=] [/url]
5. TestovanieOch~ Kód je konečne vložený, je to naozaj vyčerpávajúce, poďme otestovať tento malý systém:
(1) Časovo obmedzené vzorkovanie
Otvorte sériový port, spustíte ladenie IAR a zistite, že LED1 je zapnutý, teplota na nástroji sériového portu sa neustále generuje a vzorkovací interval je určený na 2 sekundy:
(2) Riadenie vzorkovacích intervalov
Zadajte "@1" do nástroja na sériový port, potom otestujte vzorkovací interval a zistite, že sa zmenil na jednotky; Zadajte "@0" a vzorkovací interval sa zmení na 0,5 s.
(3) Kontrola spánku
Zadajte "$1" do nástroja na sériový port a zistite, že všetky LED sú vypnuté a vzorkovanie teploty sa zastavilo:
Po testovaní systém funguje normálne a stabilne a v podstate spĺňa požiadavky.
Študenti, ktorí potrebujú zdrojový kódKliknite sem pre stiahnutie
6. ZáverTento článok používa mierne komplexný experiment ako príklad, aby ukázal, ako integrovať zdroje CC2430 na čipe na napísanie relatívne štandardizovaného malého systému. O pár dní si nájdem čas na napísanie jednoduchého používateľského manuálu pre hal.h, aby som ja aj všetci mohli jednoducho ovládať CC2430.
Ďalej dokončím výskum zdrojov CC2430 na čipe a venujem sa učeniu protokolového stacku TI Z-Stack~
Písanie blogových príspevkov v tejto sérii sa zatiaľ skončilo, ale Zigbeeho cesta bude pokračovať. Budúcnosť je neznáma, ale verím, že autor prekoná prekážky spolu so všetkými a zažije vzostupy a pády, a prinesú sa zisky.
Zostaňte naladení: blogové príspevky "Pridajte sa k TI Z-Stack"!