Tämä artikkeli on konekäännöksen peiliartikkeli, klikkaa tästä siirtyäksesi alkuperäiseen artikkeliin.

Näkymä: 10835|Vastaus: 1

Zigbee Journey (10): Kattava koe – lämpötilan seurantajärjestelmä CC2430:n pohjalta

[Kopioi linkki]
Julkaistu 30.10.2014 23.47.44 | | | |
Kirjoitettuaan "Zigbee Journey (9)" 3. maaliskuuta, kirjoittaja suunnitteli alun perin heti aloittavansa pienen kokeen kirjoittamisen "lämpötilan seurantajärjestelmästä" yhteenvetona aiemmista hajanaisista tietopisteistä. Kuitenkin huomasin myös, että vaikka jokainen aiemmista pienistä kokeista oli kuvattu yksityiskohtaisesti, sen koodin normatiivinen ja rakenteellinen luonne voidaan sanoa sietämättömäksi. Koska kyseessä on yhteenveto, meidän tulisi edetä alkuperäisellä pohjalla sen sijaan, että yhdistäisimme aiemmat pienet tiedon pisteet mekaanisesti. Siksi laitoin alkuperäisen suunnitelmani tauolle, käytin aikaa upotetun kehityksen yleisten tekniikoiden oppimiseen ja kirjoitin kaksi esseetäUpotettu C51-ohjelmointimäärittely" ja "Upotetun projektin koodirakenteen hierarkia》。 Tämä päiväkirja ei ole vain yhteenveto Zigbeen ensimmäisestä matkasta, vaan sisältää myös kirjailijan viime päivien oppimiskokemukset, toivoen olevansa hyödyksi Zigbeen aloittelijoille.
Koko teksti on organisoitu ohjelmistokehityksen perusprosessin mukaan: vaatimusten analyysi, luonnoksen suunnittelu, yksityiskohtainen suunnittelu, koodaus, toteutus ja testaus.
1. Kysynnän analyysi
Keskustelun jälkeen "asiakkaan" ja "kehittäjän" välillä määritettiin seuraava järjestelmän toimintojen kuvaus:
… Nykyinen huoneen lämpötila kerätään CC2430-pohjaisilla solmuilla, ja sen lämpötilaarvoja voidaan seurata tietokoneella
… CC2430-solmun itsessään täytyy olla tietty vakausaste ja se voi automaattisesti palata normaalitilaan
… Solmun näytteenottoväli ja tehonhallinta voidaan ohjata PC:llä
2. Ääriviivasuunnittelu
Yllä olevan vaatimusanalyysin mukaan voimme jakaa järjestelmän kahteen moduuliin:CC2430-solmujaPC
  [CC2430-solmu]  
… Ulkoisia parametreja voidaan kerätä säännöllisesti ja lähettää PC:lle
… Automaattinen nollaus, kun laite sammutetaan
… PC:n komennot voidaan vastaanottaa ja käsitellä asianmukaisesti: muuta näytteenottoväliä/virranhallintaa
  [PC]  
… C-kone vastaanottaa ja näyttää dataa sarjaporttityökalun kautta
… Käskyjä voidaan lähettää mikrokontrollerille sarjaporttityökalun kautta sen näytteenottonopeuden ja virranhallinnan hallintaan
3. Yksityiskohtainen suunnittelu
(1) Koodirakenne
Tämän järjestelmän koodirakenteen kerrostaminen on itse asiassa kuvattu esseessä "Upotetun projektin koodirakenteen hierarkia", ja kopio on seuraava:
(1) Laitteiston abstraktiokerros
      [ioCC2430.h] (Järjestelmä sisältyy)Kaikki CC2430:n SFR- ja keskeytysvektorit on määritelty
      [Hal.h] Sisältää yleiset tyyppimääritelmät, yleiset jakomakrot ja CC2430:n sirun sisäisten resurssien yleiset asetukset (I/O, sarjakommunikaatio, ADC, ajastin, virranhallinta jne.)
  (2) Funktionaalinen moduulikerros
      [module.h] määrittelee sirun sisäiset resurssit (ajastimet, I/O), sirun ulkopuoliset laajennusmoduulit (LEDit) sekä niihin liittyvien toimintojen määritykset
      [module.cToteuta jokaisen moduulin alustus (LED).
  (3) Sovelluskerros
      [main.cKatso hal.h, ioCC2430.h ja module.h saavuttaaksesi erityiset sovellusvaatimukset, kuten lämpötilan mittaaminen, viestinnän PC:n kanssa sekä sammutukset ja nollaukset
(2) Kunkin moduulin toteutusmenetelmät
Moduulien mukaan jaettuna ääriviivasuunnittelun mukaan sisäinen järjestelmä voidaan jakaa kahteen päämoduuliin:CC2430-solmujaPC
Koska PC:ssä on sarjaporttiviestintätyökalut, sen toiminnot täyttävät vaatimukset, joten tätä osaa PC:stä ei tarvitse tehdä, eikä sitä tarvitse analysoida. Puhutaanpa alla osasta CC2430
Jokaisen pisteen osafunktion toteutusmenetelmä:
… Käytä ajastimen laskennan ylivuotokeskeytystä ajastetun näytteenoton laukaisemiseen
… UART0-tila sarjaportilla välittää lämpötilatiedot PC:lle
… CC2430:n sisäänrakennettua valvontapiiriä käytetään järjestelmän automaattisen nollaustoiminnon toteuttamiseen
… Sarjaporttia käytetään keskeytysten vastaanottamiseen, jotka tallentavat ja vastaavat PC:n ohjauskomentoihin
1) Jos vastaanotetaan@Merkki on näytteenottovälin ohjauskomento, jota seuraa numero, joka osoittaa näytteenottovälin: 0-0,5s, 1-1s, 2-2s
如:@0,表示每隔0.5秒采样一次。
2) Jos vastaanotetaan$  Merkki on lepotilan ohjauskomento, jota seuraa numero, joka osoittaa virtatilan
Esimerkiksi: $3, mikä tarkoittaa järjestelmän laittamista virtatilaan 3.
(3) Ohjelman kaavio
  • Maisteriohjelman vuokaavio
  • Ajastin 1 ylivuotokeskeytysohjelman kaavio
  • Sarjaportin vastaanottokeskeytysmenettelyn kaavio




