Тази статия е огледална статия за машинен превод, моля, кликнете тук, за да преминете към оригиналната статия.

Изглед: 10835|Отговор: 1

Zigbee Journey (10): Цялостен експеримент - Система за мониторинг на температурата, базирана на CC2430

[Копирай линк]
Публикувано в 30.10.2014 г. 23:47:44 ч. | | | |
След като написа "Zigbee Journey (9)" на 3 март, авторът първоначално планираше веднага да започне да пише малък експеримент за "система за мониторинг на температурата" като обобщение на серия от разпръснати точки на знанието преди това. Въпреки това, осъзнах също, че макар всеки от предишните малки експерименти да беше описан подробно, нормативният и структурен характер на неговия код може да се нарече непоносим. Тъй като това е обобщение, трябва да напредваме на първоначалната основа, вместо механично да сглобяваме предишните малки точки на знание. Затова отложих първоначалния си план, отделих време да науча общите техники на вградената разработка и написах две есетаВградена C51 програмна спецификация" и "Йерархия на вградената структура на проектния код》。 Този дневник не е само обобщение на първото пътуване на Зигби, но и включва научния опит на автора през последните дни, с надеждата да бъде полезен за начинаещите в Зигби.
Пълният текст е организиран според основния процес на разработка на софтуер: анализ на изискванията, дизайн на контури, детайлно проектиране, внедряване на кодиране и тестване.
1. Анализ на търсенето
След обсъждане между "клиента" и "разработчика" беше определено следното описание на системната функция:
… Текущата стайна температура се събира от възли, базирани на CC2430, а нейните стойности на температурата могат да се наблюдават чрез компютър
… Самият възел CC2430 трябва да има определена степен на стабилност и да може автоматично да се върне в нормално състояние
… Интервалът за семплиране и управлението на мощността на възела могат да се контролират от компютър
2. Дизайн на контура
Според горния анализ на изискванията можем да разделим системата на два модула:CC2430 възелиPC
  [CC2430 възел]  
… Външните параметри могат да се събират редовно и изпращат към компютъра
… Автоматично нулиране при изключване на машината
… Команди от компютъра могат да се приемат и обработват съответно: промяна на интервала на семпла/управление на мощността
  [PC]  
… C машината получава и показва данни чрез инструмента за сериен порт
… Инструкции могат да се изпращат към микроконтролера чрез инструмента за серийния порт, за да се контролира скоростта на семплиране и управлението на захранването
3. Детайлно проектиране
(1) Структура на кода
Наслагването на структурата на кода на тази система всъщност е описано в есето "Йерархия на вградената структура на проектния код", а копието е следното:
(1) Хардуерен слой за абстракция
      [ioCC2430.h] (включена е системата)Всички SFR и вектори на прекъсвания на CC2430 са дефинирани
      [hal.h] Включва общи дефиниции на типове, общи макроси за присвояване и обща конфигурация на ресурси на CC2430 в чипа (вход/изход, серийна комуникация, ADC, таймер, управление на захранването и др.)
  (2) Функционален модулен слой
      [module.h] дефинира вътрешни ресурси (таймери, I/O), външни разширителни модули (LED) и обяви на свързани функции
      [module.cРеализирайте инициализацията на всеки модул (LED).
  (3) Приложен слой
      [main.cВижте hal.h, ioCC2430.h и module.h, за да постигнете специфични изисквания за приложение като измерване на температура, комуникация с компютър и изключване и нулиране
(2) Методи за имплементация на всеки модул
Според модулите, разделени според контурния дизайн, вътрешната система може да бъде разделена на два основни модула:CC2430 възелиPC
Тъй като на компютъра има инструменти за серийна комуникация на портове, функциите му могат да отговарят на изискванията, така че не е нужно да правим тази част от компютъра и няма нужда да я анализираме. Нека поговорим за секция CC2430 по-долу
Методът на имплементация на всяка подфункция на точката:
… Използвайте прекъсването на препълването на броя на таймера, за да задействате таймерно вземане на проби
… Режимът UART0 със сериен порт предава температурни данни към компютър
… Вградената наблюдателна схема на CC2430 се използва за реализиране на функцията за автоматично нулиране на системата
… Серийният порт се използва за приемане на прекъсвания с цел улавяне и реакция на команди за управление от компютъра
1) Ако получи@Знакът е команда за контрол на интервала за семплиране, последвана от число, показващо интервала на семплиране: 0-0.5с, 1-1с, 2-2с
如:@0,表示每隔0.5秒采样一次。
2) Ако получи$  Знакът е командата за управление на сън, последвана от число, показващо режим на захранване
Например: $3, което означава да се постави системата в режим на захранване 3.
(3) Схема на потока на програмата
  • Блок-схема на главната програма
  • Таймер 1 Програма за препълване на прекъсване на потока
  • Схема на потока на процедурата за прекъсване при получаване на сериен порт




4. Реализация на кодиране
(1) Хардуерен слой за абстракция
Хардуерният слой за абстракция включва ioCC2430.h и hal.h. Тъй като първата система идва с нея, тя няма да бъде обявена.
Следва списък с цялото съдържание на hal.h (тъй като този файл е твърде дълъг и изглежда неудобен, ще го покажа в модули):
  • глава
  • I/O портове
  • Прекъснат
  • Сериен порт
  • Управление на захранването и часовника
  • Таймер
  • Пазач на кучето
  • ADC
