Acest articol este un articol oglindă al traducerii automate, vă rugăm să faceți clic aici pentru a sări la articolul original.

Vedere: 10835|Răspunde: 1

Zigbee Journey (10): Experiment cuprinzător - Sistem de monitorizare a temperaturii bazat pe CC2430

[Copiază linkul]
Postat pe 30.10.2014 23:47:44 | | | |
După ce a scris "Zigbee Journey (9)" pe 3 martie, autorul plănuia inițial să înceapă imediat să scrie un mic experiment despre "sistemul de monitorizare a temperaturii" ca rezumat al unei serii de puncte de cunoaștere răspândite anterioare. Totuși, am realizat și că, deși fiecare dintre micile experimente anterioare a fost descrisă în detaliu, natura normativă și structurală a codului său poate fi considerată insuportabilă. Deoarece este un rezumat, ar trebui să facem progrese pe baza inițială, în loc să asamblăm mecanic micile puncte de cunoaștere anterioare. Prin urmare, mi-am pus planul inițial pe pauză, mi-am făcut timp să învăț tehnicile generale ale dezvoltării embedded și am scris două eseuriSpecificația de programare C51 încorporată" și "Ierarhia structurii codului proiectului încorporat》。 Acest jurnal nu este doar un rezumat al primei călătorii a lui Zigbee, ci include și experiența de învățare a autorului din ultimele zile, sperând să fie de ajutor pentru începătorii Zigbee.
Textul integral este organizat conform procesului de bază al dezvoltării software-ului: analiza cerințelor, proiectarea schiței, proiectarea detaliată, implementarea codării și testarea.
1. Analiza cererii
După o discuție între "client" și "dezvoltator", a fost stabilită următoarea descriere a funcției sistemului:
… Temperatura curentă a camerei este colectată de nodurile bazate pe CC2430, iar valorile sale de temperatură pot fi monitorizate printr-un PC
… Nodul CC2430 trebuie să aibă un anumit grad de stabilitate și poate reveni automat la starea normală
… Intervalul de eșantionare și gestionarea energiei nodului pot fi controlate de un PC
2. Designul schiței
Conform analizei cerințelor de mai sus, putem împărți sistemul în două module:Nodul CC2430șiPC
  [Nod CC2430]  
… Parametrii externi pot fi colectați regulat și trimiși către PC
… Resetare automată când aparatul este oprit
… Comenzile de la PC pot fi recepționate și procesate corespunzător: schimbați intervalul de eșantion/gestionarea consumului de energie
  [PC]  
… Mașina C primește și afișează date prin unealta portului serial
… Instrucțiunile pot fi trimise microcontrolerului prin instrumentul port serial pentru a controla viteza de eșantionare și gestionarea puterii
3. Proiectare detaliată
(1) Structura codului
Stratificarea structurii codului acestui sistem a fost descrisă în eseul "Ierarhia structurii codului proiectului încorporat, iar copia este următoarea:
(1) Stratul de abstracție hardware
      [ioCC2430.h] (Sistem inclus)Toate vectorii SFR și de întrerupere ai CC2430 sunt definiți
      [hal.h] Include definiții comune de tipuri, macro-uri comune de atribuire și configurație comună a resurselor CC2430 pe cip (I/O, comunicare serială, ADC, timer, management al energiei etc.)
  (2) Stratul de modul funcțional
      [module.h] definește resursele on-chip (timere, I/O), modulele de expansiune off-chip (LED-uri) și declarațiile funcțiilor conexe
      [module.cImplementează inițializarea fiecărui modul (LED).
  (3) Stratul de aplicație
      [main.cConsultați hal.h, ioCC2430.h și module.h pentru a îndeplini cerințe specifice ale aplicației, cum ar fi achiziția temperaturii, intercomunicarea cu PC-ul și oprirea și resetarea
(2) Metode de implementare ale fiecărui modul
Conform modulelor împărțite conform designului de schiță, sistemul intrinsec poate fi împărțit în două module principale:Nodul CC2430șiPC
Deoarece există instrumente de comunicare prin porturi seriale pe PC, funcțiile sale pot îndeplini cerințele, deci nu trebuie să facem această parte a PC-ului și nu este nevoie să o analizăm. Să vorbim mai jos despre secțiunea CC2430
Metoda de implementare a fiecărei subfuncții a punctului:
… Folosește întreruperea de depășire a numărului de temporizatori pentru a declanșa eșantionarea temporizată
… Modul UART0 cu port serial transmite date de temperatură către un PC
… Circuitul watchdog integrat al CC2430 este folosit pentru a realiza funcția de resetare automată a sistemului
… Portul serial este folosit pentru a primi întreruperi, pentru a captura și răspunde la comenzile de control de la PC
1) Dacă este primit@Caracterul este comanda de control a intervalului de eșantionare, urmată de un număr care indică intervalul de eșantionare: 0-0,5s, 1-1, 2-2s
如:@0,表示每隔0.5秒采样一次。
2) Dacă este primit$  Caracterul este comanda de control în repaus, urmată de un număr care indică modul de alimentare
De exemplu: 3$, ceea ce înseamnă să pui sistemul în modul de putere 3.
(3) Diagramă de flux a programului
  • Diagrama de flux a programului master
  • Diagrama de flux a programului de întreruperi peste preaploare a temporizatorului 1
  • Diagrama de flux a procedurii de recepție a întreruperii porturilor seriale