4. Koodaustoteutus
(1) Laitteiston abstraktiokerros
Laitteiston abstraktiokerros sisältää ioCC2430.h:n ja hal.h:n. Koska ensimmäinen järjestelmä tulee mukana, sitä ei listata.
Seuraavassa on luettelo kaikista hal.h:n sisällöistä (koska tämä tiedosto on liian pitkä ja näyttää hankalalta, näytän sen moduuleissa):
  • Johto
  • I/O-portit
  • Keskeytetty
  • Sarjaportti
  • Tehon ja kellon hallinta
  • Ajastin
  • Vahtikoira
  • ADC
[url=] [/url]
/***********************************************************
*Tiedostonimi: hal.h
*Kirjoittaja: hustlzp
*Päivämäärä: 8. maaliskuuta 2011
*Painos: 1.1
*Toiminnon kuvaus: Laitteiston abstraktiokerros
*Muokatut asiakirjat:
**********************************************************
*/


#ifndef HAL_H
#defineHAL_H


#include


/***********************************************************
                       Yleiset tyyppimääritelmät
**********************************************************
*/
Typedef ilman signeeraustachar   BYTE;
Typedef ilman signeeraustaint    SANA;
Typedef ilman signeeraustapitkä   DWORD;



/***********************************************************
                       Yleisesti käytetyt makromääritelmät
**********************************************************
*/

//8 sijaa korkeammalle
#defineHIGH_BYTE(a) ((TAVU) (((WORD)(a)) >> 8))


//8 sijaa alempana
#defineLOW_BYTE(a) ((TAVU) ((SANA)(a)))


//Sijoitus
#defineSET_WORD(regH,regL,word)  
   tehdä{                           
      (regH)=HIGH_BYTE(sana);     
      (regL)=LOW_BYTE(sana);      
   }kun(0)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       I/O-portit
**********************************************************
*/
/*Määritä I/O-portin suunta
-----------------------------------------
*/
#defineIO_DIR_PORT_PIN(portti, pin, ohjaus)  
   tehdä{                                 
      jos(dir == IO_OUT)                 
         P##port##DIR |= (0x01<<(pintti));  
      else                              
         P##port##DIR &= ~(0x01<<(pintti));
   }kun(0)



//Parametrin dir arvo on:
#defineIO_IN 0
#defineIO_OUT 1


/*Määritä I/O-portin tulotila
-----------------------------------------
*/
#defineIO_IMODE_PORT_PIN(portti, PIN, imode)
   tehdä{                                    
      jos(imode == IO_IMODE_TRI)            
         P##port##INP |= (0x01<<(pintti));     
      else                                 
         P##port##INP &= ~(0x01<<(pintti));   
   }kun (0)



#define IO_PUD_PORT(portviini, pud)        
   do {                              
      if (pud == IO_PULLDOWN)         
         P2INP |= (0x01 << (port+5));
      else                           
         P2INP &= ~(0x01 << (portti+5));
   } kun (0)


Parametrin PUD arvo on:
#define IO_PULLUP 0 // Vedä ylös
#define IO_PULLDOWN 1 // Vedä alas


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

#define IO_FUNC_PORT_PIN(portti, pinni, func)  
   do {                                    
      if((portti == 2) && (pinni == 3)){      
         if (func) {                       
            P2SEL |= 0x02;                 
         } else {                          
            P2SEL &= ~0x02;               
         }                                 
      }                                    
      else if((portti == 2) && (pinni == 4)){  
         if (func) {                       
            P2SEL |= 0x04;                 
         } else {                          
            P2SEL &= ~0x04;               
         }                                 
      }                                    
      else{                                
         if (func) {                       
            P##port##SEL |= (0x01<<(pin));
         } else {                          
            P##port##SEL &= ~(0x01<<(pin));
        }                                 
      }                                    
   } kun (0)


Func-parametrin arvo on:
#define IO_FUNC_GIO 0 // Yleinen I/O
#define IO_FUNC_PERIPH 1 // Peripheral I/O


Määritä oheislaitteen I/O:n sijainti
#define IO_PER_LOC_TIMER1_AT_PORT0_PIN234() do { PERCFG = (PERCFG&~0x40)|0x00; } kun (0)
#define IO_PER_LOC_TIMER1_AT_PORT1_PIN012() do { PERCFG = (PERCFG&~0x40)|0x40; } kun (0)

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

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

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

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

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

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