[url=] [/url]
/***********************************************************
*Име на файла: hal.h
*Автор: hustlzp
*Дата: 8 март 2011 г.
*Издание: 1.1
*Описание на функцията: Хардуерен слой за абстракция
*Модифицирани записи:
**********************************************************
*/


#ifndef HAL_H
#defineHAL_H


#include


/***********************************************************
                       Общи дефиниции на типове
**********************************************************
*/
typedef unsignedЧар   BYTE;
typedef unsignedint    ДУМА;
typedef unsignedДълго   DWORD;



/***********************************************************
                       Често използвани макро дефиниции
**********************************************************
*/

//8 места по-високо
#defineHIGH_BYTE(a) ((БАЙТ) (((WORD)(a)) >> 8))


//8 места по-ниско
#defineLOW_BYTE(a) ((БАЙТ) ((WORD)(a)))


//Назначение
#defineSET_WORD(regH,regL,word)  
   правя{                           
      (regH)=HIGH_BYTE(дума);     
      (regL)=LOW_BYTE(дума);      
   }докато(0)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       I/O портове
**********************************************************
*/
/*Конфигурирайте посоката на I/O порта
-----------------------------------------
*/
#defineIO_DIR_PORT_PIN(порт, пин, режисьор)  
   правя{                                 
      ако(реж. == IO_OUT)                 
         P##port##DIR |= (0x01<<(щифт));  
      Друго                              
         P##port##DIR &= ~(0x01<<(щифт));
   }докато(0)



//Стойността на параметъра dir е:
#defineIO_IN 0
#defineIO_OUT 1


/*Конфигурирайте входния режим на I/O порта
-----------------------------------------
*/
#defineIO_IMODE_PORT_PIN(порт, пин, imode)
   правя{                                    
      ако(iMode == IO_IMODE_TRI)            
         P##port##INP |= (0x01<<(щифт));     
      Друго                                 
         P##port##INP &= ~(0x01<<(щифт));   
   }докато (0)



#define IO_PUD_PORT(порт, пуд)        
   do {                              
      ако (пуд == IO_PULLDOWN)         
         P2INP |= (0x01 << (порт+5));
      Друго                           
         P2INP &= ~(0x01 << (порт+5));
   } докато (0)


Стойността на параметъра PUD е:
#define IO_PULLUP 0 // Дръпни нагоре
#define IO_PULLDOWN 1 // Дръпни надолу


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

