Tento článek je zrcadlovým článkem o strojovém překladu, klikněte zde pro přechod na původní článek.

Pohled: 10835|Odpověď: 1

Zigbee Journey (10): Komplexní experiment – systém měření teploty založený na CC2430

[Kopírovat odkaz]
Zveřejněno 30.10.2014 23:47:44 | | | |
Po napsání knihy "Zigbee Journey (9)" 3. března původně autor plánoval okamžitě začít psát malý experiment o "systému monitorování teploty" jako shrnutí řady rozptýlených poznatků dříve. Nicméně jsem si také uvědomil, že ačkoliv byl každý z předchozích malých experimentů podrobně popsán, normativní a strukturální povaha jeho kódu by mohla být nesnesitelná. Jelikož jde o shrnutí, měli bychom postupovat na původním základě, místo abychom mechanicky skládali předchozí drobné body znalostí. Proto jsem svůj původní plán odložil, věnoval čas naučení se obecným technikám embedded vývoje a napsal dvě esejeSpecifikace programování v embedded C51" a "Hierarchie struktury vestavěného projektového kódu》。 Tento záznam není jen shrnutím první cesty Zigbee, ale také zahrnuje autorovy zkušenosti z posledních dnů, aby byl užitečný pro začátečníky v Zigbee.
Celý text je organizován podle základního procesu vývoje softwaru: analýza požadavků, návrh osnov, detailní návrh, implementace kódu a testování.
1. Analýza poptávky
Po diskusi mezi "zákazníkem" a "vývojářem" byl určen následující popis systémové funkce:
… Aktuální teplotu v místnosti zaznamenávají uzly založené na CC2430 a její teplotní hodnoty lze sledovat pomocí PC
… Samotný uzel CC2430 musí mít určitou míru stability a může se automaticky vrátit do normálního stavu
… Interval vzorkování a správu energie uzlu lze ovládat PC
2. Návrh osnov
Podle výše uvedené analýzy požadavků můžeme systém rozdělit do dvou modulů:Uzel CC2430aPC
  [Uzel CC2430]  
… Externí parametry lze pravidelně sbírat a posílat do PC
… Automatický reset při vypnutí stroje
… Příkazy z PC lze přijímat a zpracovávat podle toho: změnit interval vzorkování/správu energie
  [PC]  
… C stroj přijímá a zobrazuje data prostřednictvím nástroje sériového portu
… Instrukce lze posílat mikrokontroléru prostřednictvím nástroje sériového portu pro řízení rychlosti vzorkování a správy energie
3. Detailní návrh
(1) Struktura kódu
Vrstvení kódové struktury tohoto systému bylo skutečně popsáno v eseji "Hierarchie struktury vestavěného projektového kódu", a kopie je následující:
(1) Vrstva hardwarové abstrakce
      [ioCC2430.h] (Systém zahrnut)Všechny SFR a přerušovací vektory CC2430 jsou definovány
      [hal.h] Zahrnuje definice běžných typů, společná alokační makra a společnou konfiguraci zdrojů CC2430 na čipu (I/O, sériová komunikace, ADC, časovač, správa energie atd.)
  (2) Funkční vrstva modulů
      [module.h] definuje zdroje na čipu (časovače, I/O), rozšiřující moduly mimo čip (LED) a deklarace souvisejících funkcí
      [module.cImplementujte inicializaci každého modulu (LED).
  (3) Aplikační vrstva
      [main.cPro dosažení specifických požadavků aplikace, jako je měření teploty, interkomunikace s PC a vypínání a reset, se odkazujte na hal.h, ioCC2430.h a module.h.
(2) Metody implementace každého modulu
Podle modulů rozdělených podle osnovního návrhu lze vnitřní systém rozdělit na dva hlavní moduly:Uzel CC2430aPC
Protože na PC jsou nástroje pro komunikaci se sériovým portem, jeho funkce splňují požadavky, takže tuto část PC nemusíme dělat a není třeba ji analyzovat. Pojďme si níže povědět o sekci CC2430
Metoda implementace každé podfunkce bodu:
… Použijte přerušení přetečení časovače k vyvolání časovaného vzorkování
… Režim UART0 se sériovým portem přenáší teplotní data do PC
… Vestavěný watchdog obvod CC2430 slouží k realizaci automatické resetovací funkce systému
… Sériový port slouží k přijímání přerušení pro zachycení a reakci na řídicí příkazy z PC
1) Pokud je přijato@Znak je příkaz pro řízení vzorkovacího intervalu, následovaný číslem označujícím vzorkovací interval: 0-0,5s, 1-1s, 2-2s
如:@0,表示每隔0.5秒采样一次。
2) Pokud je přijato$  Znak je příkaz pro ovládání spánku, následovaný číslem označujícím režim napájení
Například: $3, což znamená přepnout systém do režimu napájení 3.
(3) Programový diagram
  • Diagram toku magisterského programu
  • Diagram přerušení přerušení programu Timer 1
  • Diagram postupu přerušení příjmu sériového portu