//Parametrin imode arvo on:
#defineIO_IMODE_PUD 0   //Vedä ylös/vedä alas
#defineIO_IMODE_TRI 1   //Kolme osavaltiota[url=] [/url]

[url=] [/url]
/***********************************************************
                       Keskeytetty
**********************************************************
*/
//Päälle/pois-keskeytyksille
#defineINT_ON 1
#defineINT_OFF 0


//Käytetään keskeytyslippujen asettamiseen/tyhjentämiseen
#defineINT_SET 1
#defineINT_CLR 0


//Globaalit keskeytysasetukset
#defineINT_GLOBAL_ENABLE(päällä) EA=(!! päällä)


//Määrittele katko
#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


/*Keskeytykset sallittiin
-----------------------------------------
*/
#defineINT_ENABLE(inum, on)                        
   tehdä{                                             
      jos      (inum==INUM_RFERR) { RFERRIE = päällä; }  
      else jos(inum==INUM_ADC)   { ADCIE = päällä; }  
      else jos(inum==INUM_URX0)  { URX0IE = päällä; }  
      else jos(inum==INUM_URX1)  { URX1IE = päällä; }  
      else jos(inum==INUM_ENC)   { ENCIE = päällä; }  
      else jos(inum==INUM_ST)    { STIE = päällä; }  
      else jos(inum==INUM_P2INT) { (päällä)? (IEN2 |=0x02) : (IEN2 &= ~0x02); }
      else jos(inum==INUM_UTX0)  { (päällä)? (IEN2 |=0x04) : (IEN2 &= ~0x04); }
      else jos(inum==INUM_DMA)   { DMAIE = päällä; }  
      else jos(inum==INUM_T1)    { T1IE = päällä; }  
      else jos(inum==INUM_T2)    { T2IE = päällä; }  
      else jos(inum==INUM_T3)    { T3IE = päällä; }  
      else jos(inum==INUM_T4)    { T4IE = päällä; }  
      else jos(inum==INUM_P0INT) { P0IE = päällä; }  
      else jos(inum==INUM_UTX1)  { (päällä)? (IEN2 |=0x08) : (IEN2 &= ~0x08); }
      else jos(inum==INUM_P1INT) { (päällä)? (IEN2 |=0x10) : (IEN2 &= ~0x10); }
      else jos(inum==INUM_RF)    { (päällä)? (IEN2 |=0x01) : (IEN2 &= ~0x01); }
      else jos(inum==INUM_WDT)   { (päällä)? (IEN2 |=0x20) : (IEN2 &= ~0x20); }
   }kun (0)


/*Aseta katkoksen prioriteetti
-----------------------------------------
*/
#defineINT_PRIORITY(ryhmä, PRI)                     
   tehdä{                                               
      jos(pri ==0) { IP0 &= ~ryhmä; IP1 &= ~ryhmä; }
      jos(pri ==1) { IP0 |= ryhmä; IP1 &= ~ryhmä; }
      jos(pri ==2) { IP0 &= ~ryhmä; IP1 |= ryhmä; }
      jos(pri ==3) { IP0 |= ryhmä; IP1 |= ryhmä; }
   }kun (0)

//Parametrin pri arvo on: 0/1/2/3 (korkein prioriteetti)


//Parametriryhmän arvo on:
#defineRFERR_RF_DMA 0x01//Ryhmä IP0
#defineADC_P2INT_T1 0x02//Ryhmä IP1
#defineURX0_UTX0_T2 0x04//Ryhmä IP2
#defineURX1_UTX1_T3 0x08//Ryhmä IP3
#defineENC_P1INT_T4 0x10//Ryhmä IP4
#defineST_WDT_P0INT 0x20//Ryhmä IP5


/*Hae keskeytyslippu
-----------------------------------------
*/
#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                                             
)


/*Aseta keskeytyslippu
-----------------------------------------
*/
#defineINT_SETFLAG(inum, f)                     
   tehdä{                                          
      jos      (inum==INUM_RFERR) { RFERRIF= f; }
      else jos(inum==INUM_ADC)   { ADCIF = f; }
      else jos(inum==INUM_URX0)  { URX0IF = f; }
      else jos(inum==INUM_URX1)  { URX1IF = f; }
      else jos(inum==INUM_ENC)   { ENCIF_1 = ENCIF_0 = f; }
      else jos(inum==INUM_ST)    { STIF = f;  }
      else jos(inum==INUM_P2INT) { P2IF = f;  }
      else jos(inum==INUM_UTX0)  { UTX0IF= f;  }
      else jos(inum==INUM_DMA)   { DMAIF = f;  }
      else jos(inum==INUM_T1)    { T1IF = f;  }
      else jos(inum==INUM_T2)    { T2IF = f;  }
      else jos(inum==INUM_T3)    { T3IF = f;  }
      else jos(inum==INUM_T4)    { T4IF = f;  }
      else jos(inum==INUM_P0INT) { P0IF = f;  }
      else jos(inum==INUM_UTX1)  { UTX1IF= f;  }
      else jos(inum==INUM_P1INT) { P1IF = f;  }
      else jos(inum==INUM_RF)    { (f)? (S1CON |=0x03) : (S1CON &= ~0x03); }
      else jos(inum==INUM_WDT)   { WDTIF = f;  }
   }kun (0)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Sarjaportti