#define IO_FUNC_PORT_PIN(порт, пин, фънк)  
   do {                                    
      if((порт == 2) && (пин == 3)){      
         if (func) {                       
            P2SEL |= 0x02;                 
         } else {                          
            P2SEL &= ~0x02;               
         }                                 
      }                                    
      else if((порт == 2) && (пин == 4){  
         if (func) {                       
            P2SEL |= 0x04;                 
         } else {                          
            P2SEL &= ~0x04;               
         }                                 
      }                                    
      else{                                
         if (func) {                       
            P##port##SEL |= (0x01<<(щифт));
         } else {                          
            P##port##SEL &= ~(0x01<<(щифт));
        }                                 
      }                                    
   } докато (0)


Стойността на параметърния функ е:
#define IO_FUNC_GIO 0 // Общи I/O
#define IO_FUNC_PERIPH 1 // Периферен вход/изход


Конфигуриране на местоположението на периферното I/O
#define IO_PER_LOC_TIMER1_AT_PORT0_PIN234() do { PERCFG = (PERCFG&~0x40)|0x00; } докато (0)
#define IO_PER_LOC_TIMER1_AT_PORT1_PIN012() do { PERCFG = (PERCFG&~0x40)|0x40; } докато (0)

#define IO_PER_LOC_TIMER3_AT_PORT1_PIN34() do { PERCFG = (PERCFG&~0x20)|0x00; } докато (0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN67() do { PERCFG = (PERCFG&~0x20)|0x20; } докато (0)

#define IO_PER_LOC_TIMER4_AT_PORT1_PIN01() do { PERCFG = (PERCFG&~0x10)|0x00; } докато (0)
#define IO_PER_LOC_TIMER4_AT_PORT2_PIN03() do { PERCFG = (PERCFG&~0x10)|0x10; } докато (0)

#define IO_PER_LOC_SPI1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x08)|0x00; } докато (0)
#define IO_PER_LOC_SPI1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x08)|0x08; } докато (0)

#define IO_PER_LOC_SPI0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x00; } докато (0)
#define IO_PER_LOC_SPI0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x04; } докато (0)

#define IO_PER_LOC_UART1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x02)|0x00; } докато (0)
#define IO_PER_LOC_UART1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x02)|0x02; } докато (0)

#define IO_PER_LOC_UART0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x00; } докато (0)
#define IO_PER_LOC_UART0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x01; } докато (0)

//Стойността на параметра imode е:
#defineIO_IMODE_PUD 0   //Издърпване нагоре/спускане надолу
#defineIO_IMODE_TRI 1   //Три щата[url=] [/url]

[url=] [/url]
/***********************************************************
                       Прекъснат
**********************************************************
*/
//За включване/изключване на прекъсвания
#defineINT_ON 1
#defineINT_OFF 0


//Използва се за поставяне/изчистване на флагове за прекъсване
#defineINT_SET 1
#defineINT_CLR 0


//Глобални настройки на прекъсвания
#defineINT_GLOBAL_ENABLE(on) EA=(!! on)


//Дефинирайте прекъсването
#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


/*Позволени прекъсвания
-----------------------------------------
*/
#defineINT_ENABLE(инум, включен)                        
   правя{                                             
      ако      (инум==INUM_RFERR) { RFERRIE = включен; }  
      Друго ако(инум==INUM_ADC)   { ADCIE = on; }  
      Друго ако(инум==INUM_URX0)  { URX0IE = включен; }  
      Друго ако(инум==INUM_URX1)  { URX1IE = включен; }  
      Друго ако(инум==INUM_ENC)   { ENCIE = on; }  
      Друго ако(инум==INUM_ST)    { STIE = включено; }  
      Друго ако(инум==INUM_P2INT) { (on) ? (IEN2 |=0x02) : (IEN2 &= ~0x02); }
      Друго ако(инум==INUM_UTX0)  { (on) ? (IEN2 |=0x04) : (IEN2 &= ~0x04); }
      Друго ако(инум==INUM_DMA)   { DMAIE = включен; }  
      Друго ако(инум==INUM_T1)    { T1IE = включен; }  
      Друго ако(инум==INUM_T2)    { T2IE = включено; }  
      Друго ако(инум==INUM_T3)    { T3IE = включено; }  
      Друго ако(инум==INUM_T4)    { T4IE = включен; }  
      Друго ако(инум==INUM_P0INT) { P0IE = включен; }  
      Друго ако(инум==INUM_UTX1)  { (on) ? (IEN2 |=0x08) : (IEN2 &= ~0x08); }
      Друго ако(инум==INUM_P1INT) { (on) ? (IEN2 |=0x10) : (IEN2 &= ~0x10); }
      Друго ако(инум==INUM_RF)    { (on) ? (IEN2 |=0x01) : (IEN2 &= ~0x01); }
      Друго ако(инум==INUM_WDT)   { (on) ? (IEN2 |=0x20) : (IEN2 &= ~0x20); }
   }докато (0)


/*Задайте приоритет за прекъсване
-----------------------------------------
*/
#defineINT_PRIORITY(група, Pri)                     
   правя{                                               
      ако(pri ==0) { IP0 &= ~група; IP1 &= ~група; }
      ако(pri ==1) { IP0 |= група; IP1 &= ~група; }
      ако(pri ==2) { IP0 &= ~група; IP1 |= група; }
      ако(pri ==3) { IP0 |= група; IP1 |= група; }
   }докато (0)

//Стойността на параметъра pri е: 0/1/2/3 (с най-висок приоритет)


//Стойността на параметърната група е:
#defineRFERR_RF_DMA 0x01//Групов IP0
#defineADC_P2INT_T1 0x02//Група IP1
#defineURX0_UTX0_T2 0x04//Група IP2
#defineURX1_UTX1_T3 0x08//Група IP3
#defineENC_P1INT_T4 0x10//Група IP4
#defineST_WDT_P0INT 0x20//Група IP5


/*Вземи флага за прекъсване
-----------------------------------------
*/
#defineINT_GETFLAG(инум) (                       
   (инум==INUM_RFERR) ? RFERRIF :
   (инум==INUM_ADC) ? ADCIF :
   (инум==INUM_URX0) ? URX0IF :
   (инум==INUM_URX1) ? URX1IF :
   (инум==INUM_ENC) ? ENCIF_0 :
   (инум==INUM_ST) ? STIF :
   (инум==INUM_P2INT) ? P2IF :
   (инум==INUM_UTX0) ? UTX0IF :
   (инум==INUM_DMA) ? DMAIF :
   (инум==INUM_T1) ? T1IF:
   (инум==INUM_T2) ? T2IF :
   (инум==INUM_T3) ? T3IF :
   (инум==INUM_T4) ? T4IF :
   (инум==INUM_P0INT) ? P0IF:
   (инум==INUM_UTX1) ? UTX1IF :
   (инум==INUM_P1INT) ? P1IF:
   (инум==INUM_RF) ? S1CON &= ~0x03    :
   (инум==INUM_WDT) ? WDTIF :
   0                                             
)


/*Задайте флага за прекъсване
-----------------------------------------
*/
#defineINT_SETFLAG(инум, ж)                     
   правя{                                          
      ако      (инум==INUM_RFERR) { RFERRIF= f; }
      Друго ако(инум==INUM_ADC)   { ADCIF = f; }
      Друго ако(инум==INUM_URX0)  { URX0IF = f; }
      Друго ако(инум==INUM_URX1)  { URX1IF = f; }
      Друго ако(инум==INUM_ENC)   { ENCIF_1 = ENCIF_0 = f; }
      Друго ако(инум==INUM_ST)    { STIF = f;  }
      Друго ако(инум==INUM_P2INT) { P2IF = f;  }
      Друго ако(инум==INUM_UTX0)  { UTX0IF= f;  }
      Друго ако(инум==INUM_DMA)   { DMAIF = f;  }
      Друго ако(инум==INUM_T1)    { T1IF = f;  }
      Друго ако(инум==INUM_T2)    { T2IF = f;  }
      Друго ако(инум==INUM_T3)    { T3IF = f;  }
      Друго ако(инум==INUM_T4)    { T4IF = f;  }
      Друго ако(инум==INUM_P0INT) { P0IF = f;  }
      Друго ако(инум==INUM_UTX1)  { UTX1IF= f;  }
      Друго ако(инум==INUM_P1INT) { P1IF = f;  }
      Друго ако(инум==INUM_RF)    { (f) ? (S1CON |=0x03) : (S1CON &= ~0x03); }
      Друго ако(инум==INUM_WDT)   { WDTIF = f;  }
   }докато (0)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Сериен порт