4. Implementarea codării
(1) Stratul de abstracție hardware
Stratul de abstracție hardware include ioCC2430.h și hal.h. Deoarece sistemul anterior vine cu el, nu va fi listat.
Următoarea este o listă cu toate conținuturile hal.h (deoarece acest fișier este prea lung și pare incomod, îl voi arăta în module):
  • Cap
  • Porturi I/O
  • Întrerupt
  • Port serial
  • Gestionarea energiei și ceasului
  • Cronometrul
  • Câine de pază
  • ADC
[url=] [/url]
/***********************************************************
*Nume fișier: hal.h
*Autor: hustlzp
*Data: 8 martie 2011
*Ediție: 1.1
*Descrierea funcției: Strat de abstracție hardware
*Recorduri modificate:
**********************************************************
*/


#ifndef HAL_H
#defineHAL_H


#include


/***********************************************************
                       Definiții comune ale tipurilor
**********************************************************
*/
typedef nesemnatChar   BYTE;
typedef nesemnatint    CUVÂNTUL;
typedef nesemnatlung   DWORD;



/***********************************************************
                       Definiții macro utilizate frecvent
**********************************************************
*/

//8 locuri mai sus
#defineHIGH_BYTE(a) ((BYTE) (((WORD)(a)) >> 8))


//8 locuri mai jos
#defineLOW_BYTE(a) ((BYTE) ((WORD)(a)))


//Repartizare
#defineSET_WORD(regH,regL,word)  
   face{                           
      (regH)=HIGH_BYTE(cuvânt);     
      (regL)=LOW_BYTE(cuvânt);      
   }în timp ce(0)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Porturi I/O
**********************************************************
*/
/*Configurează direcția porturilor I/O
-----------------------------------------
*/
#defineIO_DIR_PORT_PIN(port, pin, dir)  
   face{                                 
      dacă(dir. == IO_OUT)                 
         P##port##DIR |= (0x01<<(pin));  
      altfel                              
         P##port##DIR &= ~(0x01<<(pin));
   }în timp ce(0)



//Valoarea parametrului dir este:
#defineIO_IN 0
#defineIO_OUT 1


/*Configurează modul de intrare al portului I/O
-----------------------------------------
*/
#defineIO_IMODE_PORT_PIN(port, pin, imode)
   face{                                    
      dacă(imode == IO_IMODE_TRI)            
         P##port##INP |= (0x01<<(pin));     
      altfel                                 
         P##port##INP &= ~(0x01<<(pin));   
   }în timp ce (0)



#define IO_PUD_PORT(babord, pud)        
   do {                              
      dacă (pud == IO_PULLDOWN)         
         P2INP |= (0x01 << (port+5));
      altfel                           
         P2INP &= ~(0x01 << (port+5));
   } în timp ce (0)


Valoarea parametrului PUD este:
#define IO_PULLUP 0 // Trage în sus
#define IO_PULLDOWN 1 // Trage în jos


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

#define IO_FUNC_PORT_PIN(port, pin, func)  
   do {                                    
      if((port == 2) && (pin == 3)){      
         dacă (func) {                       
            P2SEL |= 0x02;                 
         } altfel {                          
            P2SEL &= ~0x02;               
         }                                 
      }                                    
      else if((port == 2) && (pin == 4)){  
         dacă (func) {                       
            P2SEL |= 0x04;                 
         } altfel {                          
            P2SEL &= ~0x04;               
         }                                 
      }                                    
      else{                                
         dacă (func) {                       
            P##port##SEL |= (0x01<<(pin));
         } altfel {                          
            P##port##SEL &= ~(0x01<<(pin));
        }                                 
      }                                    
   } în timp ce (0)


Valoarea parametrului func este:
#define IO_FUNC_GIO 0 // General I/O
#define IO_FUNC_PERIPH 1 // I/O periferică


Configurează locația I/O periferică
#define IO_PER_LOC_TIMER1_AT_PORT0_PIN234() do { PERCFG = (PERCFG&~0x40)|0x00; } în timp ce (0)
#define IO_PER_LOC_TIMER1_AT_PORT1_PIN012() do { PERCFG = (PERCFG&~0x40)|0x40; } în timp ce (0)

#define IO_PER_LOC_TIMER3_AT_PORT1_PIN34() do { PERCFG = (PERCFG&~0x20)|0x00; } în timp ce (0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN67() do { PERCFG = (PERCFG&~0x20)|0x20; } în timp ce (0)

#define IO_PER_LOC_TIMER4_AT_PORT1_PIN01() do { PERCFG = (PERCFG&~0x10)|0x00; } în timp ce (0)
#define IO_PER_LOC_TIMER4_AT_PORT2_PIN03() do { PERCFG = (PERCFG&~0x10)|0x10; } în timp ce (0)

#define IO_PER_LOC_SPI1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x08)|0x00; } în timp ce (0)
#define IO_PER_LOC_SPI1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x08)|0x08; } în timp ce (0)

#define IO_PER_LOC_SPI0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x00; } în timp ce (0)
#define IO_PER_LOC_SPI0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x04; } în timp ce (0)

#define IO_PER_LOC_UART1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x02)|0x00; } în timp ce (0)
#define IO_PER_LOC_UART1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x02)|0x02; } în timp ce (0)