**********************************************************
*/
//Arvon BAUD_E vastaa eri baudinopeuksia
#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  )


//Arvon BAUD_M vastaa eri baudinopeuksia
#defineBAUD_M(pau) (      
    (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)


/*Sarjaportin konfiguraatio UART-tilassa
-----------------------------------------
*/
#defineUART_SETUP(uart, receiveEnable, baudRate, optiot)      
   tehdä{                                                         
      jos((uart) ==0){                                          
         jos(PERCFG &0x01){                                    
            P1SEL |=0x30;                                      
         }else{                                               
            P0SEL |=0x0C;                                      
         }                                                      
      }                                                         
      else{                                                   
         jos(PERCFG &0x02){                                    
            P1SEL |=0xC0;                                      
         }else{                                               
            P0SEL |=0x30;                                      
         }                                                      
      }                                                         
                                                               
      U##uart##GCR = BAUD_E((baudRate),CLKSPD);                 
      U##uart##BAUD = BAUD_M(baudRate);                        
                                                               
      U##uart##CSR |=0x80;                                    
                                                               
      U##uart##CSR |= receiveEnable;                           
                                                               
      U##uart##UCR |= ((vaihtoehdot) |0x80);                       
   }kun(0)
     
//Parametrin arvo receiveEnable:
#defineUART_RECEIVE_ENABLE 0x40   //Luvan saaminen
#defineUART_RECEIVE_DISABLE 0x00   
     
//Parametrivaihtoehtojen arvot:
#defineFLOW_CONTROL_ENABLE 0x40   //Virtauksen säätö
#defineFLOW_CONTROL_DISABLE 0x00


#defineEVEN_PARITY 0x20   //Satunnainen varmennus
#defineODD_PARITY 0x00   //Outo vahvistus


#defineNINE_BIT_TRANSFER 0x10   //9-tavun siirto
#defineEIGHT_BIT_TRANSFER 0x00   //8-tavun siirto


#definePARITY_ENABLE 0x08   //Pariteettitarkistuksen käyttöönotto
#definePARITY_DISABLE 0x00

#defineTWO_STOP_BITS 0x04   //2-asentoinen pysäytysasento
#defineONE_STOP_BITS 0x00   //1 pysäytysasento


#defineHIGH_STOP 0x02   //Pysäytystaso on korkea
#defineLOW_STOP 0x00   //Pysäytysasento on matala
     
#defineHIGH_START 0x01   //Aloitusbitin taso on korkea
#defineLOW_START 0x00   //Aloitusbitin taso on matala