**********************************************************
*/
//Стойността на BAUD_E съответства на различни скорости на бод
#defineBAUD_E(baud, clkDivPow) (     
    (бод==2400)   ?  6  +clkDivPow :
    (бод==4800)   ?  7  +clkDivPow :
    (бод==9600)   ?  8  +clkDivPow :
    (бод==14400)  ?  8  +clkDivPow :
    (бод==19200)  ?  9  +clkDivPow :
    (бод==28800)  ?  9  +clkDivPow :
    (бод==38400)  ?  10+clkDivPow :
    (бод==57600)  ?  10+clkDivPow :
    (бод==76800)  ?  11+clkDivPow :
    (бод==115200) ?  11+clkDivPow :
    (бод==153600) ?  12+clkDivPow :
    (бод==230400) ?  12+clkDivPow :
    (бод==307200) ?  13+clkDivPow :
    0  )


//Стойността на BAUD_M съответства на различни скорости на бод
#defineBAUD_M(бауд) (      
    (бод==2400)   ?  59  :
    (бод==4800)   ?  59  :
    (бод==9600)   ?  59  :
    (бод==14400)  ?  216 :
    (бод==19200)  ?  59  :
    (бод==28800)  ?  216 :
    (бод==38400)  ?  59  :
    (бод==57600)  ?  216 :
    (бод==76800)  ?  59  :
    (бод==115200) ?  216 :
    (бод==153600) ?  59  :
    (бод==230400) ?  216 :
    (бод==307200) ?  59  :
  0)


/*Конфигуриране на серийния порт в режим UART
-----------------------------------------
*/
#defineUART_SETUP(uart, receiveEnable, baudRate, опции)      
   правя{                                                         
      ако((uart) ==0){                                          
         ако(PERCFG &0x01){                                    
            P1SEL |=0x30;                                      
         }Друго{                                               
            P0SEL |=0x0C;                                      
         }                                                      
      }                                                         
      Друго{                                                   
         ако(PERCFG &0x02){                                    
            P1SEL |=0xC0;                                      
         }Друго{                                               
            P0SEL |=0x30;                                      
         }                                                      
      }                                                         
                                                               
      U##uart##GCR = BAUD_E((baudRate),CLKSPD);                 
      U##uart##BAUD = BAUD_M(baudRate);                        
                                                               
      U##uart##CSR |=0x80;                                    
                                                               
      U##uart##CSR |= получаванеАктивиране;                           
                                                               
      U##uart##UCR |= ((опции) |0x80);                       
   }докато(0)
     
//Стойността на параметъра receiveEnable:
#defineUART_RECEIVE_ENABLE 0x40   //Получаване на разрешение
#defineUART_RECEIVE_DISABLE 0x00   
     
//Стойността на параметрите:
#defineFLOW_CONTROL_ENABLE 0x40   //Контрол на потока
#defineFLOW_CONTROL_DISABLE 0x00


#defineEVEN_PARITY 0x20   //Случайна проверка
#defineODD_PARITY 0x00   //Странна проверка


#defineNINE_BIT_TRANSFER 0x10   //9-байтов трансфер
#defineEIGHT_BIT_TRANSFER 0x00   //8-байтов трансфер


#definePARITY_ENABLE 0x08   //Активиране на проверка на паритет
#definePARITY_DISABLE 0x00

#defineTWO_STOP_BITS 0x04   //2-позиционна стоп позиция
#defineONE_STOP_BITS 0x00   //1 стоп позиция


#defineHIGH_STOP 0x02   //Нивото на спиране е високо
#defineLOW_STOP 0x00   //Стоп позицията е ниска
     
#defineHIGH_START 0x01   //Нивото на началния бит е високо
#defineLOW_START 0x00   //Нивото на началния бит е ниско