4. Implementace kódování
(1) Vrstva hardwarové abstrakce
Vrstva hardwarové abstrakce zahrnuje ioCC2430.h a hal.h. Protože první systém je součástí tohoto systému, nebude uveden.
Následuje seznam všech obsahu hal.h (protože je tento soubor příliš dlouhý a vypadá nevhodně, ukážu ho v modulech):
  • hlava
  • Vstupně/výstupní porty
  • Přerušeno
  • Sériový port
  • Správa napájení a hodin
  • Časovač
  • Hlídací pes
  • ADC
[url=] [/url]
/***********************************************************
*Název souboru: hal.h
*Autor: hustlzp
*Datum: 8. března 2011
*Vydání: 1.1
*Popis funkce: Hardwarová abstrakční vrstva
*Upravené záznamy:
**********************************************************
*/


#ifndef HAL_H
#defineHAL_H


#include


/***********************************************************
                       Běžné definice typů
**********************************************************
*/
Typedef bez podepsáníchar   BYTE;
Typedef bez podepsáníint    SLOVO;
Typedef bez podepsánídlouhý   DWORD;



/***********************************************************
                       Běžně používané makrodefinice
**********************************************************
*/

//O 8 míst výše
#defineHIGH_BYTE(a) ((BYTE) (((WORD)(a)) >> 8))


//O 8 míst níže
#defineLOW_BYTE(a) ((BYTE) ((WORD)(a)))


//Přiřazení
#defineSET_WORD(regH,regL,word)  
   dělat{                           
      (regH)=HIGH_BYTE(slovo);     
      (regL)=LOW_BYTE(slovo);      
   }zatímco(0)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Vstupně/výstupní porty
**********************************************************
*/
/*Konfigurace směru vstupně/výstupního portu
-----------------------------------------
*/
#defineIO_DIR_PORT_PIN(port, pin, režie)  
   dělat{                                 
      pokud(režie == IO_OUT)                 
         P##port##DIR |= (0x01<<(pin));  
      jinak                              
         P##port##DIR &= ~(0x01<<(pin));
   }zatímco(0)



//Hodnota parametru dir je:
#defineIO_IN 0
#defineIO_OUT 1


/*Nastavte vstupní režim I/O portu
-----------------------------------------
*/
#defineIO_IMODE_PORT_PIN(port, pin, imode)
   dělat{                                    
      pokud(imode == IO_IMODE_TRI)            
         P##port##INP |= (0x01<<(pin));     
      jinak                                 
         P##port##INP &= ~(0x01<<(pin));   
   }zatímco (0)



#define IO_PUD_PORT(portské, pud)        
   do {                              
      if (pud == IO_PULLDOWN)         
         P2INP |= (0x01 << (port+5));
      jinak                           
         P2INP &= ~(0x01 << (port+5));
   } zatímco (0)


Hodnota parametru PUD je:
#define IO_PULLUP 0 // Zvedni se
#define IO_PULLDOWN 1 // Stáhnout dolů


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

#define IO_FUNC_PORT_PIN(port, pin, func)  
   do {                                    
      if((port == 2) && (pin == 3)){      
         pokud (func) {                       
            P2SEL |= 0x02;                 
         } jinak {                          
            P2SEL &= ~0x02;               
         }                                 
      }                                    
      jinak if((port == 2) && (pin == 4)){  
         pokud (func) {                       
            P2SEL |= 0x04;                 
         } jinak {                          
            P2SEL &= ~0x04;               
         }                                 
      }                                    
      else{                                
         pokud (func) {                       
            P##port##SEL |= (0x01<<(pin));
         } jinak {                          
            P##port##SEL &= ~(0x01<<(pin));
        }                                 
      }                                    
   } zatímco (0)


Hodnota parametru func je:
#define IO_FUNC_GIO 0 // Obecné vstupy/výstupy
#define IO_FUNC_PERIPH 1 // Periferní vstup/výstup


Konfigurace umístění periferního I/O
#define IO_PER_LOC_TIMER1_AT_PORT0_PIN234() do { PERCFG = (PERCFG&~0x40)|0x00; } zatímco (0)
#define IO_PER_LOC_TIMER1_AT_PORT1_PIN012() do { PERCFG = (PERCFG&~0x40)|0x40; } zatímco (0)

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

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

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

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

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

#define IO_PER_LOC_UART0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x00; } zatímco (0)
#define IO_PER_LOC_UART0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x01; } zatímco (0)