#define IO_PER_LOC_UART0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x00; } în timp ce (0)
#define IO_PER_LOC_UART0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x01; } în timp ce (0)

//Valoarea parametrului imode este:
#defineIO_IMODE_PUD 0   //Tragere în sus/tragere în jos
#defineIO_IMODE_TRI 1   //Trei state[url=] [/url]

[url=] [/url]
/***********************************************************
                       Întrerupt
**********************************************************
*/
//Pentru întreruperi on/off
#defineINT_ON 1
#defineINT_OFF 0


//Folosit pentru a plasa/șterge steaguri de întrerupere
#defineINT_SET 1
#defineINT_CLR 0


//Setări globale de întrerupere
#defineINT_GLOBAL_ENABLE(on) EA=(!! pornit)


//Definiți ruptura
#defineINUM_RFERR 0
#defineINUM_ADC 1
#defineINUM_URX0 2
#defineINUM_URX1 3
#defineINUM_ENC 4
#defineINUM_ST 5
#defineINUM_P2INT 6
#define7 INUM_UTX0
#defineINUM_DMA 8
#defineINUM_T1 9
#defineINUM_T2 10
#defineINUM_T3 11
#defineINUM_T4 12
#define13 INUM_P0INT
#defineINUM_UTX1 14
#defineINUM_P1INT 15
#defineINUM_RF 16
#define17 INUM_WDT


/*Întreruperi permise
-----------------------------------------
*/
#defineINT_ENABLE(inum, on)                        
   face{                                             
      dacă      (inum==INUM_RFERR) { RFERRIE = pornit; }  
      altfel dacă(inum==INUM_ADC)   { ADCIE = pornit; }  
      altfel dacă(inum==INUM_URX0)  { URX0IE = pornit; }  
      altfel dacă(inum==INUM_URX1)  { URX1IE = pornit; }  
      altfel dacă(inum==INUM_ENC)   { ENCIE = pornit; }  
      altfel dacă(inum==INUM_ST)    { STIE = pornit; }  
      altfel dacă(inum==INUM_P2INT) { (pornit) ? (IEN2 |=0x02) : (IEN2 &= ~0x02); }
      altfel dacă(inum==INUM_UTX0)  { (pornit) ? (IEN2 |=0x04) : (IEN2 &= ~0x04); }
      altfel dacă(inum==INUM_DMA)   { DMAIE = pornit; }  
      altfel dacă(inum==INUM_T1)    { T1IE = pornit; }  
      altfel dacă(inum==INUM_T2)    { T2IE = pornit; }  
      altfel dacă(inum==INUM_T3)    { T3IE = pornit; }  
      altfel dacă(inum==INUM_T4)    { T4IE = on; }  
      altfel dacă(inum==INUM_P0INT) { P0IE = on; }  
      altfel dacă(inum==INUM_UTX1)  { (pornit) ? (IEN2 |=0x08) : (IEN2 &= ~0x08); }
      altfel dacă(inum==INUM_P1INT) { (pornit) ? (IEN2 |=0x10) : (IEN2 &= ~0x10); }
      altfel dacă(inum==INUM_RF)    { (pornit) ? (IEN2 |=0x01) : (IEN2 &= ~0x01); }
      altfel dacă(inum==INUM_WDT)   { (pornit) ? (IEN2 |=0x20) : (IEN2 &= ~0x20); }
   }în timp ce (0)


/*Setează prioritatea întreruperii
-----------------------------------------
*/
#defineINT_PRIORITY(grup, pri)                     
   face{                                               
      dacă(pri ==0) { IP0 &= ~group; IP1 &= ~grup; }
      dacă(pri ==1) { IP0 |= grup; IP1 &= ~grup; }
      dacă(pri ==2) { IP0 &= ~group; IP1 |= grup; }
      dacă(pri ==3) { IP0 |= grup; IP1 |= grup; }
   }în timp ce (0)

//Valoarea parametrului pri este: 0/1/2/3 (cea mai mare prioritate)


//Valoarea grupului de parametri este:
#defineRFERR_RF_DMA 0x01//Grupul IP0
#defineADC_P2INT_T1 0x02//Grupul IP1
#defineURX0_UTX0_T2 0x04//Grupul IP2
#defineURX1_UTX1_T3 0x08//Grupul IP3
#defineENC_P1INT_T4 0x10//Grupul IP4
#defineST_WDT_P0INT 0x20//Grupul IP5


/*Obține flag-ul de întrerupere
-----------------------------------------
*/
#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) ? T1FI:
   (inum==INUM_T2) ? T2FI :
   (inum==INUM_T3) ? T3FI :
   (inum==INUM_T4) ? T4FI:
   (inum==INUM_P0INT) ? P0IF :
   (inum==INUM_UTX1) ? UTX1IF :
   (inum==INUM_P1INT) ? P1FI:
   (inum==INUM_RF) ? S1CON &= ~0x03    :
   (inum==INUM_WDT) ? WDTIF :
   0                                             
)


