Po tem, ko je 3. marca napisal "Zigbee Journey (9)", je avtor sprva načrtoval, da bo takoj začel pisati majhen eksperiment o "sistemu merjenja temperature" kot povzetek serije razpršenih točk znanja. Vendar pa sem tudi spoznal, da čeprav je bil vsak od prejšnjih manjših eksperimentov podrobno opisan, bi lahko rekli, da je normativna in strukturna narava njegove kode neznosna. Ker gre za povzetek, bi morali napredovati na prvotni osnovi, namesto da mehanično sestavljamo prejšnje majhne točke znanja. Zato sem prvotni načrt odložil, si vzel čas za učenje splošnih tehnik vgrajenega razvoja in napisal dva esejaVgrajena programska specifikacija C51" in "Hierarhija strukture vgrajene projektne kode》。 Ta dnevnik ni le povzetek Zigbeejevega prvega potovanja, temveč vključuje tudi avtorjeve učne izkušnje v zadnjih dneh, v upanju, da bo v pomoč začetnikom Zigbeeja.
Celotno besedilo je organizirano po osnovnem postopku razvoja programske opreme: analiza zahtev, načrtovanje orisa, podrobno načrtovanje, implementacija kodiranja in testiranje.
1. Analiza povpraševanjaPo pogovoru med "stranko" in "razvijalcem" je bil določen naslednji opis sistemske funkcije:
… Trenutno sobno temperaturo zbirajo vozlišča na osnovi CC2430, njene temperaturne vrednosti pa je mogoče spremljati preko računalnika
… Samo vozlišče CC2430 mora imeti določeno stopnjo stabilnosti in se lahko samodejno vrne v normalno stanje
… Interval vzorčenja in upravljanje porabe energije vozlišča lahko nadzoruje računalnik
2. Načrtovanje orisaPo zgornji analizi zahtev lahko sistem razdelimo na dva modula:Vozlišče CC2430inPC。
[CC2430 vozlišče]
… Zunanje parametre je mogoče redno zbirati in pošiljati računalniku
… Samodejna ponastavitev, ko je naprava izklopljena
… Ukaze iz računalnika je mogoče prejeti in ustrezno obdelati: spremenite interval vzorčenja/upravljanje porabe energije
[PC]
… Stroj C sprejema in prikazuje podatke preko orodja za serijski port
… Ukaze je mogoče pošiljati mikrokrmilniku preko orodja za serijski priključek za nadzor hitrosti vzorčenja in upravljanja porabe energije
3. Podrobna zasnova(1) Struktura kode
Plastenje kodne strukture tega sistema je bilo dejansko opisano v eseju "Hierarhija strukture vgrajene projektne kode", in kopija je naslednja:
(1) Plast strojne abstrakcije
[ioCC2430.h] (Sistem vključen):Vsi SFR in prekinitveni vektorji CC2430 so definirani
[hal.h] Vključuje skupne definicije tipov, skupne makroje za dodeljevanje in skupno konfiguracijo CC2430 virov na čipu (I/O, serijska komunikacija, ADC, časovnik, upravljanje porabe itd.)
(2) Funkcionalna modulska plast
[module.h] določa vire na čipu (časovniki, vhodno-izhodne), razširitvene module zunaj čipa (LED) in deklaracije povezanih funkcij
[module.cImplementirajte inicializacijo vsakega modula (LED).
(3) Aplikacijska plast
[main.cZa dosego specifičnih aplikacijskih zahtev, kot so zajem temperature, komunikacija z računalnikom ter izklop in ponastavitev se sklicujete na hal.h, ioCC2430.h in module.h
(2) Metode implementacije vsakega modula
Glede na module, razdeljene glede na načrt osnutka, lahko notranji sistem razdelimo na dva glavna modula:Vozlišče CC2430inPC。
Ker so na PC-ju orodja za serijsko komunikacijo, lahko njegove funkcije izpolnijo zahteve, zato tega dela računalnika ni treba opravljati in ni potrebe po analizi. Pogovorimo se spodaj o poglavju CC2430
Metoda implementacije vsake podfunkcije točke:
… Uporabite prekinitev prelivanja časovnika za sprožitev časovnega vzorčenja
… Način UART0 s serijskim priključkom prenaša temperaturne podatke na računalnik
… Vgrajeno vezje nadzornika CC2430 se uporablja za izvedbo funkcije samodejnega ponovnega zagona sistema
… Serijski priključek se uporablja za sprejem prekinitev, ki zajemajo in odgovarjajo na krmilne ukaze računalnika
1) Če je prejeto@Znak je ukaz za nadzor intervala vzorčenja, sledi številka, ki označuje interval vzorčenja: 0-0,5s, 1-1s, 2-2s
如:@0,表示每隔0.5秒采样一次。
2) Če je prejeto$ Znak je ukaz za nadzor spanja, sledi pa številka, ki označuje način napajanja
Na primer: $3, kar pomeni, da sistem preklopite v način napajanja 3.
(3) Shema poteka programa
- Diagram poteka magistrskega programa
- Časovnik 1 Shema pretoka programa preliva
- Diagram poteka postopka prekinitve sprejemanja serijskih vrat
4. Implementacija kodiranja(1) Plast strojne abstrakcije
Plast abstrakcije strojne opreme vključuje ioCC2430.h in hal.h. Ker je prvi sistem priložen, ne bo naveden.
Spodaj je seznam vseh vsebin hal.h (ker je ta datoteka predolga in izgleda neprijetno, jo bom prikazal v modulih):
- glava
- Vhodno/izhodni priključki
- Prekinjeno
- Serijski prenos
- Upravljanje porabe in ure
- Timer
- Čuvaj
- ADC
[url=]
[/url]
/***********************************************************
*Ime datoteke: hal.h
*Avtor: hustlzp
*Datum: 8. marec 2011
*Izdaja: 1.1
*Opis funkcije: plast abstrakcije strojne opreme
*Spremenjeni zapisi:
***********************************************************/
#ifndef HAL_H
#defineHAL_H
#include
/***********************************************************
Pogoste definicije tipov
***********************************************************/
Typedef brez podpisachar BYTE;
Typedef brez podpisaint BESEDA;
Typedef brez podpisadolgo DWORD;
/***********************************************************
Pogosto uporabljene makro definicije
***********************************************************/
//8 mest višje
#defineHIGH_BYTE(a) ((BAJT) (((BESEDA)(a)) >> 8))
//8 mest nižje
#defineLOW_BYTE(a) ((BAJT) ((BESEDA)(a)))
//Dodelitev
#defineSET_WORD(regH,regL,beseda)
delati{
(regH)=HIGH_BYTE(beseda);
(regL)=LOW_BYTE(beseda);
}medtem ko(0)
[url=] [/url]
[url=] [/url]
/***********************************************************
Vhodno/izhodni priključki
***********************************************************/
/*Nastavite smer vhodno/izhodnega priključka
-----------------------------------------*/
#defineIO_DIR_PORT_PIN(port, pin, dirigent)
delati{
če(dir == IO_OUT)
P##port##DIR |= (0x01<<(pin));
else
P##port##DIR &= ~(0x01<<(pin));
}medtem ko(0)
//Vrednost parametra dir je:
#defineIO_IN 0
#defineIO_OUT 1
/*Nastavite vhodni način vhodno-izhodnega priključka
-----------------------------------------*/
#defineIO_IMODE_PORT_PIN(port, pin, imode)
delati{
če(imode == IO_IMODE_TRI)
P##port##INP |= (0x01<<(pin));
else
P##port##INP &= ~(0x01<<(pin));
}medtem ko (0)
#define IO_PUD_PORT(port, pud)
do {
if (pud == IO_PULLDOWN)
P2INP |= (0x01 << (port+5));
else
P2INP &= ~(0x01 << (port+5));
} medtem ko (0)
Vrednost parametra PUD je:
#define IO_PULLUP 0 // Potegni gor
#define IO_PULLDOWN 1 // Potegni dol
/*配置I/O口的功能
-----------------------------------------*/
#define IO_FUNC_PORT_PIN(port, pin, func)
do {
if((port == 2) && (pin == 3)){
če (func) {
P2SEL |= 0x02;
} else {
P2SEL &= ~0x02;
}
}
sicer če((port == 2) && (pin == 4)){
če (func) {
P2SEL |= 0x04;
} else {
P2SEL &= ~0x04;
}
}
else{
če (func) {
P##port##SEL |= (0x01<<(pin));
} else {
P##port##SEL &= ~(0x01<<(pin));
}
}
} medtem ko (0)
Vrednost parametra func je:
#define IO_FUNC_GIO 0 // General I/O
#define IO_FUNC_PERIPH 1 // Periferni vhodni/izhodni
Konfiguracija lokacije perifernega vhodno/izhodnega sistema
#define IO_PER_LOC_TIMER1_AT_PORT0_PIN234() do { PERCFG = (PERCFG&~0x40)|0x00; } medtem ko (0)
#define IO_PER_LOC_TIMER1_AT_PORT1_PIN012() do { PERCFG = (PERCFG&~0x40)|0x40; } medtem ko (0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN34() do { PERCFG = (PERCFG&~0x20)|0x00; } medtem ko (0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN67() do { PERCFG = (PERCFG&~0x20)|0x20; } medtem ko (0)
#define IO_PER_LOC_TIMER4_AT_PORT1_PIN01() do { PERCFG = (PERCFG&~0x10)|0x00; } medtem ko (0)
#define IO_PER_LOC_TIMER4_AT_PORT2_PIN03() do { PERCFG = (PERCFG&~0x10)|0x10; } medtem ko (0)
#define IO_PER_LOC_SPI1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x08)|0x00; } medtem ko (0)
#define IO_PER_LOC_SPI1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x08)|0x08; } medtem ko (0)
#define IO_PER_LOC_SPI0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x00; } medtem ko (0)
#define IO_PER_LOC_SPI0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x04; } medtem ko (0)
#define IO_PER_LOC_UART1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x02)|0x00; } medtem ko (0)
#define IO_PER_LOC_UART1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x02)|0x02; } medtem ko (0)
#define IO_PER_LOC_UART0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x00; } medtem ko (0)
#define IO_PER_LOC_UART0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x01; } medtem ko (0)
//Vrednost parametra imode je:
#defineIO_IMODE_PUD 0 //Potegni gor/potegni dol
#defineIO_IMODE_TRI 1 //Tri države[url=] [/url]
[url=] [/url]
/***********************************************************
Prekinjeno
***********************************************************/
//Za vklop/izklop prekinitve
#defineINT_ON 1
#defineINT_OFF 0
//Uporablja se za postavljanje/brisanje zastavic prekinitev
#defineINT_SET 1
#defineINT_CLR 0
//Globalne nastavitve prekinitev
#defineINT_GLOBAL_ENABLE(on) EA=(!! vklopljeno)
//Definiraj prelom
#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
/*Dovoljene prekinitve
-----------------------------------------*/
#defineINT_ENABLE(inum, vklopljeno)
delati{
če (inum==INUM_RFERR) { RFERRIE = vklopljeno; }
else če(inum==INUM_ADC) { ADCIE = vklopljeno; }
else če(inum==INUM_URX0) { URX0IE = vklopljeno; }
else če(inum==INUM_URX1) { URX1IE = na; }
else če(inum==INUM_ENC) { ENCIE = vklopljeno; }
else če(inum==INUM_ST) { STIE = vklopljeno; }
else če(inum==INUM_P2INT) { (vklopljeno) ? (IEN2 |=0x02) : (IEN2 &= ~0x02); }
else če(inum==INUM_UTX0) { (vklopljeno) ? (IEN2 |=0x04) : (IEN2 &= ~0x04); }
else če(inum==INUM_DMA) { DMAIE = vklopljen; }
else če(inum==INUM_T1) { T1IE = v; }
else če(inum==INUM_T2) { T2IE = vklopljeno; }
else če(inum==INUM_T3) { T3IE = vklopljeno; }
else če(inum==INUM_T4) { T4IE = v; }
else če(inum==INUM_P0INT) { P0IE = v; }
else če(inum==INUM_UTX1) { (vklopljeno) ? (IEN2 |=0x08) : (IEN2 &= ~0x08); }
else če(inum==INUM_P1INT) { (vklopljeno) ? (IEN2 |=0x10) : (IEN2 &= ~0x10); }
else če(inum==INUM_RF) { (vklopljeno) ? (IEN2 |=0x01) : (IEN2 &= ~0x01); }
else če(inum==INUM_WDT) { (vklopljeno) ? (IEN2 |=0x20) : (IEN2 &= ~0x20); }
}medtem ko (0)
/*Nastavite prioriteto izpada
-----------------------------------------*/
#defineINT_PRIORITY(skupina, pri)
delati{
če(pri ==0) { IP0 &= ~grupa; IP1 &= ~skupina; }
če(pri ==1) { IP0 |= grupa; IP1 &= ~skupina; }
če(pri ==2) { IP0 &= ~grupa; IP1 |= grupa; }
če(pri ==3) { IP0 |= grupa; IP1 |= grupa; }
}medtem ko (0)
//Vrednost parametra pri je: 0/1/2/3 (najvišja prioriteta)
//Vrednost skupine 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
/*Pridobite zastavico prekinitve
-----------------------------------------*/
#defineINT_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
)
/*Nastavite zastavico prekinitve
-----------------------------------------*/
#defineINT_SETFLAG(inum, f)
delati{
če (inum==INUM_RFERR) { RFERRIF= f; }
else če(inum==INUM_ADC) { ADCIF = f; }
else če(inum==INUM_URX0) { URX0IF = f; }
else če(inum==INUM_URX1) { URX1IF = f; }
else če(inum==INUM_ENC) { ENCIF_1 = ENCIF_0 = f; }
else če(inum==INUM_ST) { STIF = f; }
else če(inum==INUM_P2INT) { P2IF = f; }
else če(inum==INUM_UTX0) { UTX0IF= f; }
else če(inum==INUM_DMA) { DMAIF = f; }
else če(inum==INUM_T1) { T1IF = f; }
else če(inum==INUM_T2) { T2IF = f; }
else če(inum==INUM_T3) { T3IF = f; }
else če(inum==INUM_T4) { T4IF = f; }
else če(inum==INUM_P0INT) { P0IF = f; }
else če(inum==INUM_UTX1) { UTX1IF= f; }
else če(inum==INUM_P1INT) { P1IF = f; }
else če(inum==INUM_RF) { (f) ? (S1CON |=0x03) : (S1CON &= ~0x03); }
else če(inum==INUM_WDT) { WDTIF = f; }
}medtem ko (0)
[url=] [/url]
[url=] [/url]
/***********************************************************
Serijski prenos
***********************************************************/
//Vrednost BAUD_E ustreza različnim hitrostim prenosa
#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 )
//Vrednost BAUD_M ustreza različnim hitrostim prenosa
#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)
/*Konfiguracija serijskih vrat v načinu UART
-----------------------------------------*/
#defineUART_SETUP(uart, receiveEnable, baudRate, opcije)
delati{
če((uart) ==0){
če(PERCFG &0x01){
P1SEL |=0x30;
}else{
P0SEL |=0x0C;
}
}
else{
če(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 |= ((možnosti) |0x80);
}medtem ko(0)
//Vrednost parametra ReEnable :
#defineUART_RECEIVE_ENABLE 0x40 //Prejem dovoljenja
#defineUART_RECEIVE_DISABLE 0x00
//Vrednost parametričnih možnosti:
#defineFLOW_CONTROL_ENABLE 0x40 //Nadzor pretoka
#defineFLOW_CONTROL_DISABLE 0x00
#defineEVEN_PARITY 0x20 //Občasno preverjanje
#defineODD_PARITY 0x00 //Nenavadna potrditev
#defineNINE_BIT_TRANSFER 0x10 //9-bajtni prenos
#defineEIGHT_BIT_TRANSFER 0x00 //8-bajtni prenos
#definePARITY_ENABLE 0x08 //Omogočanje preverjanja paritete
#definePARITY_DISABLE 0x00
#defineTWO_STOP_BITS 0x04 //2-položajni stop položaj
#defineONE_STOP_BITS 0x00 //1 stop položaj
#defineHIGH_STOP 0x02 //Raven zaustavitve je visoka
#defineLOW_STOP 0x00 //Položaj zaustavitve je nizek
#defineHIGH_START 0x01 //Začetna bitna raven je visoka
#defineLOW_START 0x00 //Začetna bitna raven je nizka
//Serijski prenos pošilja like
#defineUART_SEND(uart,data)
delati{
medtem ko(U##uart##CSR &0x01);
U##uart##DBUF = podatki;
}medtem ko (0)
#defineUART0_SEND(data) UART_SEND(0,data)
#defineUART1_SEND(podatki) UART_SEND(1,podatki)
//Serijski prenos sprejema znake
#defineUART_RECEIVE(uart,data)
delati{
medtem ko(! (U##uart##CSR&0x04));
data=U##uart##DBUF;
}medtem ko(0)
#defineUART0_RECEIVE(podatki) UART_RECEIVE(0,podatki)
#defineUART1_RECEIVE(podatki) UART_RECEIVE(1,podatki)
[url=] [/url]
[url=] [/url]
/***********************************************************
Upravljanje porabe in ure
***********************************************************/
//Vzemi prehod z uro
#defineCLKSPD (CLKCON & 0x07)
//Nastavi način napajanja
#defineSET_POWER_MODE(način)
delati{
če(način ==0) { SPANJE &= ~0x03; }
else če(način ==3) { SPANJE |=0x03; }
else{ SPANJE &= ~0x03; SLEEP |= način; }
PCON |=0x01;
ASM("NOP");
}medtem ko (0)
//Način parametrov je nastavljen na naslednje vrednosti:
#definePOWER_MODE_0 0x00
#definePOWER_MODE_1 0x01
#definePOWER_MODE_2 0x02
#definePOWER_MODE_3 0x03
//Uporablja se za zaznavanje stabilnosti visokofrekvenčnih RC oscilatorjev
#defineHIGH_FREQUENCY_RC_OSC_STABLE (SPANJE & 0x20)
//Uporablja se za zaznavanje stabilnega stanja kristalnega oscilatorja
#defineXOSC_STABLE (SPANJE & 0x40)
//Pridobi vrednost frekvence tikanja časovnika
#defineTICKSPD ((CLKCON & 0x38) >> 3)
//Nastavite frekvenco glavne ure
#defineSET_MAIN_CLOCK_SOURCE(vir)
delati{
če(vir) {
CLKCON |=0x40;
medtem ko(! HIGH_FREQUENCY_RC_OSC_STABLE);
če(TICKSPD ==0){
CLKCON |=0x08;
}
SPANJE |=0x04;
}
else{
SPANJE &= ~0x04;
medtem ko(! XOSC_STABLE);
ASM("NOP");
CLKCON &= ~0x47;
SPANJE |=0x04;
}
}medtem ko (0)
//Vrednost vira parametra je:
#defineKRISTALNA 0x00 //Kristalni oscilator
#defineRC 0x01 //RC oscilator
[url=] [/url]
[url=] [/url]
/***********************************************************
Timer 1
***********************************************************/
//Časovnik 1 omogoča, da se prelivanje štetja prekine
#defineTIMER1_ENABLE_OVERFLOW_INT(val)
(TIMIF = (val) ? ČAS |0x40: TIMIF & ~0x40)
//Nastavi zastavico prekinitve, ki preteče za časovnik 1
#defineTIMER1_OVERFLOW_INT_SETFLAG(f) (T1CTL= ((T1CTL & (~0x10)) | f))
//Začne se časovnik 1
#defineTIMER1_RUN(vrednost) (T1CTL = (vrednost) ? T1CTL|0x02 : T1CTL&~0x03)
//Nastavi delitev ure za števec
#defineSET_TIMER_TICK(vrednost) do{ CLKCON = ((CLKCON & (~0x38)) | vrednost); } medtem ko (0)
//Vrednost vrednosti je:
#defineTIMER1_TICK_32M 0x00 //32MHz
#defineTIMER1_TICK_16M 0x08 //16MHz, privzeta vrednost za ponastavitev sistema
#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
//Nastavi TICK crossover na timer 1
#defineSET_TIMER1_TICKDIV(vrednost)
delati{
T1CTL &= ~0x0c;
T1CTL |= vrednost;
}medtem ko (0)
//kjer je vrednost:
#defineTIMER1_TICKDIV_1 0x00 //1 divizija
#defineTIMER1_TICKDIV_8 0x04 //8-smerna frekvenca
#defineTIMER1_TICKDIV_32 0x08
#defineTIMER1_TICKDIV_128 0x0c
//Nastavi obdobje presežka časovnika
#defineSET_TIMER1_PERIOD(vrednost)
delati{
T1CC0H = HIGH_BYTE(vrednost);
T1CC0L = LOW_BYTE(vrednost);
}medtem ko (0)
//Nastavite način delovanja Timer 1
#defineSET_TIMER1_MODE(mode)
delati{
T1CTL = ((T1CTL & (~0x03)) | način);
}medtem ko (0)
//Vrednost načina je:
#defineTIMER1_MODE_STOP 0x00
#defineTIMER1_MODE_FREE 0x01
#defineTIMER1_MODE_MODULE 0x02
#defineTIMER1_MODE_UPDOWN 0x03
[url=] [/url]
[url=] [/url]
/***********************************************************
Čuvaj
***********************************************************/
//Nastavi obdobje presežka za watchdog časovnik
#defineWDT_SET_TIMEOUT_PERIOD(premor)
delati{ WDCTL &= ~0x03; WDCTL |= odmor; }medtem ko (0)
//Vrednost časovne omejitve parametra je:
#defineSEC_1 0x00 //po 1 sekundi
#defineM_SEC_250 0x01 //Po 250 ms
#defineM_SEC_15 0x02 //Po 15 ms
#defineM_SEC_2 0x03 //Po 2 ms
//Postopki hranjenja psov
#defineWDT_RESET() do {
WDCTL = (WDCTL & ~0xF0) |0xA0;
WDCTL = (WDCTL & ~0xF0) |0x50;
} medtem ko (0)
//Zaženi/ustavi watchdog časovnik
#defineWDT_ENABLE() WDCTL |= 0x08
#defineWDT_DISABLE() WDCTL &= ~0x08
[url=] [/url]
[url=] [/url]
/***********************************************************
ADC
***********************************************************/
//Konfigurirajte en sam ADC
#defineADC_SINGLE_CONVERSION(nastavitve)
delati{ ADCCON3 = nastavitve; }medtem ko(0)
//Nastavitev parametrov je sestavljena iz naslednjih kombinacij:
//Referenčna napetost
#defineADC_REF_1_25_V 0x00 //Notranja referenčna napetost 1,25 V
#defineADC_REF_P0_7 0x40 //Zunanja referenčna napetost na pinu AIN7
#defineADC_REF_AVDD 0x80 //AVDD_SOC Značke
#defineADC_REF_P0_6_P0_7 0xC0 //AIN6-AIN7 Zunanja referenčna napetost za diferencialne vhode
//Vzorčna frekvenca
#defineADC_8_BIT 0x00 //8. mesto
#defineADC_10_BIT 0x10 //10. mesto
#defineADC_12_BIT 0x20 //12. mesto
#defineADC_14_BIT 0x30 //14. mesto
//Vstop na kanal
#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 //Zemljišče
#defineADC_TEMP_SENS 0x0E //Temperaturni senzor v čipu
#defineADC_VDD_3 0x0F //VDD/3
Pretvorba ADC je zaključena
#define ADC_SAMPLE_READY() (ADCCON1 & 0x80)
#endif
//启动ADC转化
#define ADC_START()
naredi { ADCCON1 |= 0x40; } medtem ko (0)//Izberite sprožilni način ADC-ja kot ročni (tj. ADC_SAMPLE_READY)
#defineADC_STOP()
delati{ ADCCON1 |=0x30; }medtem ko (0)[url=] [/url]
(2) Funkcionalna modulska plast
[url=] [/url]
/***********************************************************
*Ime datoteke: module.h
*Avtor: hustlzp
*Datum: 6. marec 2011
*Različica: 1.0
*Opis funkcije: datoteka glave funkcionalnega modulskega sloja
*Seznam funkcij: void led_init()
void timer1_init()
praznina uart0_init(praznina);
void Uart0SendString(unsigned char *s);
Float adc_start(praznina)
void get_temperature(nepodpisani char *izhod, float temp);
praznina watchdog_init(praznina);
*Spremenjeni zapisi:
***********************************************************/
#ifndef MODULE_H
#defineMODULE_H
#include"hal.h"
/***********************************************************
LED
***********************************************************/
//Določite LED pine
#defineLED1 P1_0
#defineLED2 P1_1
#defineLED3 P1_2
#defineLED4 P1_3
//LED lučka in ugasnjena
#defineLED_OFF 1
#defineLED_ON 0
//Inicializacija LED
prazninaled_init(praznina);
/***********************************************************
timer1
***********************************************************/
//Uporablja se za nastavitev vrednosti presežnega obdobja za časovnik
#defineTIMER1_OVF_2SEC 0xF424 //2
#defineTIMER1_OVF_1SEC 0x7A12 //1
#defineTIMER1_OVF_dot5SEC 0x3D09 //0,5 s
//Timer 1 se inicializira
praznina timer1_init(praznina);
/***********************************************************
UART0
***********************************************************/
//Inicializacija UART0
praznina uart0_init(praznina);
//Serijski prenosni niz
praznina Uart0SendString(unsignedchar*s);
/***********************************************************
ADC-14
***********************************************************/
//Uporablja se za pretvorbo podatkov, pridobljenih z ADC, v temperaturo Celzija
#defineADC_TO_CELSIUS(temperatura) (temperatura * 0,06229 - 311,43)
//Začni pretvorbo v ADC
Plovecadc_start(praznina);
//Predelava
praznina get_temperature(nepodpisanochar*izhod,Ploveczačasno);
/***********************************************************
WatchDog
***********************************************************/
//Inicializacija Watch Doga
praznina watchdog_init(praznina);
#endif
[url=] [/url]
[url=] [/url]
/***********************************************************
*Ime datoteke: module.c
*Avtor: hustlzp
*Datum: 2011/3/11
*Različica: 1.0
*Opis funkcije: izvorna datoteka funkcionalnega modulskega sloja
*Seznam funkcij: (izpuščen)
*Spremenjeni zapisi:
***********************************************************/
#include"module.h"
/***********************************************************
*Ime funkcije: led_init
*Funkcijska funkcija: inicializacija LED diod
*Vhodni parametri: Brez
*Izvozni parametri: Ni
***********************************************************/
prazninaled_init(praznina)
{
//Konfigurirajte P1.0, P1.1, P1.2 in P1.3 kot splošne vhodno-izhodne priključke
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);
//Nastavite P1.0, P1.1, P1.2 in P1.3 kot izhode
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;
}
/***********************************************************
*Ime funkcije: timer1_init
* Funkcijska funkcija: inicializacija časovnika 1
*Vhodni parametri: Brez
*Izvozni parametri: Ni
***********************************************************/
prazninatimer1_init(praznina)
{
INT_GLOBAL_ENABLE(INT_ON); //Odpri globalno prekinitev
INT_ENABLE(INUM_T1, INT_ON); //Odprti T1 prekinitev
TIMER1_ENABLE_OVERFLOW_INT(INT_ON); //Prekinitev prelivanja štetja odprtega T1
SET_TIMER_TICK(TIMER1_TICK_4M); //Nastavi časovnik TICK na 4MHz
SET_TIMER1_PERIOD(TIMER1_OVF_2SEC); //Nastavi obdobje štetja za T1 na 2
SET_TIMER1_TICKDIV(TIMER1_TICKDIV_128); //Nastavite crossover ure za T1 na 128
SET_TIMER1_MODE(TIMER1_MODE_MODULE); //Nastavite način delovanja T1 na modul
}
/***********************************************************
*Ime funkcije: uart0_init
*Funkcijska funkcija: inicializacija serijskega porta UART0
*Vhodni parametri: Brez
*Izvozni parametri: Ni
***********************************************************/
prazninauart0_init(praznina)
{
//Izberite lokacijo UART
IO_PER_LOC_UART0_AT_PORT0_PIN2345();
//Konfiguracija UART: Dovoljen sprejem, 115200bps, enobitni stop bit, brez paritete
UART_SETUP(0, UART_RECEIVE_ENABLE,115200, ONE_STOP_BITS | PARITY_DISABLE);
//Odpri popolno prekinitev
INT_GLOBAL_ENABLE(INT_ON);
//Odpri serijski port 0 za sprejem prekinitev
INT_ENABLE(INUM_URX0, INT_ON);
}
/***********************************************************
*Ime funkcije: Uart0SendString
* Funkcijska funkcija: inicializacija časovnika 1
*Vstopni parameter: nepodpisani znak *s
Niz, ki ga želiš poslati
*Izvozni parametri: Ni
***********************************************************/
prazninaUart0SendString(unsignedchar*s)
{
medtem ko(*s !=0)
UART0_SEND(*s++);
}
/***********************************************************
*Ime funkcije: adc_start
*Funkcijska funkcija: Začni pretvorbo ADC
*Vhodni parametri: Brez
*Izvozni parameter: plavajoči
Temperaturna vrednost v tablici
***********************************************************/
Plovecadc_start(praznina)
{
nepodpisanointtemperatura;
//Referenčna napetost je 1,25V, natančnost vzorčenja je 14 bitov, cilj pretvorbe pa je temperaturni senzor na čipu
ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);
ADC_STOP(); //Nastavi način sprožilca za pretvorbo ADC na ročno
ADC_START(); //Začni pretvorbo v ADC
medtem ko(! ADC_SAMPLE_READY()); //Počakaj, da se pretvorba zaključi
temp = ADCL >>2; //Shrani rezultate pretvorbe v temperaturo
temp |= ((((unsignedint) ADCH) <<6);
VrnitevADC_TO_CELSIUS(začasna); //Po pretvorbi vrne dejansko temperaturno vrednost
}
/***********************************************************
*Ime funkcije: get_temperature
*Funkcijska funkcija: Obdela temperaturno vrednost in jo shrani v polje znakov za serijski izhod
*Parametr vnosa: neznano znaki *izhod
Uporablja se za shranjevanje pretvorjene temperature
Temperatura plovca
Vrednost temperature Celzija
*Izvozni parametri: Ni
***********************************************************/
prazninaget_temperature(nepodpisanochar*izhod,Plovectemp)
{
Izhod[0] = (nepodpisanochar(začasna začasnost) /10 + 48; //Deset mest
Izhod[1] = (nepodpisanochar(začasno) %10 + 48; //enomestna številka
Izhod[2] ='.'; //Decimalna vejica
Izhod[3] = (nepodpisanochar(temperatura*10) %10 + 48; //Deseti
Izhod[4] = (nepodpisanochar(temperatura*100) %10 + 48; //Percentil
Izhod[5] =''; //Nizni endifikatorji
}
/***********************************************************
*Ime funkcije: watchdog_init
*Funkcijska funkcija: inicializacija Watch Dog
*Vhodni parametri: Brez
*Izvozni parametri: Ni
***********************************************************/
prazninawatchdog_init(praznina)
{
WDT_SET_TIMEOUT_PERIOD(SEC_1); //Nastavi čas odmora na 1 sekunde
WDT_ENABLE(); //Zaženi čuvajskega psa
}
[url=] [/url]
(3) Aplikacijska plast
[url=] [/url]
/*******************************************************************
Ime datoteke: main.c
Avtor: hustlzp
Datum: 2011/3/11
Različica: 1.0
Opis funkcije: Glavna programska datoteka
Seznam funkcij: (izpuščen)
Zapis o spremembah:
*******************************************************************/
#include
/********************************************************************
Postopki storitve prekinitev
********************************************************************/
/* 定时器1溢出中断子程序
-------------------------------------------------------*/
#pragma vektor=T1_VECTOR
__interrupt praznina T1_ISR(praznina)
{
EA=0; Vrata so prekinjena
led2 = LED_ON;
get_temperature(izhod,adc_start()); Pretvorite temperaturno vrednost v polje znakov, ki jih želimo izpisati
Uart0SendString(izhod); Vrednost izhodne temperature
Uart0SendString("°C");
led2
/* 串口接收中断子程序
-------------------------------------------------------*/
#pragma vektor=URX0_VECTOR
__interrupt praznina RE_ISR(praznina)
{
EA=0;
led3 = LED_ON;
receive = U0DBUF;
if(type==1) // type=1, kar pomeni, da se prejeti znak uporablja za nastavitev obdobja presežka časovnika
{
tip=0;
Preklop (sprejem)
{
Primer '0': // Obdobje presežka časovnika je 0,5 s
{
SET_TIMER1_PERIOD(TIMER1_OVF_dot5SEC);
premor;
}
primer '1': // Obdobje presežka časovnika je 1 s
{
SET_TIMER1_PERIOD(TIMER1_OVF_1SEC);
premor;
}
primer '2': // Obdobje presežka časovnika je 2 s
{
SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
premor;
}
}
}
sicer if(type==2) // type=2, kar pomeni, da se prejeti znaki uporabljajo za nadzor spanja
{
tip=0;
led1 = LED_OFF;
led2 = LED_OFF;
led3 = LED_OFF;
Preklop (sprejem)
{
primer '1': // Vstopi v način napajanja PM1
{
SET_POWER_MODE(1);
premor;
}
primer '2': // Vstopi v način napajanja PM2
{
SET_POWER_MODE(2);
premor;
}
primer '3': //Vstopi v način napajanja PM3
{
SET_POWER_MODE(3);
premor;
}
}
}
sicer if(type==0) // type=0, kar pomeni, da je prejeti znak tip kontrolnega ukaza: @ ali $
{
if(receive=='@')
{
tip=1; '@' se prejme, kar označuje, da se naslednji znak uporablja za nastavitev presežnega obdobja
}
sicer če(receive=='$')
{
tip=2; Prejme se '$', kar pomeni, da se naslednji znak uporablja za nadzor sistemskega spanja
}
}
led3 = LED_OFF;
EA=1;
}
=LED_OFF;
TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR); Odstranite znak za prekinitev
EA=1; Odprta prekinitev
}
/* 主函数
-------------------------------------------------------*/
void main(void)
{
SET_MAIN_CLOCK_SOURCE(CRYSTAL); Nastavite sistemsko uro na 32MHz kristalni oscilator
led_init(); Inicializacija LED
uart0_init(); Inicializacija serijskega porta UART0
timer1_init(); Timer 1 se inicializira
watchdog_init(); Inicializacija Watch Doga
medtem ko (1)
{
WDT_RESET(); Nenehno hranite psa
}
}/********************************************************************
Glavni program
********************************************************************/
/* 全局变量
-------------------------------------------------------*/
izhod neoznačenega znaka[6]={0}; Podatki o temperaturi se shranjujejo za enostaven serijski izpis
nepodpisani char sprejema; Shrani prejete znake
neoznačen tip=0; Tipna zastavica prejetega znaka je nastavljena na 0/1/2"module.h"[url=] [/url]
5. TestiranjeOh~ Koda je končno prilepljena, res je naporno, preizkusimo ta majhen sistem:
(1) Časovno vzorčenje
Odprite serijski priključek in začnite razhroščevanje z IAR, ugotovite, da je LED1 vklopljen, temperatura na orodju serijskega priključka pa se nenehno generira, vzorčni interval pa je določen na 2:
(2) Nadzor intervalov vzorčenja
Vnesi "@1" v orodje za serijski port, nato preizkusi interval vzorčenja in ugotovi, da je postal 1; Vnesite "@0" in vzorčni interval se spremeni na 0,5 s.
(3) Nadzor spanja
Vnesi "$1" v orodje za serijski priključek in ugotovi, da so vse LED diode ugasnjene in da se je vzorčenje temperature ustavilo:
Po testiranju sistem deluje normalno in stabilno ter v osnovi izpolnjuje zahteve.
Študenti, ki potrebujejo izvorno kodoKliknite tukaj za prenos
6. ZaključekTa članek uporablja nekoliko obsežen eksperiment kot primer, da pokaže, kako integrirati CC2430 vgrajene vire za pisanje relativno standardiziranega majhnega sistema. Čez nekaj dni si bom vzel čas in napisal preprost uporabniški priročnik za hal.h, da bom jaz in vsi ostali lahko enostavno upravljali CC2430.
Nato bom zaključil raziskavo o CC2430 vgrajenih virih in se posvetil učenju protokola TI Z-Stack~
Pisanje blog zapisov v tej seriji je za zdaj končano, a Zigbeejeva pot se bo nadaljevala. Pokrajina pred njo je neznana, a verjamem, da bo avtor premagal ovire z vsemi in okusil vzpone in padce, in da bo napredek.
Ostanite z nami: "Pridružite se TI Z-Stack" blog objavam!