//Hodnota parametru imode je:
#defineIO_IMODE_PUD 0   //Zvednout/stáhnout dolů
#defineIO_IMODE_TRI 1   //Tři státy[url=] [/url]

[url=] [/url]
/***********************************************************
                       Přerušeno
**********************************************************
*/
//Pro přerušení zapnuto/vypnuto
#defineINT_ON 1
#defineINT_OFF 0


//Používá se k umisťování/mazání příznaků přerušení
#defineINT_SET 1
#defineINT_CLR 0


//Globální nastavení přerušení
#defineINT_GLOBAL_ENABLE(on) EA=(!! zapnuto)


//Definujte přerušení
#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
#define9 INUM_T1
#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é přerušení
-----------------------------------------
*/
#defineINT_ENABLE(inum, dál)                        
   dělat{                                             
      pokud      (inum==INUM_RFERR) { RFERRIE = zapnuto; }  
      jinak pokud(inum==INUM_ADC)   { ADCIE = zapnuto; }  
      jinak pokud(inum==INUM_URX0)  { URX0IE = zapnuto; }  
      jinak pokud(inum==INUM_URX1)  { URX1IE = zapnuto; }  
      jinak pokud(inum==INUM_ENC)   { ENCIE = zapnuto; }  
      jinak pokud(inum==INUM_ST)    { STIE = zapnuto; }  
      jinak pokud(inum==INUM_P2INT) { (zapnuto)? (IEN2 |=0x02) : (IEN2 &= ~0x02); }
      jinak pokud(inum==INUM_UTX0)  { (zapnuto)? (IEN2 |=0x04) : (IEN2 &= ~0x04); }
      jinak pokud(inum==INUM_DMA)   { DMAIE = zapnuto; }  
      jinak pokud(inum==INUM_T1)    { T1IE = zapnuto; }  
      jinak pokud(inum==INUM_T2)    { T2IE = zapnuto; }  
      jinak pokud(inum==INUM_T3)    { T3IE = zapnuto; }  
      jinak pokud(inum==INUM_T4)    { T4IE = zapnuto; }  
      jinak pokud(inum==INUM_P0INT) { P0IE = zapnuto; }  
      jinak pokud(inum==INUM_UTX1)  { (zapnuto)? (IEN2 |=0x08) : (IEN2 &= ~0x08); }
      jinak pokud(inum==INUM_P1INT) { (zapnuto)? (IEN2 |=0x10) : (IEN2 &= ~0x10); }
      jinak pokud(inum==INUM_RF)    { (zapnuto)? (IEN2 |=0x01) : (IEN2 &= ~0x01); }
      jinak pokud(inum==INUM_WDT)   { (zapnuto)? (IEN2 |=0x20) : (IEN2 &= ~0x20); }
   }zatímco (0)


/*Nastavte prioritu výpadku
-----------------------------------------
*/
#defineINT_PRIORITY(skupina, pri)                     
   dělat{                                               
      pokud(pri ==0) { IP0 &= ~skupina; IP1 &= ~skupina; }
      pokud(pri ==1) { IP0 |= skupina; IP1 &= ~skupina; }
      pokud(pri ==2) { IP0 &= ~skupina; IP1 |= skupina; }
      pokud(pri ==3) { IP0 |= skupina; IP1 |= skupina; }
   }zatímco (0)

//Hodnota parametru pri je: 0/1/2/3 (nejvyšší priorita)