/*Setează steagul de întrerupere
-----------------------------------------
*/
#defineINT_SETFLAG(inum, f)                     
   face{                                          
      dacă      (inum==INUM_RFERR) { RFERRIF= f; }
      altfel dacă(inum==INUM_ADC)   { ADCIF = f; }
      altfel dacă(inum==INUM_URX0)  { URX0IF = f; }
      altfel dacă(inum==INUM_URX1)  { URX1IF = f; }
      altfel dacă(inum==INUM_ENC)   { ENCIF_1 = ENCIF_0 = f; }
      altfel dacă(inum==INUM_ST)    { STIF = f;  }
      altfel dacă(inum==INUM_P2INT) { P2IF = f;  }
      altfel dacă(inum==INUM_UTX0)  { UTX0IF= f;  }
      altfel dacă(inum==INUM_DMA)   { DMAIF = f;  }
      altfel dacă(inum==INUM_T1)    { T1IF = f;  }
      altfel dacă(inum==INUM_T2)    { T2IF = f;  }
      altfel dacă(inum==INUM_T3)    { T3IF = f;  }
      altfel dacă(inum==INUM_T4)    { T4IF = f;  }
      altfel dacă(inum==INUM_P0INT) { P0IF = f;  }
      altfel dacă(inum==INUM_UTX1)  { UTX1IF= f;  }
      altfel dacă(inum==INUM_P1INT) { P1IF = f;  }
      altfel dacă(inum==INUM_RF)    { (f) ? (S1CON |=0x03) : (S1CON &= ~0x03); }
      altfel dacă(inum==INUM_WDT)   { WDTIF = f;  }
   }în timp ce (0)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Port serial
**********************************************************
*/
//Valoarea BAUD_E corespunzătoare diferitelor rate în bauduri
#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  )


//Valoarea BAUD_M corespunzătoare diferitelor rate de baud
#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)