//Sarjaportti lähettää hahmoja
#defineUART_SEND(uart, data)            
   tehdä{                                 
     kun(U##uart##CSR &0x01);        
       U##uart##DBUF = data;            
   }kun (0)
#defineUART0_SEND(data) UART_SEND(0,data)
#defineUART1_SEND(data) UART_SEND(1,data)


//Sarjaportti vastaanottaa merkkejä
#defineUART_RECEIVE(uart, data)         
   tehdä{                                 
     kun(! (U##uart##CSR&0x04));      
       data=U##uart##DBUF;              
   }kun(0)
#defineUART0_RECEIVE(data) UART_RECEIVE(0,data)
#defineUART1_RECEIVE(data) UART_RECEIVE(1,data)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Tehon ja kellon hallinta
**********************************************************
*/
//Hanki kellojakoveri
#defineCLKSPD (CLKCON & 0x07)


//Aseta virtatila
#defineSET_POWER_MODE(tila)                  
   tehdä{                                       
      jos(tila ==0) { UNI &= ~0x03; }
      else jos(tila ==3) { UNI |=0x03;  }
      else{ UNI &= ~0x03; SLEEP |= tila;  }
      PCON |=0x01;                           
      asm("NOP");                              
   }kun (0)


//Parametritila asetetaan seuraaviin arvoihin:
#definePOWER_MODE_0 0x00  
#definePOWER_MODE_1 0x01
#definePOWER_MODE_2 0x02
#definePOWER_MODE_3 0x03


//Käytetään havaitsemaan korkeataajuisten RC-oskillaattoreiden stabiilisuutta
#defineHIGH_FREQUENCY_RC_OSC_STABLE (UNI & 0x20)


//Käytetään kideoskillaattorin stabiilin tilan havaitsemiseen
#defineXOSC_STABLE (UNI & 0x40)


//Saat ajastimen tick-taajuusarvon
#defineTICKSPD ((CLKCON & 0x38) >> 3)


//Aseta pääkellotaajuuden taajuus
#defineSET_MAIN_CLOCK_SOURCE(lähde)
   tehdä{                              
      jos(lähde) {                    
        CLKCON |=0x40;               
        kun(! HIGH_FREQUENCY_RC_OSC_STABLE);
        jos(TICKSPD ==0){            
          CLKCON |=0x08;            
        }                             
        UNI |=0x04;               
      }                              
      else{                          
        UNI &= ~0x04;               
        kun(! XOSC_STABLE);         
        asm("NOP");                  
        CLKCON &= ~0x47;              
        UNI |=0x04;               
      }                              
   }kun (0)


//Parametrilähteen arvo on:
#defineKRISTALLI 0x00   //Kideoskillaattori
#defineRC 0x01   //RC-oskillaattori
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Ajastin 1
**********************************************************
*/
//Ajastin 1 sallii laskennan ylivuodon keskeyttämisen
#defineTIMER1_ENABLE_OVERFLOW_INT(val)
   (TIMIF = (val) ? TIMIF |0x40: TIMIF & ~0x40)


//Aseta ylivuotokeskeytyksen lippu ajastimelle 1
#defineTIMER1_OVERFLOW_INT_SETFLAG(f) (T1CTL= ((T1CTL & (~0x10)) | f))


//Ajastin 1 käynnistyy
#defineTIMER1_RUN(arvo) (T1CTL = (arvo) ? T1CTL|0x02 : T1CTL&~0x03)


//Aseta ajastimen kellojako
#defineSET_TIMER_TICK(arvo) do{ CLKCON = ((CLKCON & (~0x38)) | arvo); } while(0)


//Arvon arvo on:
#defineTIMER1_TICK_32M 0x00  //32MHz
#defineTIMER1_TICK_16M 0x08  //16MHz, järjestelmän nollauksen oletusarvo
#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

//Aseta TICK-jakosuoja ajastimelle 1
#defineSET_TIMER1_TICKDIV(arvo)  
   tehdä{                             
     T1CTL &= ~0x0c;               
     T1CTL |= arvo;               
   }kun (0)
      
//missä arvo on:      
#defineTIMER1_TICKDIV_1 0x00   //1 divisioona
#defineTIMER1_TICKDIV_8 0x04   //8-suuntainen taajuus
#defineTIMER1_TICKDIV_32 0x08
#defineTIMER1_TICKDIV_128 0x0c


//Aseta ajastimen ylivuotoaika
#defineSET_TIMER1_PERIOD(arvo)
   tehdä{                           
     T1CC0H = HIGH_BYTE(arvo);  
     T1CC0L = LOW_BYTE(arvo);   
   }kun (0)
     
//Aseta Timer 1:n toimintatila
#defineSET_TIMER1_MODE(tila)  
   tehdä{                        
     T1CTL = ((T1CTL & (~0x03)) | tila);           
   }kun (0)


//Tilan arvo on:
#defineTIMER1_MODE_STOP 0x00
#defineTIMER1_MODE_FREE 0x01
#defineTIMER1_MODE_MODULE 0x02
#defineTIMER1_MODE_UPDOWN 0x03
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Vahtikoira
**********************************************************
*/
//Aseta ylivuotoaika vahtiajastimelle
#defineWDT_SET_TIMEOUT_PERIOD(aikalisä)
   tehdä{ WDCTL &= ~0x03; WDCTL |= aikalisä; }kun (0)


//Parametrin aikakatkaisun arvo on:
#defineSEC_1 0x00     //1 sekunnin jälkeen
#defineM_SEC_250 0x01     //250 ms jälkeen
#defineM_SEC_15 0x02     //15 ms jälkeen
#defineM_SEC_2 0x03     //2 ms:n jälkeen


//Koiran ruokintamenettelyt
#defineWDT_RESET() do {           
   WDCTL = (WDCTL & ~0xF0) |0xA0;
   WDCTL = (WDCTL & ~0xF0) |0x50;
} kun (0)


//Käynnistä/pysäytä vahtikoiran ajastin
#defineWDT_ENABLE() WDCTL |= 0x08
#defineWDT_DISABLE() WDCTL &= ~0x08
[url=] [/url]

[url=] [/url]
/***********************************************************
                       ADC
**********************************************************
*/
//Konfiguroi yksi ADC
#defineADC_SINGLE_CONVERSION(asetukset)
   tehdä{ ADCCON3 = asetukset; }kun(0)

//Parametrien asetus koostuu seuraavista yhdistelmistä:
//Viitejännite
#defineADC_REF_1_25_V 0x00     //Sisäinen 1,25V viitejännite
#defineADC_REF_P0_7 0x40     //Ulkoinen referenssijännite AIN7-pinnissä
#defineADC_REF_AVDD 0x80     //AVDD_SOC Pinsit
#defineADC_REF_P0_6_P0_7 0xC0     //AIN6-AIN7 Ulkoinen referenssijännite differentiaalituloille


//Näytteenottotaajuus
#defineADC_8_BIT 0x00     //8. sija
#defineADC_10_BIT 0x10     //10. sija
#defineADC_12_BIT 0x20     //12. sija
#defineADC_14_BIT 0x30     //14. sija


//Tule kanavalle
#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     //Maa
#defineADC_TEMP_SENS 0x0E     //Sirun sisäinen lämpötila-anturi
#defineADC_VDD_3 0x0F     //vdd/3




ADC-muunnos on valmis
#define ADC_SAMPLE_READY() (ADCCON1 & 0x80)

#endif
//启动ADC转化
#define ADC_START()
  do { ADCCON1 |= 0x40; } kun (0)//Valitse ADC:n laukaisutila manuaalisesti (eli ADC_SAMPLE_READY)
#defineADC_STOP()  
  tehdä{ ADCCON1 |=0x30; }kun (0)[url=] [/url]


(2) Funktionaalinen moduulikerros
  • module.h
  • module.c
[url=] [/url]
/***********************************************************
*Tiedostonimi: module.h
*Kirjoittaja: hustlzp
*Päivämäärä: 6. maaliskuuta 2011
*Versio: 1.0
*Funktion kuvaus: Toiminnallisen moduulin kerroksen otsikkotiedosto
*Funktioluettelo: void led_init()
            void timer1_init()
            void uart0_init(void);
            void Uart0SendString(allekirjoittamaton hahmo *s);
            float adc_start(tyhjiö)
            void get_temperature(merkitsemätön hahmo *ulostulo, kelluva lämpötila);
            void watchdog_init(void);
*Muokatut asiakirjat:
**********************************************************
*/

#ifndef MODULE_H
#defineMODULE_H


#include"Hal.h"


/***********************************************************
                        LED
**********************************************************
*/
//Määrittele LED-pinnit
#defineled1 P1_0         
#defineLED2 P1_1         
#defineled3 P1_2         
#defineled4 P1_3   

//LED-valot ja pois päältä
#defineLED_OFF 1
#defineLED_ON 0

//LED-alustus
voidled_init(void);




/***********************************************************
                        timer1
**********************************************************
*/
//Käytetään ajastimen ylivuotojakson arvon asettamiseen
#defineTIMER1_OVF_2SEC 0xF424   //2s
#defineTIMER1_OVF_1SEC 0x7A12   //1s
#defineTIMER1_OVF_dot5SEC 0x3D09   //0,5s   

//Ajastin 1 käynnistyy
void  timer1_init(void);
                  

/***********************************************************
                        UART0
**********************************************************
*/
//UART0:n alustus
void  uart0_init(void);                    

//Sarjaporttisiirtojono
void  Uart0SendString(allekirjoittamatonchar*s);
   

/***********************************************************
                        ADC-14
**********************************************************
*/
//Käytetään ADC:n saaman datan muuntamiseen Celsius-lämpötilaksi
#defineADC_TO_CELSIUS(lämpötila) (lämpötila * 0,06229 - 311,43)

//Aloita ADC-muunnos
Floatadc_start(void);

//Muunnos
void  get_temperature(allekirjoittamatonchar*ulostulo,Floattemp);


/***********************************************************
                        WatchDog
**********************************************************
*/
//Vahtikoiran alustus
void  watchdog_init(void);                 

#endif
[url=] [/url]

[url=] [/url]
/***********************************************************
*Tiedostonimi: module.c
*Kirjoittaja: hustlzp
*Päivämäärä: 2011/3/11
*Versio: 1.0
*Funktion kuvaus: Toiminnallisen moduulikerroksen lähdetiedosto
*Toimintolista: (jätetty pois)
*Muokatut asiakirjat:
**********************************************************
*/


#include"module.h"


/***********************************************************
*Toiminnon nimi: led_init
*Toimintotoiminto: LED-alustus
*Sisääntuloparametrit: Ei lainkaan
*Vientiparametrit: Ei
**********************************************************
*/
voidled_init(void)
{
  //Määritä P1.0, P1.1, P1.2 ja P1.3 yleisiksi I/O-portteiksi
  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);
  
  //Määritä P1.0, P1.1, P1.2 ja P1.3 ulostuloiksi
  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;
}


/***********************************************************
*Toiminnon nimi: timer1_init
* Funktiofunktio: Ajastin 1 alustus
*Sisääntuloparametrit: Ei lainkaan
*Vientiparametrit: Ei
**********************************************************
*/
voidtimer1_init(void)
{
  INT_GLOBAL_ENABLE(INT_ON);                 //Avaa globaali keskeytys
  
  INT_ENABLE(INUM_T1, INT_ON);               //Avaa T1-keskeytys

  TIMER1_ENABLE_OVERFLOW_INT(INT_ON);        //Avoin T1-laskennan ylivuotokeskeytys
  
  SET_TIMER_TICK(TIMER1_TICK_4M);            //Aseta ajastin TICK 4MHz:iin
  
  SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);        //Aseta laskenta-aika T1:lle 2:ksi.
  
  SET_TIMER1_TICKDIV(TIMER1_TICKDIV_128);   //Aseta kellon risteys T1:lle arvoon 128
  
  SET_TIMER1_MODE(TIMER1_MODE_MODULE);      //Aseta T1:n juoksutilaksi moduuli
}