//Серийният порт изпраща персонажи
#defineUART_SEND(uart,data)            
   правя{                                 
     докато(U##uart##CSR &0x01);        
       U##uart##DBUF = данни;            
   }докато (0)
#defineUART0_SEND(данни) UART_SEND(0,данни)
#defineUART1_SEND(данни) UART_SEND(1,данни)


//Серийният порт приема символи
#defineUART_RECEIVE(uart,data)         
   правя{                                 
     докато(! (U##uart##CSR&0x04));      
       data=U##uart##DBUF;              
   }докато(0)
#defineUART0_RECEIVE(данни) UART_RECEIVE(0,данни)
#defineUART1_RECEIVE(данни) UART_RECEIVE(1,данни)
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Управление на захранването и часовника
**********************************************************
*/
//Вземи кросоувъра с часовника
#defineCLKSPD (CLKCON и 0x07)


//Настрой режима на захранване
#defineSET_POWER_MODE(режим)                  
   правя{                                       
      ако(режим ==0) { СЪН &= ~0x03; }
      Друго ако(режим ==3) { СЪН |=0x03;  }
      Друго{ СЪН &= ~0x03; SLEEP |= режим;  }
      PCON |=0x01;                           
      asm("NOP");                              
   }докато (0)


//Режимът на параметрите се задава на следните стойности:
#definePOWER_MODE_0 0x00  
#definePOWER_MODE_1 0x01
#definePOWER_MODE_2 0x02
#definePOWER_MODE_3 0x03


//Използва се за откриване на стабилността на високочестотни RC осцилатори
#defineHIGH_FREQUENCY_RC_OSC_STABLE (СЪН & 0x20)


//Използва се за откриване на стабилното състояние на кристалния осцилатор
#defineXOSC_STABLE (СЪН & 0x40)


//Вземи честотата на тиковете на таймера
#defineTICKSPD ((CLKCON и 0x38) >> 3)


//Задайте главната честота на часовника
#defineSET_MAIN_CLOCK_SOURCE(източник)
   правя{                              
      ако(източник) {                    
        CLKCON |=0x40;               
        докато(! HIGH_FREQUENCY_RC_OSC_STABLE);
        ако(TICKSPD ==0){            
          CLKCON |=0x08;            
        }                             
        СЪН |=0x04;               
      }                              
      Друго{                          
        СЪН &= ~0x04;               
        докато(! XOSC_STABLE);         
        asm("NOP");                  
        CLKCON &= ~0x47;              
        СЪН |=0x04;               
      }                              
   }докато (0)


//Стойността на параметърния източник е:
#defineCRYSTAL 0x00   //Кристален осцилатор
#defineRC 0x01   //RC осцилатор
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Таймер 1
**********************************************************
*/
//Таймер 1 позволява препълването на броя да бъде прекъснато
#defineTIMER1_ENABLE_OVERFLOW_INT(вал)
   (TIMIF = (вал) ? TIMIF |0x40: TIMIF & ~0x40)


//Задайте флага за прекъсване на препълване за таймер 1
#defineTIMER1_OVERFLOW_INT_SETFLAG(f) (T1CTL= ((T1CTL & (~0x10)) | f))


//Таймер 1 започва
#defineTIMER1_RUN(стойност) (T1CTL = (стойност) ? T1CTL|0x02 : T1CTL&~0x03)


//Задайте часовниковото деление за таймера
#defineSET_TIMER_TICK(value) do{ CLKCON = (((CLKCON & (~0x38)) | стойност); } докато (0)


//Стойността на стойността е:
#defineTIMER1_TICK_32M 0x00  //32MHz
#defineTIMER1_TICK_16M 0x08  //16MHz, стандартната стойност за нулиране на системата
#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

//Настрой кросоувъра TICK за таймер 1
#defineSET_TIMER1_TICKDIV(стойност)  
   правя{                             
     T1CTL &= ~0x0c;               
     T1CTL |= стойност;               
   }докато (0)
      
//където стойността е:      
#defineTIMER1_TICKDIV_1 0x00   //1 дивизия
#defineTIMER1_TICKDIV_8 0x04   //8-посочна честота
#defineTIMER1_TICKDIV_32 0x08
#defineTIMER1_TICKDIV_128 0x0c


//Задайте период на препълване на таймера
#defineSET_TIMER1_PERIOD(стойност)
   правя{                           
     T1CC0H = HIGH_BYTE(стойност);  
     T1CC0L = LOW_BYTE(стойност);   
   }докато (0)
     
//Задайте режима на работа на Таймер 1
#defineSET_TIMER1_MODE(режим)  
   правя{                        
     T1CTL = ((T1CTL & (~0x03)) | режим);           
   }докато (0)


//Стойността на режима е:
#defineTIMER1_MODE_STOP 0x00
#defineTIMER1_MODE_FREE 0x01
#defineTIMER1_MODE_MODULE 0x02
#defineTIMER1_MODE_UPDOWN 0x03
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Пазач на кучето
**********************************************************
*/
//Задайте периода на препълване за таймера на watchdog
#defineWDT_SET_TIMEOUT_PERIOD(пауза)
   правя{ WDCTL &= ~0x03; WDCTL |= таймаут; }докато (0)


//Стойността на таймаута на параметра е:
#defineSEC_1 0x00     //след 1 секунда
#defineM_SEC_250 0x01     //След 250 ms
#defineM_SEC_15 0x02     //След 15 ms
#defineM_SEC_2 0x03     //След 2 ms


//Процедури за хранене на кучета
#defineWDT_RESET() do {           
   WDCTL = (WDCTL & ~0xF0) |0xA0;
   WDCTL = (WDCTL & ~0xF0) |0x50;
} докато (0)


//Стартиране/спиране на таймера на Watchdog
#defineWDT_ENABLE() WDCTL |= 0x08
#defineWDT_DISABLE() WDCTL &= ~0x08
[url=] [/url]

[url=] [/url]
/***********************************************************
                       ADC
**********************************************************
*/
//Конфигурирайте един ADC
#defineADC_SINGLE_CONVERSION(настройки)
   правя{ ADCCON3 = настройки; }докато(0)

//Настройката на параметъра се състои от следните комбинации:
//Референтно напрежение
#defineADC_REF_1_25_V 0x00     //Вътрешно референтно напрежение 1.25V
#defineADC_REF_P0_7 0x40     //Външно референтно напрежение на пина AIN7
#defineADC_REF_AVDD 0x80     //AVDD_SOC Значки
#defineADC_REF_P0_6_P0_7 0xC0     //AIN6-AIN7 Външно референтно напрежение за диференциални входове


//Честота на семплиране
#defineADC_8_BIT 0x00     //8-мо място
#defineADC_10_BIT 0x10     //10-то място
#defineADC_12_BIT 0x20     //12-то място
#defineADC_14_BIT 0x30     //14-то място


//Влизане в канала
#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     //Земя
#defineADC_TEMP_SENS 0x0E     //Температурен сензор в чипа
#defineADC_VDD_3 0x0F     //vdd/3




Конверсията на ADC е завършена
#define ADC_SAMPLE_READY() (ADCCON1 и 0x80)

#endif
//启动ADC转化
#define ADC_START()
  do { ADCCON1 |= 0x40; } докато (0)//Изберете режим на задействане на ADC като ръчен (т.е. ADC_SAMPLE_READY)
#defineADC_STOP()  
  правя{ ADCCON1 |=0x30; }докато (0)[url=] [/url]


(2) Функционален модулен слой
  • module.h
  • module.c
[url=] [/url]
/***********************************************************
*Име на файла: module.h
*Автор: hustlzp
*Дата: 6 март 2011 г.
*Версия: 1.0
*Описание на функцията: Файл с заглавие на слоя на функционалния модул
*Списък с функции: void led_init()
            Void timer1_init()
            void uart0_init(void);
            void Uart0SendString(неподписан символ *s);
            Float adc_start(Void)
            void get_temperature(Unsigned char *output, float temp);
            void watchdog_init(празнота);
*Модифицирани записи:
**********************************************************
*/

#ifndef MODULE_H
#defineMODULE_H


#include"hal.h"


/***********************************************************
                        LED
**********************************************************
*/
//Определете LED пиновете
#defineled1 P1_0         
#defineLED2 P1_1         
#defineled3 P1_2         
#defineLED4 P1_3   

//LED светлина и изключение
#defineLED_OFF 1
#defineLED_ON 0

//Инициализация на LED
Празнотаled_init(Празнота);




/***********************************************************
                        Таймер1
**********************************************************
*/
//Използва се за задаване на стойността на периода на препълване за таймера
#defineTIMER1_OVF_2SEC 0xF424   //2s
#defineTIMER1_OVF_1SEC 0x7A12   //1s
#defineTIMER1_OVF_dot5SEC 0x3D09   //0.5s   

//Таймер 1 инициализира
Празнота  timer1_init(Празнота);
                  

/***********************************************************
                        UART0
**********************************************************
*/
//Инициализация на UART0
Празнота  uart0_init(Празнота);                    

//Сериен портов предавателен низ
Празнота  Uart0SendString(без знакЧар*s);
   

/***********************************************************
                        ADC-14
**********************************************************
*/
//Използва се за преобразуване на данните, получени от ADC, в температура по Целзий
#defineADC_TO_CELSIUS(temp) (temp * 0.06229 - 311.43)

//Иницииране на конверсия на ADC
Платформаadc_start(Празнота);

//Преобразуване
Празнота  get_temperature(без подписЧар*изход,Платформавременен режим);


/***********************************************************
                        WatchDog
**********************************************************
*/
//Инициализация на кучето за наблюдение
Празнота  watchdog_init(Празнота);                 

#endif
[url=] [/url]

[url=] [/url]
/***********************************************************
*Име на файл: module.c
*Автор: hustlzp
*Дата: 2011/3/11
*Версия: 1.0
*Описание на функцията: Изходен файл на слоя на функционалния модул
*Списък с функции: (пропуснат)
*Модифицирани записи:
**********************************************************
*/


#include"module.h"


/***********************************************************
*Име на функция: led_init
*Функция: LED инициализация
*Параметри на влизане: Няма
*Параметри за експорт: Няма
**********************************************************
*/
Празнотаled_init(Празнота)
{
  //Конфигурирайте P1.0, P1.1, P1.2 и P1.3 като общи 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);
  
  //Конфигурирайте P1.0, P1.1, P1.2 и 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;
}


/***********************************************************
*Име на функцията: timer1_init
* Функция: Инициализация на таймер 1
*Параметри на влизане: Няма
*Параметри за експорт: Няма
**********************************************************
*/
Празнотаtimer1_init(Празнота)
{
  INT_GLOBAL_ENABLE(INT_ON);                 //Отворете глобалното прекъсване
  
  INT_ENABLE(INUM_T1, INT_ON);               //Отворено T1 прекъсване

  TIMER1_ENABLE_OVERFLOW_INT(INT_ON);        //Прекъсване за препълване на броя на отворен T1
  
  SET_TIMER_TICK(TIMER1_TICK_4M);            //Настрой таймера TICK на 4MHz
  
  SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);        //Задайте периода на броене от T1 до 2 секунди
  
  SET_TIMER1_TICKDIV(TIMER1_TICKDIV_128);   //Настройте кросоувъра на часовника от T1 до 128
  
  SET_TIMER1_MODE(TIMER1_MODE_MODULE);      //Задайте режима на работа на T1 на модул
}


/***********************************************************
*Име на функцията: uart0_init
*Функция: Инициализация на сериен порт UART0
*Параметри на влизане: Няма
*Параметри за експорт: Няма
**********************************************************
*/
Празнотаuart0_init(Празнота)
{
  //Изберете местоположението на UART
  IO_PER_LOC_UART0_AT_PORT0_PIN2345();
  
  //Конфигуриране на UART: Допустимо приемане, 115200bps, еднобитов стоп бит, без паритет
  UART_SETUP(0, UART_RECEIVE_ENABLE,115200, ONE_STOP_BITS | PARITY_DISABLE);

  //Отворете тоталното прекъсване
  INT_GLOBAL_ENABLE(INT_ON);      

  //Отворете сериен порт 0 за получаване на прекъсвания
  INT_ENABLE(INUM_URX0, INT_ON);   
}


/***********************************************************
*Име на функцията: Uart0SendString
* Функция: Инициализация на таймер 1
*Входен параметър: неподписан символ *s
            Нишката, която искаш да изпратиш
*Параметри за експорт: Няма
**********************************************************
*/
ПразнотаUart0SendString(без знакЧар*s)
{
  докато(*s !=0)         
    UART0_SEND(*s++);
}


/***********************************************************
*Име на функцията: adc_start
*Функция: Стартиране на конверсия на АЦП
*Параметри на влизане: Няма
*Параметър за експорт: float
            Температурната стойност в таблета
**********************************************************
*/
Платформаadc_start(Празнота)
{
  без подписintвременно;
  
  //Референтното напрежение е 1.25V, точността на семплиране е 14 бита, а целта за преобразуване е температурният сензор на чипа
  ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);
  
  ADC_STOP();                           //Задайте метода на задействане за преобразуване на ADC в ръчно
  
  ADC_START();                           //Иницииране на конверсия на ADC
  
  докато(! ADC_SAMPLE_READY());            //Изчакай конверсията да завърши
  
  temp = ADCL >>2;                     //Запази резултатите от конверсията в температура
  temp |= (((без знакint) ADCH) <<6);
  
  ВръщанеADC_TO_CELSIUS(временно);           //Връща действителната стойност на температурата след преобразуване
}


