Efter at have skrevet "Zigbee Journey (9)" den 3. marts planlagde forfatteren oprindeligt straks at begynde at skrive et lille eksperiment om "temperaturovervågningssystem" som et resumé af en række spredte videnspunkter før. Men jeg indså også, at selvom hvert af de tidligere små eksperimenter var beskrevet i detaljer, kunne den normative og strukturelle karakter af kodens karakter siges at være uudholdelig. Da det er et resumé, bør vi gøre fremskridt på det oprindelige grundlag i stedet for mekanisk at samle de tidligere små videnspunkter. Derfor satte jeg min oprindelige plan på pause, tog mig tid til at lære de generelle teknikker for embedded development og skrev to essaysIndlejret C51-programmeringsspecifikation" og "Hierarki af indlejret projektkodestruktur》。 Denne log er ikke kun et resumé af Zigbees første rejse, men indeholder også forfatterens læringserfaringer fra de seneste dage, i håb om at være til hjælp for Zigbee-begyndere.
Fuldteksten er organiseret efter den grundlæggende proces for softwareudvikling: kravanalyse, dispositionsdesign, detaljeret design, kodningsimplementering og test.
1. EfterspørgselsanalyseEfter drøftelse mellem "kunden" og "udvikleren" blev følgende systemfunktionsbeskrivelse fastlagt:
… Den aktuelle rumtemperatur indsamles af CC2430-baserede noder, og dens temperaturværdier kan overvåges via en PC
… CC2430-noden skal have en vis grad af stabilitet og kan automatisk vende tilbage til normal tilstand
… Samplingsintervallet og strømstyringen af noden kan styres af en PC
2. OversigtsdesignIfølge ovenstående kravanalyse kan vi opdele systemet i to moduler:CC2430-nodeogPC。
[CC2430 Node]
… Eksterne parametre kan indsamles regelmæssigt og sendes til PC'en
… Automatisk nulstilling, når maskinen slukkes
… Kommandoer fra PC'en kan modtages og behandles derefter: ændr prøveintervallet/strømstyringen
[PC]
… C-maskinen modtager og viser data gennem det serielle portværktøj
… Instruktioner kan sendes til mikrocontrolleren via det serielle portværktøj for at styre dens prøvetagningshastighed og strømstyring
3. Detaljeret design(1) Kodestruktur
Lagdelingen af kodestrukturen i dette system er faktisk beskrevet i essayet "Hierarki af indlejret projektkodestruktur", og kopien er som følger:
(1) Hardware-abstraktionslag
[ioCC2430.h] (System inkluderet):Alle SFR- og afbrydelsesvektorer i CC2430 er defineret
[hal.h] Inkluderer fælles typedefinitioner, almindelige tildelingsmakroer og fælles konfiguration af CC2430 on-chip ressourcer (I/O, seriel kommunikation, ADC, timer, strømstyring osv.)
(2) Funktionelt modullag
[module.h] definerer on-chip ressourcer (timere, I/O), off-chip udvidelsesmoduler (LED'er) og deklarationer af relaterede funktioner
[module.cImplementér initialiseringen af hvert modul (LED).
(3) Applikationslag
[main.cSe hal.h, ioCC2430.h og module.h for at opfylde specifikke applikationskrav såsom temperaturindhentning, kommunikation med PC samt nedlukning og nulstilling
(2) Implementeringsmetoder for hvert modul
Ifølge modulerne opdelt efter dispositionsdesignet kan det intrinsiske system opdeles i to hovedmoduler:CC2430-nodeogPC。
Da der findes serielle portkommunikationsværktøjer på PC'en, kan dens funktioner opfylde kravene, så vi behøver ikke at lave denne del af PC'en, og der er ikke behov for at analysere den. Lad os tale om afsnit CC2430 nedenfor
Implementeringsmetoden for hver delfunktion af punktet:
… Brug timerens count overflow-interrupt til at udløse timed sampling
… UART0-tilstanden med seriel port sender temperaturdata til en PC
… CC2430's indbyggede watchdog-kredsløb bruges til at realisere systemets automatiske nulstillingsfunktion
… Den serielle port bruges til at modtage afbrydelser for at fange og besvare kontrolkommandoer fra PC'en
1) Hvis modtaget@Tegnet er samplingsintervalkontrolkommandoen, efterfulgt af et tal, der angiver samplingsintervallet: 0-0,5 sekunder, 1-1 sekunder, 2-2 sekunder
如:@0,表示每隔0.5秒采样一次。
2) Hvis modtaget$ Tegnet er søvnkontrolkommandoen, efterfulgt af et tal, der angiver strøm-tilstanden
For eksempel: $3, hvilket betyder at sætte systemet i strømtilstand 3.
(3) Programflowchart
- Masterprogram-flowchart
- Timer 1 Overflow Interrupt Program Flowdiagram
- Flowdiagram for procedure for modtagelse af seriel port
4. Kodningsimplementering(1) Hardware-abstraktionslag
Hardware-abstraktionslaget inkluderer ioCC2430.h og hal.h. Da det tidligere system følger med, vil det ikke blive opført.
Følgende er en liste over alt indholdet i hal.h (fordi denne fil er for lang og ser besværlig ud, vil jeg vise den i moduler):
- Hoved
- I/O-porte
- Afbrudt
- Seriel port
- Strøm- og clockstyring
- Timer
- Vagthund
- ADC
[url=]
[/url]
/***********************************************************
*Filnavn: hal.h
*Forfatter: hustlzp
*Dato: 8. marts 2011
*Udgave: 1.1
*Funktionsbeskrivelse: Hardware-abstraktionslag
*Ændrede optegnelser:
***********************************************************/
#ifndef HAL_H
#defineHAL_H
#include
/***********************************************************
Almindelige typedefinitioner
***********************************************************/
typedef usigneretChar BYTE;
typedef usigneretint WORD;
typedef usigneretLang DWORD;
/***********************************************************
Almindeligt anvendte makrodefinitioner
***********************************************************/
//8 pladser højere
#defineHIGH_BYTE(a) ((BYTE) (((WORD)(a)) >> 8))
//8 pladser lavere
#defineLOW_BYTE(a) ((BYTE) ((WORD)(a)))
//Tildeling
#defineSET_WORD(regH,regL,ord)
gøre{
(regH)=HIGH_BYTE(ord);
(regL)=LOW_BYTE(ord);
}mens(0)
[url=] [/url]
[url=] [/url]
/***********************************************************
I/O-porte
***********************************************************/
/*Konfigurer I/O-portens retning
-----------------------------------------*/
#defineIO_DIR_PORT_PIN(port, pin, instruktør)
gøre{
hvis(dir: == IO_OUT)
P##port##DIR |= (0x01<<(nåle));
ellers
P##port##DIR &= ~(0x01<<(nåle));
}mens(0)
//Værdien af parameter-dir'en er:
#defineIO_IN 0
#defineIO_OUT 1
/*Konfigurer input-tilstanden på I/O-porten
-----------------------------------------*/
#defineIO_IMODE_PORT_PIN(port, pin, imode)
gøre{
hvis(imode == IO_IMODE_TRI)
P##port##INP |= (0x01<<(nåle));
ellers
P##port##INP &= ~(0x01<<(nåle));
}mens (0)
#define IO_PUD_PORT(bagbord, pud)
do {
hvis (pud == IO_PULLDOWN)
P2INP |= (0x01 << (port+5));
ellers
P2INP &= ~(0x01 << (port+5));
} mens (0)
Værdien af parameteren PUD er:
#define IO_PULLUP 0 // Træk op
#define IO_PULLDOWN 1 // Træk ned
/*配置I/O口的功能
-----------------------------------------*/
#define IO_FUNC_PORT_PIN(port, pin, func)
do {
hvis((port == 2) && (pin == 3)){
hvis (func) {
P2SEL |= 0x02;
} ellers {
P2SEL &= ~0x02;
}
}
else if((port == 2) && (pin == 4)){
hvis (func) {
P2SEL |= 0x04;
} ellers {
P2SEL &= ~0x04;
}
}
else{
hvis (func) {
P##port##SEL |= (0x01<<(nål));
} ellers {
P##port##SEL &= ~(0x01<<(nål));
}
}
} mens (0)
Værdien af parameterfunkcen er:
#define IO_FUNC_GIO 0 // Generel I/O
#define IO_FUNC_PERIPH 1 // Perifert I/O
Konfigurer placeringen af den perifere I/O
#define IO_PER_LOC_TIMER1_AT_PORT0_PIN234() do { PERCFG = (PERCFG&~0x40)|0x00; } mens (0)
#define IO_PER_LOC_TIMER1_AT_PORT1_PIN012() do { PERCFG = (PERCFG&~0x40)|0x40; } mens (0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN34() do { PERCFG = (PERCFG&~0x20)|0x00; } mens (0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN67() do { PERCFG = (PERCFG&~0x20)|0x20; } mens (0)
#define IO_PER_LOC_TIMER4_AT_PORT1_PIN01() do { PERCFG = (PERCFG&~0x10)|0x00; } mens (0)
#define IO_PER_LOC_TIMER4_AT_PORT2_PIN03() do { PERCFG = (PERCFG&~0x10)|0x10; } mens (0)
#define IO_PER_LOC_SPI1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x08)|0x00; } mens (0)
#define IO_PER_LOC_SPI1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x08)|0x08; } mens (0)
#define IO_PER_LOC_SPI0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x00; } mens (0)
#define IO_PER_LOC_SPI0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x04; } mens (0)
#define IO_PER_LOC_UART1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x02)|0x00; } mens (0)
#define IO_PER_LOC_UART1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x02)|0x02; } mens (0)
#define IO_PER_LOC_UART0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x00; } mens (0)
#define IO_PER_LOC_UART0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x01; } mens (0)
//Værdien af parameteren imode er:
#defineIO_IMODE_PUD 0 //Træk op/træk ned
#defineIO_IMODE_TRI 1 //Tre stater[url=] [/url]
[url=] [/url]
/***********************************************************
Afbrudt
***********************************************************/
//For tænd/sluk-afbrydelser
#defineINT_ON 1
#defineINT_OFF 0
//Bruges til at placere/rydde afbrydelsesflag
#defineINT_SET 1
#defineINT_CLR 0
//Globale afbrydelsesindstillinger
#defineINT_GLOBAL_ENABLE(on) EA=(!! på)
//Definér bruddet
#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
/*Tilladte afbrydelser
-----------------------------------------*/
#defineINT_ENABLE(inum, på)
gøre{
hvis (inum==INUM_RFERR) { RFERRIE = on; }
ellers hvis(inum==INUM_ADC) { ADCIE = på; }
ellers hvis(inum==INUM_URX0) { URX0IE = on; }
ellers hvis(inum==INUM_URX1) { URX1IE = on; }
ellers hvis(inum==INUM_ENC) { ENCIE = på; }
ellers hvis(inum==INUM_ST) { STIE = på; }
ellers hvis(inum==INUM_P2INT) { (on) ? (IEN2 |=0x02) : (IEN2 &= ~0x02); }
ellers hvis(inum==INUM_UTX0) { (on) ? (IEN2 |=0x04) : (IEN2 &= ~0x04); }
ellers hvis(inum==INUM_DMA) { DMAIE = på; }
ellers hvis(inum==INUM_T1) { T1IE = på; }
ellers hvis(inum==INUM_T2) { T2IE = on; }
ellers hvis(inum==INUM_T3) { T3IE = on; }
ellers hvis(inum==INUM_T4) { T4IE = på; }
ellers hvis(inum==INUM_P0INT) { P0IE = på; }
ellers hvis(inum==INUM_UTX1) { (on) ? (IEN2 |=0x08) : (IEN2 &= ~0x08); }
ellers hvis(inum==INUM_P1INT) { (on) ? (IEN2 |=0x10) : (IEN2 &= ~0x10); }
ellers hvis(inum==INUM_RF) { (on) ? (IEN2 |=0x01) : (IEN2 &= ~0x01); }
ellers hvis(inum==INUM_WDT) { (on) ? (IEN2 |=0x20) : (IEN2 &= ~0x20); }
}mens (0)
/*Indstil nedbrudsprioriteten
-----------------------------------------*/
#defineINT_PRIORITY(gruppe, pri)
gøre{
hvis(pri ==0) { IP0 &= ~group; IP1 &= ~gruppe; }
hvis(pri ==1) { IP0 |= gruppe; IP1 &= ~gruppe; }
hvis(pri ==2) { IP0 &= ~group; IP1 |= gruppe; }
hvis(pri ==3) { IP0 |= gruppe; IP1 |= gruppe; }
}mens (0)
//Værdien af parameteren pri er: 0/1/2/3 (højeste prioritet)
//Værdien af parametergruppen er:
#defineRFERR_RF_DMA 0x01//Gruppe IP0
#defineADC_P2INT_T1 0x02//Gruppe IP1
#defineURX0_UTX0_T2 0x04//Gruppe IP2
#defineURX1_UTX1_T3 0x08//Gruppe IP3
#defineENC_P1INT_T4 0x10//Gruppe IP4
#defineST_WDT_P0INT 0x20//Gruppe IP5
/*Få afbrydelsesflaget
-----------------------------------------*/
#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
)
/*Sæt interrupt-flaget
-----------------------------------------*/
#defineINT_SETFLAG(Inum, F)
gøre{
hvis (inum==INUM_RFERR) { RFERRIF= f; }
ellers hvis(inum==INUM_ADC) { ADCIF = f; }
ellers hvis(inum==INUM_URX0) { URX0IF = f; }
ellers hvis(inum==INUM_URX1) { URX1IF = f; }
ellers hvis(inum==INUM_ENC) { ENCIF_1 = ENCIF_0 = f; }
ellers hvis(inum==INUM_ST) { STIF = f; }
ellers hvis(inum==INUM_P2INT) { P2IF = f; }
ellers hvis(inum==INUM_UTX0) { UTX0IF= f; }
ellers hvis(inum==INUM_DMA) { DMAIF = f; }
ellers hvis(inum==INUM_T1) { T1IF = f; }
ellers hvis(inum==INUM_T2) { T2IF = f; }
ellers hvis(inum==INUM_T3) { T3IF = f; }
ellers hvis(inum==INUM_T4) { T4IF = f; }
ellers hvis(inum==INUM_P0INT) { P0IF = f; }
ellers hvis(inum==INUM_UTX1) { UTX1IF= f; }
ellers hvis(inum==INUM_P1INT) { P1IF = f; }
ellers hvis(inum==INUM_RF) { (f) ? (S1CON |=0x03) : (S1CON &= ~0x03); }
ellers hvis(inum==INUM_WDT) { WDTIF = f; }
}mens (0)
[url=] [/url]
[url=] [/url]
/***********************************************************
Seriel port
***********************************************************/
//Værdien af BAUD_E svarer til forskellige baudhastigheder
#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 )
//Værdien af BAUD_M svarer til forskellige baudrater
#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)
/*Seriel portkonfiguration i UART-tilstand
-----------------------------------------*/
#defineUART_SETUP(uart, receiveEnable, baudRate, options)
gøre{
hvis((uart) ==0){
hvis(PERCFG &0x01){
P1SEL |=0x30;
}ellers{
P0SEL |=0x0C;
}
}
ellers{
hvis(PERCFG &0x02){
P1SEL |=0xC0;
}ellers{
P0SEL |=0x30;
}
}
U##uart##GCR = BAUD_E((baudRate),CLKSPD);
U##uart##BAUD = BAUD_M(baudRate);
U##uart##CSR |=0x80;
U##uart##CSR |= modtagEny;
U##uart##UCR |= ((muligheder) |0x80);
}mens(0)
//Værdien af parameteren receiveAktiver:
#defineUART_RECEIVE_ENABLE 0x40 //Modtagelse af tilladelse
#defineUART_RECEIVE_DISABLE 0x00
//Værdien af parametermulighederne:
#defineFLOW_CONTROL_ENABLE 0x40 //Flowkontrol
#defineFLOW_CONTROL_DISABLE 0x00
#defineEVEN_PARITY 0x20 //Lejlighedsvis verifikation
#defineODD_PARITY 0x00 //Underlig verifikation
#defineNINE_BIT_TRANSFER 0x10 //9-byte overførsel
#defineEIGHT_BIT_TRANSFER 0x00 //8-byte overførsel
#definePARITY_ENABLE 0x08 //Paritetstjek-aktivering
#definePARITY_DISABLE 0x00
#defineTWO_STOP_BITS 0x04 //2-positioners stopposition
#defineONE_STOP_BITS 0x00 //1 stopposition
#defineHIGH_STOP 0x02 //Stopniveauet er højt
#defineLOW_STOP 0x00 //Stoppositionen er lav
#defineHIGH_START 0x01 //Startbitniveauet er højt
#defineLOW_START 0x00 //Startbitniveauet er lavt
//Seriell port sender tegn
#defineUART_SEND(uart,data)
gøre{
mens(U##uart##CSR &0x01);
U##uart##DBUF = data;
}mens (0)
#defineUART0_SEND(data) UART_SEND(0,data)
#defineUART1_SEND(data) UART_SEND(1,data)
//Seriell port modtager tegn
#defineUART_RECEIVE(uart,data)
gøre{
mens(! (U##uart##CSR&0x04));
data=U##uart##DBUF;
}mens(0)
#defineUART0_RECEIVE(data) UART_RECEIVE(0,data)
#defineUART1_RECEIVE(data) UART_RECEIVE(1,data)
[url=] [/url]
[url=] [/url]
/***********************************************************
Strøm- og clockstyring
***********************************************************/
//Få clock-crossoveren
#defineCLKSPD (CLKCON & 0x07)
//Indstil strømtilstanden
#defineSET_POWER_MODE(tilstand)
gøre{
hvis(mode ==0) { SØVN &= ~0x03; }
ellers hvis(mode ==3) { SØVN |=0x03; }
ellers{ SLEEP &= ~0x03; SLEEP |= tilstand; }
PCON |=0x01;
ASM("NOP");
}mens (0)
//Parametertilstanden sættes til følgende værdier:
#definePOWER_MODE_0 0x00
#definePOWER_MODE_1 0x01
#definePOWER_MODE_2 0x02
#definePOWER_MODE_3 0x03
//Bruges til at detektere stabiliteten af højfrekvente RC-oscillatorer
#defineHIGH_FREQUENCY_RC_OSC_STABLE (SOV & 0x20)
//Bruges til at detektere den stabile tilstand af krystaloscillatoren
#defineXOSC_STABLE (SOV & 0x40)
//Få tikfrekvensværdien for timeren
#defineTICKSPD ((CLKCON & 0x38) >> 3)
//Indstil hovedclockfrekvensen
#defineSET_MAIN_CLOCK_SOURCE(kilde)
gøre{
hvis(kilde) {
CLKCON |=0x40;
mens(! HIGH_FREQUENCY_RC_OSC_STABLE);
hvis(TICKSPD ==0){
CLKCON |=0x08;
}
SØVN |=0x04;
}
ellers{
SOV &= ~0x04;
mens(! XOSC_STABLE);
ASM("NOP");
CLKCON &= ~0x47;
SØVN |=0x04;
}
}mens (0)
//Værdien af parameterkilden er:
#defineCRYSTAL 0x00 //Krystaloscillator
#defineRC 0x01 //RC-oscillator
[url=] [/url]
[url=] [/url]
/***********************************************************
Timer 1
***********************************************************/
//Timer 1 tillader count-overflow at afbryde
#defineTIMER1_ENABLE_OVERFLOW_INT(Val)
(TIMIF = (val) ? TIMIF |0x40: TIMIF & ~0x40)
//Sæt overflow-interruptflaget for timer 1
#defineTIMER1_OVERFLOW_INT_SETFLAG(f) (T1CTL= ((T1CTL & (~0x10)) | f))
//Timer 1 starter
#defineTIMER1_RUN(værdi) (T1CTL = (værdi) ? T1CTL|0x02 : T1CTL&~0x03)
//Indstil ur-divisionen for timeren
#defineSET_TIMER_TICK(værdi) do{ CLKCON = ((CLKCON & (~0x38)) | værdi); } mens (0)
//Værdien af værdien er:
#defineTIMER1_TICK_32M 0x00 //32MHz
#defineTIMER1_TICK_16M 0x08 //16 MHz, standardværdien for systemnulstilling
#defineTIMER1_TICK_8M 0x10 //8 MHz
#defineTIMER1_TICK_4M 0x18 //4MHz
#defineTIMER1_TICK_2M 0x20 //2 MHz
#defineTIMER1_TICK_1M 0x28 //1 MHz
#defineTIMER1_TICK_500k 0x30 //500kHz
#defineTIMER1_TICK_250k 0x38 //250kHz
//Indstil TICK-delefiltret til timer 1
#defineSET_TIMER1_TICKDIV(værdi)
gøre{
T1CTL &= ~0x0c;
T1CTL |= værdi;
}mens (0)
//hvor værdien er:
#defineTIMER1_TICKDIV_1 0x00 //1 division
#defineTIMER1_TICKDIV_8 0x04 //8-vejs frekvens
#defineTIMER1_TICKDIV_32 0x08
#defineTIMER1_TICKDIV_128 0x0c
//Indstil timerens overløbsperiode
#defineSET_TIMER1_PERIOD(værdi)
gøre{
T1CC0H = HIGH_BYTE(værdi);
T1CC0L = LOW_BYTE(værdi);
}mens (0)
//Indstil driftstilstanden for Timer 1
#defineSET_TIMER1_MODE(tilstand)
gøre{
T1CTL = ((T1CTL & (~0x03)) | mode);
}mens (0)
//Værdien af mode er:
#defineTIMER1_MODE_STOP 0x00
#defineTIMER1_MODE_FREE 0x01
#defineTIMER1_MODE_MODULE 0x02
#defineTIMER1_MODE_UPDOWN 0x03
[url=] [/url]
[url=] [/url]
/***********************************************************
Vagthund
***********************************************************/
//Indstil overløbsperioden for watchdog-timeren
#defineWDT_SET_TIMEOUT_PERIOD(timeout)
gøre{ WDCTL &= ~0x03; WDCTL |= timeout; }mens (0)
//Værdien af parameter-timeouten er:
#defineSEC_1 0x00 //Efter 1 sekund
#defineM_SEC_250 0x01 //efter 250 ms
#defineM_SEC_15 0x02 //Efter 15 ms
#defineM_SEC_2 0x03 //Efter 2 ms
//Hundefodringsprocedurer
#defineWDT_RESET() do {
WDCTL = (WDCTL & ~0xF0) |0xA0;
WDCTL = (WDCTL & ~0xF0) |0x50;
} mens (0)
//Start/stop vagthundens timer
#defineWDT_ENABLE() WDCTL |= 0x08
#defineWDT_DISABLE() WDCTL &= ~0x08
[url=] [/url]
[url=] [/url]
/***********************************************************
ADC
***********************************************************/
//Konfigurér en enkelt ADC
#defineADC_SINGLE_CONVERSION(indstillinger)
gøre{ ADCCON3 = indstillinger; }mens(0)
//Parameterindstillingen består af følgende kombinationer:
//Referencespænding
#defineADC_REF_1_25_V 0x00 //Intern 1,25V referencespænding
#defineADC_REF_P0_7 0x40 //Ekstern referencespænding på AIN7-pinnen
#defineADC_REF_AVDD 0x80 //AVDD_SOC Nåle
#defineADC_REF_P0_6_P0_7 0xC0 //AIN6-AIN7 Ekstern referencespænding til differentialindgange
//Prøvetakningsrate
#defineADC_8_BIT 0x00 //8. plads
#defineADC_10_BIT 0x10 //10. plads
#defineADC_12_BIT 0x20 //12. plads
#defineADC_14_BIT 0x30 //14. plads
//Træd ind i kanalen
#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 //Land
#defineADC_TEMP_SENS 0x0E //In-chip temperatursensor
#defineADC_VDD_3 0x0F //VDD/3
ADC-konverteringen er færdig
#define ADC_SAMPLE_READY() (ADCCON1 & 0x80)
#endif
//启动ADC转化
#define ADC_START()
do { ADCCON1 |= 0x40; } mens (0)//Vælg trigger-tilstanden på ADC'en som manuel (dvs. ADC_SAMPLE_READY)
#defineADC_STOP()
gøre{ ADCCON1 |=0x30; }mens (0)[url=] [/url]
(2) Funktionelt modullag
[url=] [/url]
/***********************************************************
*Filnavn: module.h
*Forfatter: hustlzp
*Dato: 6. marts 2011
*Version: 1.0
*Funktionsbeskrivelse: Funktionsmodullags headerfil
*Funktionsliste: void led_init()
tomrum timer1_init()
tomrum uart0_init(tomrum);
void Uart0SendString (usigneret tegn *s);
float adc_start(tomrum)
void get_temperature(usigneret char *output, flydende temperatur);
tomrum watchdog_init(tomrum);
*Ændrede optegnelser:
***********************************************************/
#ifndef MODULE_H
#defineMODULE_H
#include"hal.h"
/***********************************************************
LED
***********************************************************/
//Definér LED-benene
#defineled1 P1_0
#defineled2 P1_1
#defineled3 P1_2
#defineled4 P1_3
//LED-lys og sluk
#defineLED_OFF 1
#defineLED_ON 0
//LED-initialisering
tomrumled_init(tomrum);
/***********************************************************
timer1
***********************************************************/
//Bruges til at sætte overflow-periodens værdi for timeren
#defineTIMER1_OVF_2SEC 0xF424 //2'ere
#defineTIMER1_OVF_1SEC 0x7A12 //1'ere
#defineTIMER1_OVF_dot5SEC 0x3D09 //0,5 sekunder
//Timer 1 initialiserer
tomrum timer1_init(tomrum);
/***********************************************************
UART0
***********************************************************/
//UART0-initialisering
tomrum uart0_init(tomrum);
//Seriel port transmissionsstreng
tomrum Uart0SendString(usigneret)Char*s);
/***********************************************************
ADC-14
***********************************************************/
//Bruges til at konvertere de data, ADC'en opnåede, til Celsius-temperatur
#defineADC_TO_CELSIUS(midlertidigt) (temp * 0,06229 - 311,43)
//Start ADC-konvertering
Floatadc_start(tomrum);
//Ombygning
tomrum get_temperature(usigneret)Char*output,Floatmidlertidigt);
/***********************************************************
WatchDog
***********************************************************/
//Vagthundsinitialisering
tomrum watchdog_init(tomrum);
#endif
[url=] [/url]
[url=] [/url]
/***********************************************************
*Filnavn: module.c
*Forfatter: hustlzp
*Dato: 2011/3/11
*Version: 1.0
*Funktionsbeskrivelse: Kildefil til funktionelt modullag
*Funktionsliste: (udeladt)
*Ændrede optegnelser:
***********************************************************/
#include"module.h"
/***********************************************************
*Funktionsnavn: led_init
*Funktionsfunktion: LED-initialisering
*Indgangsparametre: Ingen
*Eksportparametre: Ingen
***********************************************************/
tomrumled_init(tomrum)
{
//Konfigurér P1.0, P1.1, P1.2 og P1.3 som generelle I/O-porte
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);
//Konfigurer P1.0, P1.1, P1.2 og P1.3 som output
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;
}
/***********************************************************
*Funktionsnavn: timer1_init
* Funktionsfunktion: Timer 1 initialisering
*Indgangsparametre: Ingen
*Eksportparametre: Ingen
***********************************************************/
tomrumtimer1_init(tomrum)
{
INT_GLOBAL_ENABLE(INT_ON); //Åbn den globale afbrydelse
INT_ENABLE(INUM_T1, INT_ON); //Åben T1-afbrydelse
TIMER1_ENABLE_OVERFLOW_INT(INT_ON); //Åben T1 tælleoverløbsafbrydelse
SET_TIMER_TICK(TIMER1_TICK_4M); //Sæt timerens TICK til 4 MHz
SET_TIMER1_PERIOD(TIMER1_OVF_2SEC); //Sæt tælleperioden for T1 til 2 sekunder
SET_TIMER1_TICKDIV(TIMER1_TICKDIV_128); //Indstil ur-crossoveren for T1 til 128
SET_TIMER1_MODE(TIMER1_MODE_MODULE); //Sæt kørselstilstanden for T1 til modul
}
/***********************************************************
*Funktionsnavn: uart0_init
*Funktionsfunktion: Seriel port UART0 initialisering
*Indgangsparametre: Ingen
*Eksportparametre: Ingen
***********************************************************/
tomrumuart0_init(tomrum)
{
//Vælg UART-lokationen
IO_PER_LOC_UART0_AT_PORT0_PIN2345();
//Konfigurer UART: Modtagelse tilladt, 115200 bps, én-bit stopbit, ingen paritet
UART_SETUP(0, UART_RECEIVE_ENABLE,115200, ONE_STOP_BITS | PARITY_DISABLE);
//Åbn den totale afbrydelse
INT_GLOBAL_ENABLE(INT_ON);
//Åbn seriel port 0 for at modtage afbrydelser
INT_ENABLE(INUM_URX0, INT_ON);
}
/***********************************************************
*Funktionsnavn: Uart0SendString
* Funktionsfunktion: Timer 1 initialisering
*Indgangsparameter: usigneret tegn *s
Den streng, du vil sende
*Eksportparametre: Ingen
***********************************************************/
tomrumUart0SendString(usigneret)Char*s)
{
mens(*s !=0)
UART0_SEND(*s++);
}
/***********************************************************
*Funktionsnavn: adc_start
*Funktionsfunktion: Start ADC-konvertering
*Indgangsparametre: Ingen
*Eksportparameter: flydende
Temperaturværdien i tabletten
***********************************************************/
Floatadc_start(tomrum)
{
UsigneretintTemp;
//Referencespændingen er 1,25V, prøvetagningsnøjagtigheden er 14 bit, og konverteringsmålet er den indbyggede temperatursensor
ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);
ADC_STOP(); //Indstil trigger-metoden for ADC-konvertering til manuel
ADC_START(); //Start ADC-konvertering
mens(! ADC_SAMPLE_READY()); //Vent på, at konverteringen er færdig
temp = ADCL >>2; //Gem konverteringen resulterer i temp
temp |= (((usigneretint) ADCH) <<6);
TilbagevendenADC_TO_CELSIUS(midlertidigt); //Returnerer den faktiske temperaturværdi efter omregning
}
/***********************************************************
*Funktionsnavn: get_temperature
*Funktionsfunktion: Behandl temperaturværdien og gem den i tegnarrayet til seriel output
*Indgangsparameter: usigneret char *output
Bruges til at gemme den konverterede temperaturværdi
Flydetemperatur
Celsius-temperaturværdi
*Eksportparametre: Ingen
***********************************************************/
tomrumget_temperature(usigneret)Char*output,Floatmidlertidigt)
{
output[0] = (usigneretChar(midlertidig) /10 + 48; //Ti steder
output[1] = (usigneretChar(midlertidigt) %10 + 48; //Enkeltcifret
output[2] ='.'; //Decimalpunkt
output[3] = (usigneretChar(midlertidigt)10) %10 + 48; //Tiende
output[4] = (usigneretChar(midlertidigt)100) %10 + 48; //Percentil
output[5] =''; //Strengendifiere
}
/***********************************************************
*Funktionsnavn: watchdog_init
*Funktionsfunktion: Initialisering af vagthunden
*Indgangsparametre: Ingen
*Eksportparametre: Ingen
***********************************************************/
tomrumwatchdog_init(tomrum)
{
WDT_SET_TIMEOUT_PERIOD(SEC_1); //Sæt timeout-tiden til 1 sekunder
WDT_ENABLE(); //Start vagthunden
}
[url=] [/url]
(3) Applikationslag
[url=] [/url]
/*******************************************************************
Filnavn: main.c
Forfatter: hustlzp
Dato: 2011/3/11
Version: 1.0
Funktionsbeskrivelse: Masterprogramfil
Funktionsliste: (udeladt)
Modifikationsrapport:
*******************************************************************/
#include
/********************************************************************
Afbrydelsesserviceprocedurer
********************************************************************/
/* 定时器1溢出中断子程序
-------------------------------------------------------*/
#pragma vektor=T1_VECTOR
__interrupt void T1_ISR(void)
{
EA=0; Porten er afbrudt
led2 = LED_ON;
get_temperature(output,adc_start()); Konverter temperaturværdien til et array af tegn, der skal outputtes
Uart0SendString(output); Udgangstemperaturværdi
Uart0SendString("°C");
led2
/* 串口接收中断子程序
-------------------------------------------------------*/
#pragma vektor=URX0_VECTOR
__interrupt tomrum RE_ISR(tomrum)
{
EA=0;
led3 = LED_ON;
modtage = U0DBUF;
if(type==1) // type=1, hvilket indikerer, at det modtagne tegn bruges til at indstille timer-overløbsperioden
{
type=0;
Skift (modtag)
{
tilfælde '0': // Timer-overløbsperioden er 0,5 sekunder
{
SET_TIMER1_PERIOD(TIMER1_OVF_dot5SEC);
pause;
}
tilfælde '1': // Timer-overløbsperioden er 1s
{
SET_TIMER1_PERIOD(TIMER1_OVF_1SEC);
pause;
}
tilfælde '2': // Timer-overløbsperioden er 2 sekunder
{
SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
pause;
}
}
}
else if(type==2) // type=2, hvilket indikerer, at de modtagne tegn bruges til søvnkontrol
{
type=0;
led1 = LED_OFF;
led2 = LED_OFF;
led3 = LED_OFF;
Skift (modtag)
{
Kasse '1': // Gå ind i strømtilstand PM1
{
SET_POWER_MODE(1);
pause;
}
Case '2': // Indgå strømtilstand PM2
{
SET_POWER_MODE(2);
pause;
}
kasse '3': //Indgå strømtilstand PM3
{
SET_POWER_MODE(3);
pause;
}
}
}
else if(type==0) // type=0, hvilket indikerer, at det modtagne tegn er typen af kontrolkommando: @ eller $
{
if(receive=='@')
{
type=1; '@' modtages for at angive, at det næste tegn bruges til at sætte overløbsperioden
}
else hvis(modtager=='$')
{
type=2; '$' modtages, hvilket indikerer, at det næste tegn bruges til system-søvnkontrol
}
}
led3 = LED_OFF;
EA=1;
}
=LED_OFF;
TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR); Fjern afbrydelsesskiltet
EA=1; Åben afbrydelse
}
/* 主函数
-------------------------------------------------------*/
Void main(void)
{
SET_MAIN_CLOCK_SOURCE(KRYSTAL); Sæt systemclocket til 32MHz krystaloscillator
led_init(); LED-initialisering
uart0_init(); Seriel port UART0 initialisering
timer1_init(); Timer 1 initialiserer
watchdog_init(); Vagthundsinitialisering
mens (1)
{
WDT_RESET(); Fodr hunden konstant
}
}/********************************************************************
Hovedprogram
********************************************************************/
/* 全局变量
-------------------------------------------------------*/
usigneret karakteroutput[6]={0}; Temperaturdata gemmes for nem seriel output
usigneret char modtager; Gem de modtagne tegn
usigneret karaktertype=0; Typeflaget for det modtagne tegn sættes til 0/1/2"module.h"[url=] [/url]
5. TestningÅh~ Koden er endelig indsat, det er virkelig udmattende, lad os teste dette lille system:
(1) Tidsbestemt prøvetagning
Åbn den serielle port, start IAR-fejlfinding, og find ud af, at LED1 er tændt, og temperaturværdien på det serielle portværktøj genereres konstant, og prøvetagningsintervallet bestemmes til at være 2 sekunder:
(2) Kontrol af prøvetagningsinterval
Indtast "@1" i serielportværktøjet, og test derefter prøvetagningsintervallet, og find ud af, at det er blevet 1s; Indtast "@0", og prøvetagningsintervallet er ændret til 0,5 sekunder.
(3) Søvnkontrol
Indtast "$1" i serielportværktøjet og se, at alle LED'er er slukket, og temperaturprøvningen er stoppet:
Efter testning fungerer systemet normalt og stabilt og opfylder grundlæggende kravene.
Studerende, der har brug for kildekodeKlik her for at downloade
6. KonklusionDenne artikel tager et let omfattende eksperiment som eksempel for at vise, hvordan man integrerer CC2430 on-chip ressourcer for at skrive et relativt standardiseret lille system. Om et par dage vil jeg tage mig tid til at skrive en simpel brugermanual til hal.h, så jeg og alle andre nemt kan betjene CC2430.
Dernæst vil jeg færdiggøre min research om CC2430 on-chip ressourcer og dedikere mig til at lære TI Z-Stack protokolstakken~
Blogindlægget i denne serie er for nu slut, men Zigbees rejse vil fortsætte. Udsigten forude er ukendt, men jeg tror, at forfatteren vil overvinde forhindringer med alle og smage op- og nedture, og der vil være gevinster.
Følg med: "Bliv med i TI Z-Stack" blogindlæg!