//Hodnota skupiny parametrů 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ískejte přerušovací vlajku
-----------------------------------------
*/
#defineINT_GETFLAG(inum) (                       
   (inum==INUM_RFERR) ? ODPOVĚĎ :
   (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 příznak přerušení
-----------------------------------------
*/
#defineINT_SETFLAG(inum, f)                     
   dělat{                                          
      pokud      (inum==INUM_RFERR) { RFERRIF= f; }
      jinak pokud(inum==INUM_ADC)   { ADCIF = f; }
      jinak pokud(inum==INUM_URX0)  { URX0IF = f; }
      jinak pokud(inum==INUM_URX1)  { URX1IF = f; }
      jinak pokud(inum==INUM_ENC)   { ENCIF_1 = ENCIF_0 = f; }
      jinak pokud(inum==INUM_ST)    { STIF = f;  }
      jinak pokud(inum==INUM_P2INT) { P2IF = f;  }
      jinak pokud(inum==INUM_UTX0)  { UTX0IF= f;  }
      jinak pokud(inum==INUM_DMA)   { DMAIF = f;  }
      jinak pokud(inum==INUM_T1)    { T1IF = f;  }
      jinak pokud(inum==INUM_T2)    { T2IF = f;  }
      jinak pokud(inum==INUM_T3)    { T3IF = f;  }
      jinak pokud(inum==INUM_T4)    { T4IF = f;  }
      jinak pokud(inum==INUM_P0INT) { P0IF = f;  }
      jinak pokud(inum==INUM_UTX1)  { UTX1IF= f;  }
      jinak pokud(inum==INUM_P1INT) { P1IF = f;  }
      jinak pokud(inum==INUM_RF)    { (f) ? (S1CON |=0x03) : (S1CON &= ~0x03); }
      jinak pokud(inum==INUM_WDT)   { WDTIF = f;  }
   }zatímco (0)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Sériový port
**********************************************************
*/
//Hodnota BAUD_E odpovídá různým rychlostem přenosu
#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 odpovídá různým rychlostem přenosu
#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)


/*Konfigurace sériového portu v režimu UART
-----------------------------------------
*/
#defineUART_SETUP(uart, receiveEnable, baudRate, options)      
   dělat{                                                         
      pokud((uart) ==0){                                          
         pokud(PERCFG &0x01){                                    
            P1SEL |=0x30;                                      
         }jinak{                                               
            P0SEL |=0x0C;                                      
         }                                                      
      }                                                         
      jinak{                                                   
         pokud(PERCFG &0x02){                                    
            P1SEL |=0xC0;                                      
         }jinak{                                               
            P0SEL |=0x30;                                      
         }                                                      
      }                                                         
                                                               
      U##uart##GCR = BAUD_E((baudRate),CLKSPD);                 
      U##uart##BAUD = BAUD_M(baudRate);                        
                                                               
      U##uart##CSR |=0x80;                                    
                                                               
      U##uart##CSR |= přijímatPovolit;                           
                                                               
      U##uart##UCR |= ((options) |0x80);                       
   }zatímco(0)
     
//Hodnota parametru ReceiveEnable:
#defineUART_RECEIVE_ENABLE 0x40   //Získání povolení
#defineUART_RECEIVE_DISABLE 0x00   
     
//Hodnota parametrových možností:
#defineFLOW_CONTROL_ENABLE 0x40   //Řízení toku
#defineFLOW_CONTROL_DISABLE 0x00


#defineEVEN_PARITY 0x20   //Občasné ověření
#defineODD_PARITY 0x00   //Podivné ověření


#defineNINE_BIT_TRANSFER 0x10   //9-bajtový přenos
#defineEIGHT_BIT_TRANSFER 0x00   //8-bajtový přenos


#definePARITY_ENABLE 0x08   //Zpřístupnění kontroly parity
#definePARITY_DISABLE 0x00

#defineTWO_STOP_BITS 0x04   //Poloha stop 2 poloh
#defineONE_STOP_BITS 0x00   //1 poloha stop


#defineHIGH_STOP 0x02   //Úroveň stop je vysoká
#defineLOW_STOP 0x00   //Poloha stop je nízká
     
#defineHIGH_START 0x01   //Počáteční úroveň bitu je vysoká
#defineLOW_START 0x00   //Počáteční úroveň bitu je nízká


//Sériový port posílá znaky
#defineUART_SEND(uart,data)            
   dělat{                                 
     zatímco(U##uart##CSR &0x01);        
       U##uart##DBUF = data;            
   }zatímco (0)
#defineUART0_SEND(data) UART_SEND(0,data)
#defineUART1_SEND(data) UART_SEND(1,data)


//Sériový port přijímá znaky
#defineUART_RECEIVE(uart,data)         
   dělat{                                 
     zatímco(! (U##uart##CSR&0x04));      
       data=U##uart##DBUF;              
   }zatímco(0)
#defineUART0_RECEIVE(data) UART_RECEIVE(0,data)
#defineUART1_RECEIVE(data) UART_RECEIVE(1,data)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Správa napájení a hodin
**********************************************************
*/
//Pořiď si clock crossover
#defineCLKSPD (CLKCON & 0x07)


//Nastavte režim napájení
#defineSET_POWER_MODE(mode)                  
   dělat{                                       
      pokud(mód ==0) { SPÁT &= ~0x03; }
      jinak pokud(mód ==3) { SPÁT |=0x03;  }
      jinak{ SPÁT &= ~0x03; SLEEP |= režim;  }
      PCON |=0x01;                           
      ASM("NOP");                              
   }zatímco (0)


//Režim parametrů je nastaven na následující hodnoty:
#definePOWER_MODE_0 0x00  
#definePOWER_MODE_1 0x01
#definePOWER_MODE_2 0x02
#definePOWER_MODE_3 0x03


//Používá se k detekci stability vysokofrekvenčních RC oscilátorů
#defineHIGH_FREQUENCY_RC_OSC_STABLE (SPÁT & 0x20)


//Používá se k detekci stabilního stavu krystalového oscilátoru
#defineXOSC_STABLE (SPÁT A 0x40)


//Získejte hodnotu frekvence tikání časovače
#defineTICKSPD ((CLKCON & 0x38) >> 3)


//Nastavte hlavní hodinovou frekvenci
#defineSET_MAIN_CLOCK_SOURCE(zdroj)
   dělat{                              
      pokud(zdroj) {                    
        CLKCON |=0x40;               
        zatímco(! HIGH_FREQUENCY_RC_OSC_STABLE);
        pokud(TICKSPD ==0){            
          CLKCON |=0x08;            
        }                             
        SPÁT |=0x04;               
      }                              
      jinak{                          
        SPÁT &= ~0x04;               
        zatímco(! XOSC_STABLE);         
        ASM("NOP");                  
        CLKCON &= ~0x47;              
        SPÁT |=0x04;               
      }                              
   }zatímco (0)


//Hodnota zdroje parametru je:
#defineKŘIŠŤÁLOVÁ 0x00   //Krystalový oscilátor
#defineRC 0x01   //RC oscilátor
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Časovač 1
**********************************************************
*/
//Časovač 1 umožňuje přerušení přetečení počtu
#defineTIMER1_ENABLE_OVERFLOW_INT(val)
   (TIMIF = (val) ? ČASOVÁNÍ |0x40: TIMIF & ~0x40)


//Nastavte příznak přerušení přetečení pro časovač 1
#defineTIMER1_OVERFLOW_INT_SETFLAG(f) (T1CTL= ((T1CTL & (~0x10)) | f))


//Startuje časovač 1
#defineTIMER1_RUN(hodnota) (T1CTL = (hodnota) ? T1CTL|0x02 : T1CTL&~0x03)


//Nastavte dělení hodin pro č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, výchozí hodnota pro 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)  
   dělat{                             
     T1CTL &= ~0x0c;               
     T1CTL |= hodnota;               
   }zatímco (0)
      
//kde hodnota je:      
#defineTIMER1_TICKDIV_1 0x00   //1 divize
#defineTIMER1_TICKDIV_8 0x04   //8-cestná frekvence
#defineTIMER1_TICKDIV_32 0x08
#defineTIMER1_TICKDIV_128 0x0c


//Nastavte časovač přetečení
#defineSET_TIMER1_PERIOD(hodnota)
   dělat{                           
     T1CC0H = HIGH_BYTE(hodnota);  
     T1CC0L = LOW_BYTE(hodnota);   
   }zatímco (0)
     
//Nastavte provozní režim Timer 1
#defineSET_TIMER1_MODE(mode)  
   dělat{                        
     T1CTL = ((T1CTL & (~0x03)) | mód);           
   }zatímco (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]
/***********************************************************
                       Hlídací pes
**********************************************************
*/
//Nastavte přetečení pro watchdog časovač
#defineWDT_SET_TIMEOUT_PERIOD(time-out)
   dělat{ WDCTL &= ~0x03; WDCTL |= time-out; }zatímco (0)


//Hodnota timeoutu parametru je:
#defineSEC_1 0x00     //po 1 sekundě
#defineM_SEC_250 0x01     //po 250 ms
#defineM_SEC_15 0x02     //Po 15 ms
#defineM_SEC_2 0x03     //Po 2 ms


//Postupy krmení psů
#defineWDT_RESET() do {           
   WDCTL = (WDCTL & ~0xF0) |0xA0;
   WDCTL = (WDCTL & ~0xF0) |0x50;
} zatímco (0)


//Spustěte/zastavte watchdog časovač
#defineWDT_ENABLE() WDCTL |= 0x08
#defineWDT_DISABLE() WDCTL &= ~0x08
[url=] [/url]

[url=] [/url]
/***********************************************************
                       ADC
**********************************************************
*/
//Konfigurace jednoho ADC
#defineADC_SINGLE_CONVERSION(nastavení)
   dělat{ ADCCON3 = nastavení; }zatímco(0)

//Nastavení parametrů se skládá z následujících kombinací:
//Referenční napětí
#defineADC_REF_1_25_V 0x00     //Vnitřní referenční napětí 1,25V
#defineADC_REF_P0_7 0x40     //Externí referenční napětí na pinu AIN7
#defineADC_REF_AVDD 0x80     //AVDD_SOC Pins
#defineADC_REF_P0_6_P0_7 0xC0     //AIN6-AIN7 Externí referenční napětí pro diferenciální vstupy


//Vzorkovací frekvence
#defineADC_8_BIT 0x00     //8. místo
#defineADC_10_BIT 0x10     //10. místo
#defineADC_12_BIT 0x20     //12. místo
#defineADC_14_BIT 0x30     //14. místo


//Vstup na kanál
#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     //Pozemky
#defineADC_TEMP_SENS 0x0E     //Teplotní senzor v čipu
#defineADC_VDD_3 0x0F     //VDD/3




Konverze na ADC je dokončena
#define ADC_SAMPLE_READY() (ADCCON1 & 0x80)

#endif
//启动ADC转化
#define ADC_START()
  dělat { ADCCON1 |= 0x40; } zatímco (0)//Vyberte režim spouště ADC jako manuální (tj. ADC_SAMPLE_READY)
#defineADC_STOP()  
  dělat{ ADCCON1 |=0x30; }zatímco (0)[url=] [/url]


(2) Funkční vrstva modulů
  • module.h
  • module.c
[url=] [/url]
/***********************************************************
*Název souboru: module.h
*Autor: hustlzp
*Datum: 6. března 2011
*Verze: 1.0
*Popis funkce: Soubor hlavičky funkční modulové vrstvy
*Seznam funkcí: void led_init()
            prázdnota timer1_init()
            prázdnota uart0_init(prázdnota);
            void Uart0SendString(unsigned char *s);
            Float adc_start(prázdno)
            void get_temperature(neoznačený char *výstup, float temp);
            prázdnota watchdog_init(prázdnota);
*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 světlo a vypnuté
#defineLED_OFF 1
#defineLED_ON 0

//Inicializace LED
prázdnotaled_init(prázdnota);




/***********************************************************
                        timer1
**********************************************************
*/
//Používá se k nastavení hodnoty přetečení pro č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
**********************************************************
*/
//Inicializace UART0
prázdnota  uart0_init(prázdnota);                    

//Sériový portový přenosový řetězec
prázdnota  Uart0SendString(nepodepsanýchar*s);
   

/***********************************************************
                        ADC-14
**********************************************************
*/
//Používá se k převodu dat získaných ADC na teplotu Celsia
#defineADC_TO_CELSIUS(teplota) (teplota * 0,06229 - 311,43)

//Zahajte přechod na ADC
Plovákadc_start(prázdnota);

//Přestavba
prázdnota  get_temperature(nepodepsané)char*výstup,Plovákdočasné);


/***********************************************************
                        WatchDog
**********************************************************
*/
//Inicializace hlídacího psa
prázdnota  watchdog_init(prázdnota);                 

#endif
[url=] [/url]

[url=] [/url]
/***********************************************************
*Název souboru: module.c
*Autor: hustlzp
*Datum: 2011/3/11
*Verze: 1.0
*Popis funkce: Zdrojový soubor funkční vrstvy modulů
*Seznam funkcí: (vynecháno)
*Upravené záznamy:
**********************************************************
*/


#include"module.h"


/***********************************************************
*Název funkce: led_init
*Funkční funkce: inicializace LED
*Vstupní parametry: Žádné
*Exportní parametry: Žádné
**********************************************************
*/
prázdnotaled_init(prázdnota)
{
  //Konfigurujte P1.0, P1.1, P1.2 a P1.3 jako obecné 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ázev funkce: timer1_init
* Funkční funkce: Inicializace časovače 1
*Vstupní parametry: Žádné
*Exportní parametry: Žádné
**********************************************************
*/
prázdnotatimer1_init(prázdnota)
{
  INT_GLOBAL_ENABLE(INT_ON);                 //Otevřete globální přerušení
  
  INT_ENABLE(INUM_T1, INT_ON);               //Otevřené T1 přerušení

  TIMER1_ENABLE_OVERFLOW_INT(INT_ON);        //Přepadnutí přetečení otevřeného T1 počítání
  
  SET_TIMER_TICK(TIMER1_TICK_4M);            //Nastavte časovač TICK na 4MHz
  
  SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);        //Nastavte počítací období pro T1 na 2
  
  SET_TIMER1_TICKDIV(TIMER1_TICKDIV_128);   //Nastavte crossover hodin na T1 na 128
  
  SET_TIMER1_MODE(TIMER1_MODE_MODULE);      //Nastavte režim běhu T1 na modul
}


/***********************************************************
*Název funkce: uart0_init
*Funkční funkce: Inicializace sériového portu UART0
*Vstupní parametry: Žádné
*Exportní parametry: Žádné
**********************************************************
*/
prázdnotauart0_init(prázdnota)
{
  //Vyberte místo UART
  IO_PER_LOC_UART0_AT_PORT0_PIN2345();
  
  //Konfigurace UART: Příjem povolen, 115200bps, jednobitový stop bit, žádná parita
  UART_SETUP(0, UART_RECEIVE_ENABLE,115200, ONE_STOP_BITS | PARITY_DISABLE);

  //Otevřete úplné přerušení
  INT_GLOBAL_ENABLE(INT_ON);      

  //Otevřete sériový port 0 pro příjem přerušení
  INT_ENABLE(INUM_URX0, INT_ON);   
}


/***********************************************************
*Název funkce: Uart0SendString
* Funkční funkce: Inicializace časovače 1
*Vstupní parametr: nepodepsaný znak *s
            Řetěz, který chceš poslat
*Exportní parametry: Žádné
**********************************************************
*/
prázdnotaUart0SendString(nepodepsanýchar*s)
{
  zatímco(*s !=0)         
    UART0_SEND(*s++);
}


/***********************************************************
*Název funkce: adc_start
*Funkční funkce: Spusť převod ADC
*Vstupní parametry: Žádné
*Exportní parametr: plovák
            Teplotní hodnota v tabletě
**********************************************************
*/
Plovákadc_start(prázdnota)
{
  nepodepsánointteplota;
  
  //Referenční napětí je 1,25 V, přesnost vzorkování je 14 bitů a cílem konverze je teplotní senzor na čipu
  ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);
  
  ADC_STOP();                           //Nastavte spouštěcí metodu pro převod ADC na manuální
  
  ADC_START();                           //Zahajte přechod na ADC
  
  zatímco(! ADC_SAMPLE_READY());            //Počkejte, až konverze skončí
  
  temp = ADCL >>2;                     //Uložte konverzní výsledky v teplotě
  temp |= ((((nepodepsánoint) ADCH) <<6);
  
  návratADC_TO_CELSIUS(dočasně);           //Po převodu vrací skutečnou hodnotu teploty
}


/***********************************************************
*Název funkce: get_temperature
*Funkční funkce: Zpracovat teplotní hodnotu a uložit ji do znakového pole pro sériový výstup
*Vstupní parametr: neznamepsaný char *výstup
            Používá se k ukládání převedené hodnoty teploty
            Teplota plováku
            Hodnota teploty Celsia
*Exportní parametry: Žádné
**********************************************************
*/
prázdnotaget_temperature(nepodepsané)char*výstup,Plovákdočasné)
{
  Výstup[0] = (nepodepsanéchar(dočasné) /10 + 48;         //Deset míst
  Výstup[1] = (nepodepsanéchar(temp) %10 + 48;         //jednociferný počet
  Výstup[2] ='.';                                      //Desetinná čárka
  Výstup[3] = (nepodepsanéchar(dočasná teplota*10) %10 + 48;      //Desáté
  Výstup[4] = (nepodepsanéchar(dočasná teplota*100) %10 + 48;      //Percentil
  Výstup[5] ='';                                    //Řetězcové endifikátory
}


/***********************************************************
*Název funkce: watchdog_init
*Funkce funkce: inicializace watchdog
*Vstupní parametry: Žádné
*Exportní parametry: Žádné
**********************************************************
*/
prázdnotawatchdog_init(prázdnota)
{
  WDT_SET_TIMEOUT_PERIOD(SEC_1);   //Nastavte čas na 1 sekundu
  WDT_ENABLE();                    //Spusť hlídacího psa
}
[url=] [/url]


(3) Aplikační vrstva
  • main.c
[url=] [/url]
/*******************************************************************
Název souboru: main.c
Autor: hustlzp
Datum: 2011/3/11
Verze: 1.0
Popis funkce: Hlavní programový soubor
Seznam funkcí: (vynecháno)
Záznam o úpravách:
******************************************************************
*/


#include




/********************************************************************
                             Postupy pro přerušení
********************************************************************/
/* 定时器1溢出中断子程序
-------------------------------------------------------*/
#pragma vektor=T1_VECTOR
__interrupt prázdnota T1_ISR(prázdnota)
{
  EA=0;                                   Brána je přerušena
  
  led2 = LED_ON;                          
  
  get_temperature(výstup,adc_start());    Převeďte teplotní hodnotu na pole znaků, které má být vytištěno
   
  Uart0SendString(output);                Hodnota výstupní 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, což znamená, že přijatý znak je použit k nastavení doby přetečení časovače
  {
    typ=0;
    Přepínat (přijímat)
    {
      případ '0': // Přetečení časovače je 0,5 s
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_dot5SEC);
        pauza;
      }
      případ '1': // Doba přetečení časovače je 1s
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_1SEC);
        pauza;
      }
      případ '2': // Přetečení časovače je 2 s
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
        pauza;         
      }
    }
  }
  jinak if(type==2) // type=2, což označuje, že přijaté znaky se používají pro řízení spánku
  {
    typ=0;
    led1 = LED_OFF;
    led2 = LED_OFF;
    led3 = LED_OFF;
    Přepínat (přijímat)
    {
      případ '1': // Vstup do režimu napájení PM1
      {
        SET_POWER_MODE(1);  
        pauza;
      }
      případ '2': // Vstup do režimu napájení PM2
      {
        SET_POWER_MODE(2);  
        pauza;
      }
      případ '3': //Vstup do režimu napájení PM3
      {
        SET_POWER_MODE(3);  
        pauza;
      }
    }
  }
  jinak if(type==0) // type=0, což znamená, že přijatý znak je typ řídicího příkazu: @ nebo $
  {
    if(receive=='@')  
    {
      typ=1;     '@' označuje, že další znak je použit k nastavení přetečení
    }
    jinak if(receive=='$')
    {
      typ=2;     Přijímá se '$', což označuje, že další znak je použit pro řízení systému spánku
    }
  }
  
  led3 = LED_OFF;
   
  EA=1;
}
=LED_OFF;
  
  TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR);   Odstraňte přerušovací ceduli
  
  EA=1;                                   Otevřené přerušení  
}
/* 主函数
-------------------------------------------------------*/
void main(void)
{
  SET_MAIN_CLOCK_SOURCE(CRYSTAL);  Nastavte systémový takt na krystalový oscilátor 32MHz
  
  led_init();                      Inicializace LED
  
  uart0_init();                    Inicializace sériového portu UART0
  
  timer1_init();                   Časovač 1 inicializuje
  
  watchdog_init();                 Inicializace hlídacího psa
  
  zatímco (1)
  {
    WDT_RESET();                   Krmte psa neustále
  }
}/********************************************************************
                            Hlavní program   
********************************************************************/
/* 全局变量
-------------------------------------------------------*/
výstup znaku bez znaku[6]={0};       Teplotní data jsou ukládána pro snadný sériový výstup
nepodepsaný char přijímat;             Uložit přijaté znaky
neoznačený typ znaku=0;              Příznak typu přijatého znaku je nastaven na 0/1/2"module.h"[url=] [/url]