/*Configurația porturilor seriale în modul UART
-----------------------------------------
*/
#defineUART_SETUP(uart, receiveEnable, baudRate, opțiuni)      
   face{                                                         
      dacă((uart) ==0){                                          
         dacă(PERCFG &0x01){                                    
            P1SEL |=0x30;                                      
         }altfel{                                               
            P0SEL |=0x0C;                                      
         }                                                      
      }                                                         
      altfel{                                                   
         dacă(PERCFG &0x02){                                    
            P1SEL |=0xC0;                                      
         }altfel{                                               
            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 |= ((opțiuni) |0x80);                       
   }în timp ce(0)
     
//Valoarea parametrului receiveEnable:
#defineUART_RECEIVE_ENABLE 0x40   //Primirea permisiunii
#defineUART_RECEIVE_DISABLE 0x00   
     
//Valoarea opțiunilor parametrilor:
#defineFLOW_CONTROL_ENABLE 0x40   //Controlul fluxului
#defineFLOW_CONTROL_DISABLE 0x00


#defineEVEN_PARITY 0x20   //Verificări ocazionale
#defineODD_PARITY 0x00   //Verificare ciudată


#defineNINE_BIT_TRANSFER 0x10   //Transfer de 9 octeți
#defineEIGHT_BIT_TRANSFER 0x00   //Transfer de 8 octeți


#definePARITY_ENABLE 0x08   //Activarea verificării parității
#definePARITY_DISABLE 0x00

#defineTWO_STOP_BITS 0x04   //Poziția de oprire cu 2 poziții
#defineONE_STOP_BITS 0x00   //Poziția de oprire 1


#defineHIGH_STOP 0x02   //Nivelul de oprire este ridicat
#defineLOW_STOP 0x00   //Poziția de oprire este joasă
     
#defineHIGH_START 0x01   //Nivelul bitului de început este ridicat
#defineLOW_START 0x00   //Nivelul bitului de start este scăzut


//Portul serial trimite caractere
#defineUART_SEND(uart,data)            
   face{                                 
     în timp ce(U##uart##CSR &0x01);        
       U##uart##DBUF = date;            
   }în timp ce (0)
#defineUART0_SEND(date) UART_SEND(0,date)
#defineUART1_SEND(date) UART_SEND(1,date)


//Portul serial primește caractere
#defineUART_RECEIVE(uart,data)         
   face{                                 
     în timp ce(! (U##uart##CSR&0x04));      
       data=U##uart##DBUF;              
   }în timp ce(0)
#defineUART0_RECEIVE(date) UART_RECEIVE(0,date)
#defineUART1_RECEIVE(date) UART_RECEIVE(1,date)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Gestionarea energiei și ceasului
**********************************************************
*/
//Ia crossover-ul cu ceasul
#defineCLKSPD (CLKCON & 0x07)


//Setează modul de putere
#defineSET_POWER_MODE(mod)                  
   face{                                       
      dacă(mod ==0) { SOMN &= ~0x03; }
      altfel dacă(mod ==3) { SLEEP |=0x03;  }
      altfel{ SOMN &= ~0x03; SLEEP |= mod;  }
      PCON |=0x01;                           
      asm("NU");                              
   }în timp ce (0)


//Modul parametrilor este setat la următoarele valori:
#definePOWER_MODE_0 0x00  
#definePOWER_MODE_1 0x01
#definePOWER_MODE_2 0x02
#definePOWER_MODE_3 0x03


//Folosit pentru a detecta stabilitatea oscilatoarelor RC de înaltă frecvență
#defineHIGH_FREQUENCY_RC_OSC_STABLE (SOMN & 0x20)


//Folosit pentru a detecta starea stabilă a oscilatorului cu cristal
#defineXOSC_STABLE (SOMN & 0x40)


//Obține valoarea frecvenței de tick a cronometrului
#defineTICKSPD ((CLKCON & 0x38) >> 3)


//Setează frecvența ceasului principal
#defineSET_MAIN_CLOCK_SOURCE(sursă)
   face{                              
      dacă(sursa) {                    
        CLKCON |=0x40;               
        în timp ce(! HIGH_FREQUENCY_RC_OSC_STABLE);
        dacă(TICKSPD ==0){            
          CLKCON |=0x08;            
        }                             
        SLEEP |=0x04;               
      }                              
      altfel{                          
        SOMN &= ~0x04;               
        în timp ce(! XOSC_STABLE);         
        asm("NU");                  
        CLKCON &= ~0x47;              
        SLEEP |=0x04;               
      }                              
   }în timp ce (0)


//Valoarea sursei parametrilor este:
#defineCRISTAL 0x00   //Oscilator cu cristal
#defineRC 0x01   //Oscilator RC
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Cronometrul 1
**********************************************************
*/
//Cronometrul 1 permite depășirii numărului să întrerupă
#defineTIMER1_ENABLE_OVERFLOW_INT(val)
   (TIMIF = (val) ? TIMIF |0x40: TIMIF & ~0x40)


//Setează flag-ul de întrerupere a overflow-ului pentru timer 1
#defineTIMER1_OVERFLOW_INT_SETFLAG(f) (T1CTL= ((T1CTL & (~0x10)) | f))


//Cronometrul 1 pornește
#defineTIMER1_RUN(valoare) (T1CTL = (valoare) ? T1CTL|0x02 : T1CTL&~0x03)


//Setează diviziunea ceasului pentru cronometru
#defineSET_TIMER_TICK(valoare) do{ CLKCON = ((CLKCON & (~0x38)) | valoare); } în timp ce (0)


//Valoarea valorii este:
#defineTIMER1_TICK_32M 0x00  //32MHz
#defineTIMER1_TICK_16M 0x08  //16MHz, valoarea implicită pentru resetarea sistemului
#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

//Setează crossover-ul TICK pentru timer 1
#defineSET_TIMER1_TICKDIV(valoare)  
   face{                             
     T1CTL &= ~0x0c;               
     T1CTL |= valoare;               
   }în timp ce (0)
      
//unde valoarea este:      
#defineTIMER1_TICKDIV_1 0x00   //1 Divizie
#defineTIMER1_TICKDIV_8 0x04   //Frecvență de 8 căi
#defineTIMER1_TICKDIV_32 0x08
#defineTIMER1_TICKDIV_128 0x0c


//Setează perioada de depășire a temporizatorului
#defineSET_TIMER1_PERIOD(valoare)
   face{                           
     T1CC0H = HIGH_BYTE(valoare);  
     T1CC0L = LOW_BYTE(valoare);   
   }în timp ce (0)
     
//Setează modul de funcționare al temporizatorului 1
#defineSET_TIMER1_MODE(mod)  
   face{                        
     T1CTL = ((T1CTL & (~0x03)) | mod);           
   }în timp ce (0)


//Valoarea modului este:
#defineTIMER1_MODE_STOP 0x00
#defineTIMER1_MODE_FREE 0x01
#defineTIMER1_MODE_MODULE 0x02
#defineTIMER1_MODE_UPDOWN 0x03
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Câine de pază
**********************************************************
*/
//Setează perioada de depășire pentru timer-ul watchdog
#defineWDT_SET_TIMEOUT_PERIOD(pauză)
   face{ WDCTL &= ~0x03; WDCTL |= timeout; }în timp ce (0)


//Valoarea timeout-ului parametrului este:
#defineSEC_1 0x00     //după 1 secundă
#defineM_SEC_250 0x01     //după 250 ms
#defineM_SEC_15 0x02     //după 15 ms
#defineM_SEC_2 0x03     //După 2 ms


//Proceduri de hrănire pentru câini
#defineWDT_RESET() do {           
   WDCTL = (WDCTL & ~0xF0) |0xA0;
   WDCTL = (WDCTL & ~0xF0) |0x50;
} în timp ce (0)


//Pornește/oprește cronometrul watchdog
#defineWDT_ENABLE() WDCTL |= 0x08
#defineWDT_DISABLE() WDCTL &= ~0x08
[url=] [/url]

[url=] [/url]
/***********************************************************
                       ADC
**********************************************************
*/
//Configurează un singur ADC
#defineADC_SINGLE_CONVERSION(setări)
   face{ ADCCON3 = setări; }în timp ce(0)

//Setarea parametrilor este compusă din următoarele combinații:
//Tensiunea de referință
#defineADC_REF_1_25_V 0x00     //Tensiune de referință internă de 1,25V
#defineADC_REF_P0_7 0x40     //Tensiunea de referință externă pe pinul AIN7
#defineADC_REF_AVDD 0x80     //AVDD_SOC Insigne
#defineADC_REF_P0_6_P0_7 0xC0     //AIN6-AIN7 Tensiune de referință externă pentru intrări diferențiale


//Rata de eșantionare
#defineADC_8_BIT 0x00     //Locul 8
#defineADC_10_BIT 0x10     //Locul 10
#defineADC_12_BIT 0x20     //Locul 12
#defineADC_14_BIT 0x30     //Locul 14


//Intră în canal
#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     //Teren
#defineADC_TEMP_SENS 0x0E     //Senzor de temperatură integrat în cip
#defineADC_VDD_3 0x0F     //VDD/3




Conversia ADC este completă
#define ADC_SAMPLE_READY() (ADCCON1 & 0x80)

#endif
//启动ADC转化
#define ADC_START()
  do { ADCCON1 |= 0x40; } în timp ce (0)//Selectează modul de declanșare al ADC-ului ca manual (adică ADC_SAMPLE_READY)
#defineADC_STOP()  
  face{ ADCCON1 |=0x30; }în timp ce (0)[url=] [/url]


(2) Stratul de modul funcțional
  • module.h
  • module.c
[url=] [/url]
/***********************************************************
*Nume fișier: module.h
*Autor: hustlzp
*Data: 6 martie 2011
*Versiune: 1.0
*Descrierea funcției: Fișier header pentru stratul modulului funcțional
*Listă funcții: void led_init()
            void timer1_init()
            vid uart0_init(vid);
            void Uart0SendString(caracter nesemnat *s);
            plutește adc_start(gol)
            void get_temperature(caracterul nesemnat *output, float temp);
            void watchdog_init(void);
*Recorduri modificate:
**********************************************************
*/

#ifndef MODULE_H
#defineMODULE_H


#include"hal.h"


/***********************************************************
                        LED
**********************************************************
*/
//Definiți pinii LED-urilor
#definea condus1 P1_0         
#defineled2 P1_1         
#defineled3 P1_2         
#defineled4 P1_3   

//Lumină LED și oprită
#defineLED_OFF 1
#defineLED_ON 0

//Inițializarea LED-urilor
Voidled_init(Void);




/***********************************************************
                        timer1
**********************************************************
*/
//Folosit pentru a seta valoarea perioadei de depășire pentru cronometru
#defineTIMER1_OVF_2SEC 0xF424   //2s
#defineTIMER1_OVF_1SEC 0x7A12   //1
#defineTIMER1_OVF_dot5SEC 0x3D09   //0,5s   

//Cronometrul 1 se inițializează
Void  timer1_init(Void);
                  

/***********************************************************
                        UART0
**********************************************************
*/
//Inițializarea UART0
Void  uart0_init(Void);                    

//Șirul de transmisie al porturilor seriale
Void  Uart0SendString(nesemnatChar*s);
   

/***********************************************************
                        ADC-14
**********************************************************
*/
//Folosit pentru a converti datele obținute de ADC la temperatura Celsius
#defineADC_TO_CELSIUS(temperatură) (temperatură * 0,06229 - 311,43)

//Inițiați conversia ADC
Floatadc_start(Void);

//Conversia
Void  get_temperature(nesemnatChar*ieșire,Floattemporar);


/***********************************************************
                        WatchDog
**********************************************************
*/
//Inițializarea câinelui de pază
Void  watchdog_init(Void);                 

#endif
[url=] [/url]

[url=] [/url]
/***********************************************************
*Nume fișier: module.c
*Autor: hustlzp
*Data: 2011/3/11
*Versiune: 1.0
*Descrierea funcției: Fișier sursă pentru stratul modulului funcțional
*Lista funcțiilor: (omisă)
*Recorduri modificate:
**********************************************************
*/


#include"module.h"


/***********************************************************
*Nume funcție: led_init
*Funcția funcției: Inițializarea LED-ului
*Parametri de intrare: Niciunul
*Parametri de export: Niciunul
**********************************************************
*/
Voidled_init(Void)
{
  //Configurați P1.0, P1.1, P1.2 și P1.3 ca porturi generale de I/O
  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);
  
  //Configurați P1.0, P1.1, P1.2 și P1.3 ca ieșiri
  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);
  
  conduse1 = LED_ON;
  a condus2 = LED_OFF;
  a condus3 = LED_OFF;
  conduse4 = LED_OFF;
}


/***********************************************************
*Nume funcție: timer1_init
* Funcția funcției: inițializarea temporizatorului 1
*Parametri de intrare: Niciunul
*Parametri de export: Niciunul
**********************************************************
*/
Voidtimer1_init(Void)
{
  INT_GLOBAL_ENABLE(INT_ON);                 //Deschide întreruperea globală
  
  INT_ENABLE(INUM_T1, INT_ON);               //Întreruperea T1 deschisă

  TIMER1_ENABLE_OVERFLOW_INT(INT_ON);        //Întrerupere de overflow cu numărătoare deschisă T1
  
  SET_TIMER_TICK(TIMER1_TICK_4M);            //Setează cronometrul TICK la 4MHz
  
  SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);        //Setează perioada de numărare pentru T1 la 2
  
  SET_TIMER1_TICKDIV(TIMER1_TICKDIV_128);   //Setează crossover-ul ceasului pentru T1 la 128
  
  SET_TIMER1_MODE(TIMER1_MODE_MODULE);      //Setează modul de rulare al T1 pe modul
}


/***********************************************************
*Nume funcție: uart0_init
*Funcția funcției: Inițializarea portului serial UART0
*Parametri de intrare: Niciunul
*Parametri de export: Niciunul
**********************************************************
*/
Voiduart0_init(Void)
{
  //Selectează locația UART
  IO_PER_LOC_UART0_AT_PORT0_PIN2345();
  
  //Configurează UART: Recepție permisă, 115200bps, bit de oprire pe un bit, fără paritate
  UART_SETUP(0, UART_RECEIVE_ENABLE,115200, ONE_STOP_BITS | PARITY_DISABLE);

  //Deschide întreruperea totală
  INT_GLOBAL_ENABLE(INT_ON);      

  //Deschide portul serial 0 pentru a primi întreruperi
  INT_ENABLE(INUM_URX0, INT_ON);   
}


/***********************************************************
*Nume funcție: Uart0SendString
* Funcția funcției: inițializarea temporizatorului 1
*Parametru de intrare: caracter nesemnat *s
            Șirul pe care vrei să-l trimiți
*Parametri de export: Niciunul
**********************************************************
*/
VoidUart0SendString(nesemnatChar*s)
{
  în timp ce(*s !=0)         
    UART0_SEND(*s++);
}


/***********************************************************
*Nume funcție: adc_start
*Funcția funcție: Inițierea conversiei ADC
*Parametri de intrare: Niciunul
*Parametru export: float
            Valoarea temperaturii din tabletă
**********************************************************
*/
Floatadc_start(Void)
{
  nesemnatintTemp;
  
  //Tensiunea de referință este de 1,25V, acuratețea de eșantionare este de 14 biți, iar ținta de conversie este senzorul de temperatură integrat pe cip
  ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);
  
  ADC_STOP();                           //Setează metoda de declanșare pentru conversia ADC în manual
  
  ADC_START();                           //Inițiați conversia ADC
  
  în timp ce(! ADC_SAMPLE_READY());            //Așteaptă ca conversia să se finalizeze
  
  temp = ADCL >>2;                     //Salvează rezultatele conversiei în temperatură
  temp |= (((nesemnatint) ADCH) <<6);
  
  ÎntoarcereaADC_TO_CELSIUS(temporar);           //Returnează valoarea reală a temperaturii după conversie
}