/***********************************************************
*Toiminnon nimi: uart0_init
*Toimintotoiminto: Sarjaportin UART0 alustus
*Sisääntuloparametrit: Ei lainkaan
*Vientiparametrit: Ei
**********************************************************
*/
voiduart0_init(void)
{
  //Valitse UART-sijainti
  IO_PER_LOC_UART0_AT_PORT0_PIN2345();
  
  //UART:n konfigurointi: Vastaanotto sallittu, 115200 bps, yksibittinen stop-bitti, ei pariteettia
  UART_SETUP(0, UART_RECEIVE_ENABLE,115200, ONE_STOP_BITS | PARITY_DISABLE);

  //Avaa koko keskeytys
  INT_GLOBAL_ENABLE(INT_ON);      

  //Avaa sarjaportti 0 keskeytysten vastaanottamiseen
  INT_ENABLE(INUM_URX0, INT_ON);   
}


/***********************************************************
*Funktion nimi: Uart0SendString
* Funktiofunktio: Ajastin 1 alustus
*Merkintäparametri: merkitsemätön hahmo *s
            Se merkkijono, jonka haluat lähettää
*Vientiparametrit: Ei
**********************************************************
*/
voidUart0SendString(allekirjoittamatonchar*s)
{
  kun(*s !=0)         
    UART0_SEND(*s++);
}