/***********************************************************
*Име на функцията: get_temperature
*Функция на функцията: Обработете стойността на температурата и я съхранявайте в масива от символи за серийния изход
*Входен параметър: неподписан символ *output
            Използва се за съхранение на преобразуваната температурна стойност
            Температура на плаването
            Температурна стойност на Целзий
*Параметри за експорт: Няма
**********************************************************
*/
Празнотаget_temperature(без подписЧар*изход,Платформаtemp)
{
  Изход[0] = (без знакЧар)(временно) /10 + 48;         //Десет места
  Изход[1] = (без знакЧар)(temp) %10 + 48;         //Едноцифрен брой
  Изход[2] ='.';                                      //Десетична точка
  Изход[3] = (без знакЧар)(temp*10) %10 + 48;      //Десети
  Изход[4] = (без знакЧар)(temp*100) %10 + 48;      //Перцентил
  Изход[5] ='';                                    //Ендификатори на струни
}


/***********************************************************
*Име на функцията: watchdog_init
*Функция: Инициализация на кучето наблюдение
*Параметри на влизане: Няма
*Параметри за експорт: Няма
**********************************************************
*/
Празнотаwatchdog_init(Празнота)
{
  WDT_SET_TIMEOUT_PERIOD(SEC_1);   //Задайте времето за тайм-аут на 1 секунди
  WDT_ENABLE();                    //Стартирай пазачите
}
[url=] [/url]