/***********************************************************
*Nume funcție: get_temperature
*Funcția de funcție: Procesează valoarea de temperatură și o stochează în matricea de caractere pentru ieșirea serială
*Parametru de intrare: unsigned char *ieșire
            Folosit pentru a stoca valoarea convertită a temperaturii
            Temperatura plutorului
            Valoarea temperaturii Celsius
*Parametri de export: Niciunul
**********************************************************
*/
Voidget_temperature(nesemnatChar*ieșire,Floattemporar)
{
  Ieșire[0] = (nesemnatChar)(temp) /10 + 48;         //Zece locuri
  Ieșire[1] = (nesemnatChar(temp) %10 + 48;         //O singură cifră
  Ieșire[2] ='.';                                      //Virgulă zecimală
  Ieșire[3] = (nesemnatChar(temp*10) %10 + 48;      //A zecea
  Ieșire[4] = (nesemnatChar(temp*100) %10 + 48;      //Percentila
  Ieșire[5] ='';                                    //Endiferitoare de corzi
}


/***********************************************************
*Nume funcție: watchdog_init
*Funcția funcției: Inițializarea câinelui de pază
*Parametri de intrare: Niciunul
*Parametri de export: Niciunul
**********************************************************
*/
Voidwatchdog_init(Void)
{
  WDT_SET_TIMEOUT_PERIOD(SEC_1);   //Setează timpul de timeout la 1s
  WDT_ENABLE();                    //Pornește watchdog-ul
}
[url=] [/url]


(3) Stratul de aplicație
  • main.c
[url=] [/url]
/*******************************************************************
Nume fișier: main.c
Autor: hustlzp
Data: 2011/3/11
Versiune: 1.0
Descrierea funcției: Fișier master al programului
Lista funcțiilor: (omisă)
Istoric de modificări:
******************************************************************
*/


#include




/********************************************************************
                             Proceduri de serviciu de întrerupere
********************************************************************/
/* 定时器1溢出中断子程序
-------------------------------------------------------*/
#pragma vector=T1_VECTOR
__interrupt vid T1_ISR(vid)
{
  EA=0;                                   Poarta este întreruptă
  
  a condus2 = LED_ON;                          
  
  get_temperature(ieșire,adc_start());    Convertiți valoarea temperaturii într-un tablou de caractere care vor fi generate.
   
  Uart0SendString (ieșire);                Valoarea temperaturii de ieșire
  Uart0SendString("°C");  


  led2


/* 串口接收中断子程序
-------------------------------------------------------*/
#pragma vector=URX0_VECTOR
__interrupt vid RE_ISR(vid)
{
  EA=0;
  
  conduse3 = LED_ON;

  primește = U0DBUF;   
  
  if(type==1) // type=1, ceea ce indică faptul că caracterul primit este folosit pentru a seta perioada de depășire a temporizatorului
  {
    tip=0;
    Comutare (recepție)
    {
      Cazul '0': // Perioada de depășire a temporizatorului este de 0,5 secunde
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_dot5SEC);
        pauză;
      }
      cazul '1': // Perioada de debordare a temporizatorului este 1s
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_1SEC);
        pauză;
      }
      cazul '2': // Perioada de debordare a temporizatorului este 2s
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
        pauză;         
      }
    }
  }
  else if(type==2) // type=2, indicând că caracterele primite sunt folosite pentru controlul somnului
  {
    tip=0;
    a condus1 = LED_OFF;
    a condus2 = LED_OFF;
    a condus3 = LED_OFF;
    Comutare (recepție)
    {
      majestuosul '1': // Intră în modul de putere PM1
      {
        SET_POWER_MODE(1);  
        pauză;
      }
      majusculă '2': // Intră în modul de alimentare PM2
      {
        SET_POWER_MODE(2);  
        pauză;
      }
      carcasa '3': //Intră în modul de alimentare PM3
      {
        SET_POWER_MODE(3);  
        pauză;
      }
    }
  }
  else if(type==0) // type=0, ceea ce indică faptul că caracterul primit este tipul comenzii control: @ sau $
  {
    if(receive=='@')  
    {
      tip=1;     '@' este primit pentru a indica faptul că următorul caracter este folosit pentru a seta perioada de debordare
    }
    altfel dacă(primește=='$')
    {
      tip=2;     "$" este primit, indicând că următorul caracter este folosit pentru controlul sistemului în repaus.
    }
  }
  
  a condus3 = LED_OFF;
   
  EA=1;
}
=LED_OFF;
  
  TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR);   Șterge semnul de întrerupere
  
  EA=1;                                   Întrerupere deschisă  
}
/* 主函数
-------------------------------------------------------*/
Void principal(void)
{
  SET_MAIN_CLOCK_SOURCE(CRYSTAL);  Setează ceasul sistemului la oscilatorul cu cristal de 32MHz
  
  led_init();                      Inițializarea LED-urilor
  
  uart0_init();                    Inițializarea portului serial UART0
  
  timer1_init();                   Cronometrul 1 se inițializează
  
  watchdog_init();                 Inițializarea câinelui de pază
  
  în timp ce (1)
  {
    WDT_RESET();                   Hrănește câinele constant
  }
}/********************************************************************
                            Programul principal   
********************************************************************/
/* 全局变量
-------------------------------------------------------*/
caracterul nesemnat output[6]={0};       Datele de temperatură sunt stocate pentru o ieșire serială ușoară
caracterul nesemnat primește;             Stochează caracterele primite
tip de caracter nesemnat=0;              Flag-ul de tip al caracterului primit este setat la 0/1/2"module.h"[url=] [/url]