5. Testování
Ó~ Kód je konečně vložený, je to opravdu vyčerpávající, pojďme otestovat tenhle malý systém:
(1) Časově omezené vzorkování
Otevřete sériový port, spustite ladění IAR a zjistíte, že LED1 je zapnutý, teplota na nástroji sériového portu se neustále generuje a vzorkovací interval je určen na 2 sekundy:
(2) Řízení vzorkovacích intervalů
Zadejte "@1" do nástroje pro sériový port, poté otestujte vzorkovací interval a zjistíte, že se stal jedničkami; Zadejte "@0" a vzorkovací interval se změní na 0,5 s.
(3) Kontrola spánku
Zadejte "$1" do nástroje pro sériový port a zjistíte, že všechny LED diody jsou zhasnuté a měření teploty se zastavilo:
Po testování systém funguje normálně a stabilně a v podstatě splňuje požadavky.
Studenti, kteří potřebují zdrojový kódKlikněte zde pro stažení
6. Závěr
Tento článek uvádí jako příklad mírně komplexní experiment, aby ukázal, jak integrovat zdroje CC2430 na čipu pro napsání relativně standardizovaného malého systému. Za pár dní si najdu čas napsat jednoduchou uživatelskou příručku pro hal.h, abychom já i všichni ostatní mohli snadno ovládat CC2430.
Dále dokončím svůj výzkum na CC2430 on-chip zdrojích a věnuji se učení protokolového stacku TI Z-Stack~
Psaní blogových příspěvků v této sérii je prozatím u konce, ale Zigbeeho cesta bude pokračovat. Budoucnost je neznámá, ale věřím, že autor překoná překážky spolu s každým, ochutná vzestupy i pády a přinesou zisky.
Zůstaňte naladěni: blogové příspěvky "Join TI Z-Stack"!















Předchozí:Zigbee Journey (9): Několik důležitých základních experimentů CC2430 – systematický spánek a přerušovaná bdělost
Další:Dnes je Halloween, jak ho budete bavit?
Zveřejněno 31.10.2014 8:04:14 |
Odpusťte mi, že jsem ničemu nerozuměl
Zřeknutí se:
Veškerý software, programovací materiály nebo články publikované organizací Code Farmer Network slouží pouze k učení a výzkumu; Výše uvedený obsah nesmí být používán pro komerční ani nelegální účely, jinak nesou všechny důsledky uživatelé. Informace na tomto webu pocházejí z internetu a spory o autorská práva s tímto webem nesouvisí. Musíte výše uvedený obsah ze svého počítače zcela smazat do 24 hodin od stažení. Pokud se vám program líbí, podporujte prosím originální software, kupte si registraci a získejte lepší skutečné služby. Pokud dojde k jakémukoli porušení, kontaktujte nás prosím e-mailem.

Mail To:help@itsvse.com