(3) Приложен слой
  • main.c
[url=] [/url]
/*******************************************************************
Име на файла: main.c
Автор: hustlzp
Дата: 2011/3/11
Версия: 1.0
Описание на функцията: Главен програмен файл
Списък с функции: (пропуснат)
Запис за модификации:
******************************************************************
*/


#include




/********************************************************************
                             Процедури за прекъсване на обслужване
********************************************************************/
/* 定时器1溢出中断子程序
-------------------------------------------------------*/
#pragma вектор=T1_VECTOR
__interrupt празнота T1_ISR(празнота)
{
  EA=0;                                   Портата е прекъсната
  
  led2 = LED_ON;                          
  
  get_temperature(output,adc_start());    Преобразувай стойността на температурата в масив от символи, които трябва да бъдат изведени
   
  Uart0SendString(output);                Стойност на изходната температура
  Uart0SendString("°C");  


  led2


/* 串口接收中断子程序
-------------------------------------------------------*/
#pragma вектор=URX0_VECTOR
__interrupt void RE_ISR(void)
{
  EA=0;
  
  led3 = LED_ON;

  receive = U0DBUF;   
  
  if(type==1) // type=1, което означава, че полученият символ се използва за задаване на периода на препълване на таймера
  {
    type=0;
    Превключване (приемане)
    {
      случай '0': // Периодът на препълване на таймера е 0.5s
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_dot5SEC);
        прекъсване;
      }
      случай '1': // Периодът на препълване на таймера е 1s
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_1SEC);
        прекъсване;
      }
      случай '2': // Периодът на препълване на таймера е 2 секунди
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
        прекъсване;         
      }
    }
  }
  else if(type==2) // type=2, което означава, че получените символи се използват за контрол на съня
  {
    type=0;
    led1 = LED_OFF;
    led2 = LED_OFF;
    led3 = LED_OFF;
    Превключване (приемане)
    {
      случай '1': // Влизане в режим на захранване PM1
      {
        SET_POWER_MODE(1);  
        прекъсване;
      }
      случай '2': // Влизане в режим на захранване PM2
      {
        SET_POWER_MODE(2);  
        прекъсване;
      }
      случай '3': //Влизане в режим захранване PM3
      {
        SET_POWER_MODE(3);  
        прекъсване;
      }
    }
  }
  else if(type==0) // type=0, което показва, че полученият символ е типът на командата за управление: @ или $
  {
    if(получаване=='@')  
    {
      type=1;     '@' се получава, за да посочи, че следващият символ се използва за задаване на периода на препълване
    }
    иначе if(получаване=='$')
    {
      type=2;     Получава се '$', което означава, че следващият символ се използва за контрол на съня в системата
    }
  }
  
  led3 = LED_OFF;
   
  EA=1;
}
=LED_OFF;
  
  TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR);   Изчистете знака за прекъсване
  
  EA=1;                                   Отворено прекъсване  
}
/* 主函数
-------------------------------------------------------*/
Void main(void)
{
  SET_MAIN_CLOCK_SOURCE(КРИСТАЛ);  Настройте системния тактов сигнал на 32MHz кристален осцилатор
  
  led_init();                      Инициализация на LED
  
  uart0_init();                    Инициализация на серийния порт UART0
  
  timer1_init();                   Таймер 1 инициализира
  
  watchdog_init();                 Инициализация на кучето за наблюдение
  
  докато(1)
  {
    WDT_RESET();                   Хранете кучето постоянно
  }
}/********************************************************************
                            Основна програма   
********************************************************************/
/* 全局变量
-------------------------------------------------------*/
неподписан изход на символи[6]={0};       Температурните данни се съхраняват за лесен сериен изход
неподписани чар получават;             Съхранявайте получените знаци
неподписан тип символ=0;              Типовият флаг на получения символ е зададен на 0/1/2"module.h"[url=] [/url]