5. Testare
Oh~ Codul este în sfârșit lipit, e foarte obositor, hai să testăm acest sistem mic:
(1) Eșantionare cronometrată
Deschide portul serial, începe depanarea IAR și constată că led1 este pornit, iar valoarea temperaturii pe instrumentul portului serial este generată constant, iar intervalul de eșantionare este determinat ca fiind 2s:
(2) Controlul intervalului de eșantionare
Introduceți "@1" în instrumentul port serial, apoi testați intervalul de eșantionare și constatați că a devenit 1s; Introduceți "@0" și intervalul de eșantionare s-a schimbat la 0,5s.
(3) Controlul somnului
Introduceți "$1" în instrumentul port serial și constatați că toate LED-urile sunt stinse și prelevarea de temperatură s-a oprit:
După testare, sistemul funcționează normal și stabil și, practic, respectă cerințele.
Studenți care au nevoie de cod sursăClick aici pentru a descărca
6. Concluzie
Această lucrare ia un experiment oarecum cuprinzător ca exemplu pentru a arăta cum să integrezi resursele CC2430 pe cip pentru a scrie un sistem mic relativ standardizat. Peste câteva zile, voi face timp să scriu un manual simplu de utilizare pentru hal.h, astfel încât eu și toată lumea să putem folosi ușor CC2430.
În continuare, îmi voi termina cercetarea despre resursele CC2430 on-chip și mă voi dedica învățării stivei de protocoale TI Z-Stack~
Scrierea postărilor pe blog din această serie s-a încheiat pentru moment, dar călătoria lui Zigbee va continua. Peisajul din față este necunoscut, dar cred că autorul va depăși obstacolele cu toată lumea și va gusta suișurile și coborâșurile, și vor exista câștiguri.
Rămâneți pe aproape: postările de pe blogul "Alăturați-vă TI Z-Stack"!















Precedent:Călătoria Zigbee (9): Câteva experimente importante de bază CC2430 - somnul sistematic și starea de veghe întreruptă
Următor:Astăzi este Halloween, cum o să vă distrați?
Postat pe 31.10.2014 08:04:14 |
Iartă-mă că nu am înțeles nimic
Disclaimer:
Tot software-ul, materialele de programare sau articolele publicate de Code Farmer Network sunt destinate exclusiv scopurilor de învățare și cercetare; Conținutul de mai sus nu va fi folosit în scopuri comerciale sau ilegale, altfel utilizatorii vor suporta toate consecințele. Informațiile de pe acest site provin de pe Internet, iar disputele privind drepturile de autor nu au legătură cu acest site. Trebuie să ștergi complet conținutul de mai sus de pe calculatorul tău în termen de 24 de ore de la descărcare. Dacă îți place programul, te rugăm să susții software-ul autentic, să cumperi înregistrarea și să primești servicii autentice mai bune. Dacă există vreo încălcare, vă rugăm să ne contactați prin e-mail.

Mail To:help@itsvse.com