/***********************************************************
*Toiminnon nimi: adc_start
*Funktiotoiminto: Käynnistä ADC-muunnos
*Sisääntuloparametrit: Ei lainkaan
*Vientiparametri: float
            Tabletin lämpötila-arvo
**********************************************************
*/
Floatadc_start(void)
{
  AllekirjoittamatonintVäliaikainen;
  
  //Viitejännite on 1,25V, näytteenottotarkkuus 14 bittiä ja muunnoskohde on sirun sisäinen lämpötilasensori
  ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);
  
  ADC_STOP();                           //Aseta ADC-muunnoksen laukaisumenetelmä manuaaliseksi
  
  ADC_START();                           //Aloita ADC-muunnos
  
  kun(! ADC_SAMPLE_READY());            //Odota muunnoksen valmistumista
  
  temp = ADCL >>2;                     //Tallenna muunnostulokset lämpötilaan
  temp |= (((allekirjoittamatonint) ADCH) <<6);
  
  PaluuADC_TO_CELSIUS(väliaikainen);           //Palauttaa todellisen lämpötilan arvon muunnoksen jälkeen
}


/***********************************************************
*Toiminnon nimi: get_temperature
*Funktiofunktio: Prosessoi lämpötilaarvo ja tallenna se merkkitaulukkoon sarjalähtöä varten
*Merkintäparametri: allekirjoittamaton hahmo *tulostus
            Käytetään muunnettu lämpötilaarvon tallentamiseen
            Kelluntalämpötila
            Celsius-lämpötila-arvo
*Vientiparametrit: Ei
**********************************************************
*/
voidget_temperature(allekirjoittamatonchar*ulostulo,Floattemp)
{
  Output[0] = (allekirjoittamatonchar)(temp) /10 + 48;         //Kymmenen paikkaa
  Output[1] = (allekirjoittamatonchar)(temp) %10 + 48;         //yksinumeroinen
  Output[2] ='.';                                      //Desimaalipiste
  Output[3] = (allekirjoittamatonchar)(temp*10) %10 + 48;      //Kymmenes
  Output[4] = (allekirjoittamatonchar)(temp*100) %10 + 48;      //Prosenttipiste
  Output[5] ='';                                    //String endifierit
}


/***********************************************************
*Toiminnon nimi: watchdog_init
*Toimintotoiminto: Vahtikoiran alustus
*Sisääntuloparametrit: Ei lainkaan
*Vientiparametrit: Ei
**********************************************************
*/
voidwatchdog_init(void)
{
  WDT_SET_TIMEOUT_PERIOD(SEC_1);   //Aseta aikalisäaika 1 sekunniksi
  WDT_ENABLE();                    //Aloita vahtikoira
}
[url=] [/url]


(3) Sovelluskerros
  • main.c
[url=] [/url]
/*******************************************************************
Tiedoston nimi: main.c
Kirjoittaja: hustlzp
Päivämäärä: 2011/3/11
Versio: 1.0
Toiminnon kuvaus: Pääohjelmatiedosto
Toimintoluettelo: (pois jäetty)
Muokkausmerkintä:
******************************************************************
*/


#include




/********************************************************************
                             Keskeytyspalvelumenettelyt
********************************************************************/
/* 定时器1溢出中断子程序
-------------------------------------------------------*/
#pragma vektori=T1_VECTOR
__interrupt void T1_ISR(void)
{
  EA=0;                                   Portti keskeytyy
  
  led2 = LED_ON;                          
  
  get_temperature(output,adc_start());    Muunna lämpötila-arvo merkkitaulukoksi tulostettavaksi
   
  Uart0SendString(ulostulo);                Lähtölämpötilan arvo
  Uart0SendString("°C");  


  LED2


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

  vastaanotto = U0DBUF;   
  
  if(type==1) // type=1, mikä tarkoittaa, että vastaanotettua merkkiä käytetään ajastimen ylivuotojakson asettamiseen
  {
    type=0;
    Switch(vastaanotto)
    {
      tapaus '0': // Ajastimen ylivuotoaika on 0,5s
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_dot5SEC);
        tauko;
      }
      tapaus '1': // Ajastimen ylivuotoaika on 1s
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_1SEC);
        tauko;
      }
      tapaus '2': // Ajastimen ylivuotoaika on 2s
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
        tauko;         
      }
    }
  }
  muuten if(type==2) // type=2, mikä tarkoittaa, että vastaanotettuja merkkejä käytetään lepotilan hallintaan
  {
    type=0;
    led1 = LED_OFF;
    led2 = LED_OFF;
    led3 = LED_OFF;
    Switch(vastaanotto)
    {
      case '1': // Siirry virtatilaan PM1
      {
        SET_POWER_MODE(1);  
        tauko;
      }
      case '2': // Siirry virtatilaan PM2
      {
        SET_POWER_MODE(2);  
        tauko;
      }
      kotelo '3': //Siirry virtatilaan PM3
      {
        SET_POWER_MODE(3);  
        tauko;
      }
    }
  }
  else if(type==0) // type=0, mikä tarkoittaa, että vastaanotettu merkki on ohjauskomennon tyyppi: @ tai $
  {
    if(receive=='@')  
    {
      type=1;     '@' vastaanotetaan osoittamaan, että seuraavaa merkkiä käytetään ylivuotojakson asettamiseen
    }
    else if(receive=='$')
    {
      type=2;     '$' vastaanotetaan, mikä tarkoittaa, että seuraava merkki käytetään järjestelmän lepotilan hallintaan
    }
  }
  
  led3 = LED_OFF;
   
  EA=1;
}
=LED_OFF;
  
  TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR);   Tyhjennä keskeytyskyltti
  
  EA=1;                                   Avoin keskeytys  
}
/* 主函数
-------------------------------------------------------*/
void main(void)
{
  SET_MAIN_CLOCK_SOURCE(KRISTALLI);  Aseta järjestelmän kellotaajuus 32MHz:iin kideoskillaattori
  
  led_init();                      LED-alustus
  
  uart0_init();                    Sarjaportin UART0 alustus
  
  timer1_init();                   Ajastin 1 käynnistyy
  
  watchdog_init();                 Vahtikoiran alustus
  
  while(1)
  {
    WDT_RESET();                   Ruoki koiraa jatkuvasti
  }
}/********************************************************************
                            Pääohjelma   
********************************************************************/
/* 全局变量
-------------------------------------------------------*/
allekirjoittamaton hahmo tulos[6]={0};       Lämpötiladata tallennetaan helppoa sarjalähtöä varten
Allekirjoittamaton Char vastaanotto;             Tallenna vastaanotetut merkit
allekirjoittamaton hahmotyyppi=0;              Vastaanotetun merkin tyyppilippu asetetaan arvoon 0/1/2"module.h"[url=] [/url]