5. Тестване
О~ Кодът най-накрая е поставен, наистина е изтощително, нека тестваме тази малка система:
(1) Таймерно семплиране
Отворете серийния порт и започнете IAR отстраняване на грешки, и установете, че LED1 е включен, а температурната стойност на инструмента за серийния порт се генерира постоянно, а интервалът на семплиране се определя като 2s:
(2) Контрол на интервала на семплиране
Въведете "@1" в инструмента за сериен порт, след това тествайте интервала на семплиране и установете, че е станал 1s; Въвеждаме "@0" и интервалът на семплиране се променя на 0.5 секунди.
(3) Контрол на съня
Въведете "$1" в инструмента за серийния порт и установете, че всички LED светлини са изключени и температурното измерване е спряло:
След тестване системата работи нормално и стабилно и по същество отговаря на изискванията.
Студенти, които се нуждаят от изходен кодКликнете тук, за да изтеглите
6. Заключение
Тази статия взема леко подробен експеримент като пример, за да покаже как да се интегрират ресурсите на CC2430 в чипа за създаване на сравнително стандартизирана малка система. След няколко дни ще отделя време да напиша прост потребителски наръчник за hal.h, така че аз и всички да можем лесно да работим с CC2430.
След това ще завърша проучването си за ресурси на чипа CC2430 и ще се посветя на изучаването на протоколния стек TI Z-Stack~
Писането на блог постове в тази поредица засега приключи, но пътят на Зигби ще продължи. Пейзажът напред е неизвестен, но вярвам, че авторът ще преодолее препятствията с всички и ще вкуси възходите и паденията, и ще има и успехи.
Останете на линия: блог публикации "Присъединете се към TI Z-Stack"!















Предишен:Zigbee Journey (9): Няколко важни основни експеримента с CC2430 – систематичен сън и прекъсната будност
Следващ:Днес е Хелоуин, как ще забавляваш?
Публикувано в 31.10.2014 г. 8:04:14 ч. |
Прости ми, че не разбирам нищо
Отричане:
Целият софтуер, програмни материали или статии, публикувани от Code Farmer Network, са само за учебни и изследователски цели; Горното съдържание не трябва да се използва за търговски или незаконни цели, в противен случай потребителите ще понесат всички последствия. Информацията на този сайт идва от интернет, а споровете за авторски права нямат нищо общо с този сайт. Трябва напълно да изтриете горното съдържание от компютъра си в рамките на 24 часа след изтеглянето. Ако ви харесва програмата, моля, подкрепете оригинален софтуер, купете регистрация и получете по-добри услуги. Ако има нарушение, моля, свържете се с нас по имейл.

Mail To:help@itsvse.com