5. Testaus
Oi~ Koodi on vihdoin liitetty, se on todella uuvuttavaa, testataan tätä pientä järjestelmää:
(1) Aikarajoitettu otanta
Avaa sarjaportti ja aloita IAR-virheenkorjaus, ja huomaa, että led1 on päällä, ja sarjaporttityökalun lämpötila-arvo generoidaan jatkuvasti, ja näytteenottoväli määritellään 2s:ksi:
(2) Näytteenottovälien säätö
Syötä sarjaporttityökaluun "@1" ja testaa sitten näytteenottoväli ja huomaa, että siitä on tullut 1s; Syötä "@0" ja näytteenottoväli on muuttunut 0,5 sekuntiin.
(3) Unen hallinta
Syötä sarjaporttityökaluun "$1" ja huomaa, että kaikki LEDit ovat pois päältä ja lämpötilanäytteenotto on pysähtynyt:
Testauksen jälkeen järjestelmä toimii normaalisti ja vakaasti, ja täyttää käytännössä vaatimukset.
Opiskelijat, jotka tarvitsevat lähdekoodiaLataa tästä
6. Yhteenveto
Tämä artikkeli ottaa hieman kattavan kokeen esimerkkinä osoittaakseen, miten CC2430-sirun sisäisiä resursseja voidaan integroida suhteellisen standardoidun pienen järjestelmän kirjoittamiseksi. Muutaman päivän kuluttua käytän aikaa kirjoittaakseni yksinkertaisen käyttöohjeen hal.h:lle, jotta minä ja kaikki muut voimme helposti käyttää CC2430:aa.
Seuraavaksi viimeistelen tutkimukseni CC2430:n sirun sisäisistä resursseista ja omistaudun TI Z-Stack -protokollapinon oppimiseen~
Tämän sarjan blogikirjoitus on toistaiseksi päättynyt, mutta Zigbeen matka jatkuu. Edessä oleva maisema on tuntematon, mutta uskon, että kirjailija voittaa esteet kaikkien kanssa ja maistaa ylä- ja alamäet, ja siitä tulee hyötyä.
Pysy kuulolla: "Liity TI Z-Stackiin" -blogikirjoituksiin!















Edellinen:Zigbee Journey (9): Useita tärkeitä perus CC2430-kokeita – systemaattinen uni ja keskeytetty valveillaolo
Seuraava:Tänään on Halloween, miten aiot viihdyttää?
Julkaistu 31.10.2014 8.04.14 |
Anna anteeksi, etten ymmärrä mitään
Vastuuvapauslauseke:
Kaikki Code Farmer Networkin julkaisemat ohjelmistot, ohjelmamateriaalit tai artikkelit ovat tarkoitettu vain oppimis- ja tutkimustarkoituksiin; Yllä mainittua sisältöä ei saa käyttää kaupallisiin tai laittomiin tarkoituksiin, muuten käyttäjät joutuvat kantamaan kaikki seuraukset. Tämän sivuston tiedot ovat peräisin internetistä, eikä tekijänoikeuskiistat liity tähän sivustoon. Sinun tulee poistaa yllä oleva sisältö kokonaan tietokoneeltasi 24 tunnin kuluessa lataamisesta. Jos pidät ohjelmasta, tue aitoa ohjelmistoa, osta rekisteröityminen ja hanki parempia aitoja palveluita. Jos rikkomuksia ilmenee, ota meihin yhteyttä sähköpostitse.

Mail To:help@itsvse.com