Ця стаття є дзеркальною статтею машинного перекладу, будь ласка, натисніть тут, щоб перейти до оригінальної статті.

Вид: 10835|Відповідь: 1

Zigbee Journey (10): Комплексний експеримент — система моніторингу температури на основі CC2430

[Копіювати посилання]
Опубліковано 30.10.2014 23:47:44 | | | |
Після написання «Zigbee Journey (9)» 3 березня, автор спочатку планував негайно почати писати невеликий експеримент із «системи моніторингу температури» як підсумок серії розкиданих точок знань раніше. Однак я також усвідомив, що хоча кожен із попередніх невеликих експериментів був детально описаний, нормативний і структурний характер його коду можна назвати нестерпним. Оскільки це підсумок, слід рухатися вперед на початковій основі, а не механічно збирати попередні дрібні точки знань. Тому я відклала свій початковий план, приділила час вивченню загальних технік вбудованої розробки і написала два есеСпецифікація програмування вбудованого C51" і "Ієрархія структури вбудованого коду проєкту》。 Цей журнал є не лише підсумком першої поїздки Зігбі, а й включає досвід навчання автора останніми днями, сподіваючись бути корисним для початківців у Zigbee.
Повний текст організований відповідно до базового процесу розробки програмного забезпечення: аналіз вимог, дизайн контурів, детальне проєктування, реалізація кодування та тестування.
1. Аналіз попиту
Після обговорення між «замовником» і «розробником» було визначено наступний облік функції системи:
… Поточна кімнатна температура збирається вузлами на основі CC2430, а її значення температури можна контролювати за допомогою ПК
… Сам вузол CC2430 повинен мати певний ступінь стабільності і може автоматично повертатися до нормального стану
… Інтервал дискретизації та управління потужністю вузла можуть контролюватися ПК
2. Дизайн контуру
Згідно з наведеним вище аналізом вимог, систему можна поділити на два модулі:Вузол CC2430іPC
  [Вузол CC2430]  
… Зовнішні параметри можна регулярно збирати та надсилати на ПК
… Автоматичне скидання при вимкненні машини
… Команди з ПК можна приймати та обробляти відповідно: змінювати інтервал зразків/управління потужністю
  [ПК]  
… Машина C приймає та відображає дані через інструмент послідовного порту
… Інструкції можна надсилати мікроконтролеру через інструмент послідовного порту для контролю швидкості дискретизації та управління енергоспоживанням
3. Детальне проєктування
(1) Структура коду
Шарування структури коду цієї системи фактично описано в есе "Ієрархія структури вбудованого коду проєкту», а копія виглядає так:
(1) Апаратний абстракційний шар
      [ioCC2430.h] (система включена)Усі SFR та вектори переривання CC2430 визначені
      [hal.h] Включає загальні визначення типів, загальні макроси призначення та спільну конфігурацію ресурсів на кристалі CC2430 (I/O, послідовна комунікація, АЦП, таймер, управління живленням тощо).
  (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 (оскільки цей файл надто довгий і виглядає незручним, я покажу його в модулях):
  • голова
  • Порти введення/виведення
  • Перервано
  • Послідовний порт
  • Керування потужністю та тактовим сигналом
  • Таймер
  • Сторожовий пес
  • ADC
[url=] [/url]
/***********************************************************
*Ім'я файлу: hal.h
*Автор: hustlzp
*Дата: 8 березня 2011 року
*Видання: 1.1
*Опис функції: Апаратний абстракційний шар
*Змінені записи:
**********************************************************
*/


#ifndef HAL_H
#defineHAL_H


#include


/***********************************************************
                       Поширені визначення типів
**********************************************************
*/
typedef unsignedchar   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]
/***********************************************************
                       Порти введення/виведення
**********************************************************
*/
/*Налаштуйте напрямок порту введення/виведення
-----------------------------------------
*/
#defineIO_DIR_PORT_PIN(порт, пін, реж)  
   робити{                                 
      якщо(режисер == IO_OUT)                 
         P##port##DIR |= (0x01<<(штифт));  
      інше                              
         P##port##DIR &= ~(0x01<<(штифт));
   }поки(0)



//Значення параметра dir дорівнює:
#defineIO_IN 0
#defineIO_OUT 1


/*Налаштуйте вхідний режим порту вводу/виводу
-----------------------------------------
*/
#defineIO_IMODE_PORT_PIN(порт, PIN, iMode)
   робити{                                    
      якщо(imode == IO_IMODE_TRI)            
         P##port##INP |= (0x01<<(штифт));     
      інше                                 
         P##port##INP &= ~(0x01<<(штифт));   
   }поки (0)



#define IO_PUD_PORT(порт, пуд)        
   do {                              
      якщо (PUD == 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;               
         }                                 
      }                                    
      інакше if((порт == 2) && (контакт == 4){  
         if (func) {                       
            P2SEL |= 0x04;                 
         } else {                          
            P2SEL &= ~0x04;               
         }                                 
      }                                    
      else{                                
         if (func) {                       
            P##port##SEL |= (0x01<<(штифт));
         } else {                          
            P##port##SEL &= ~(0x01<<(штифт));
        }                                 
      }                                    
   } тоді як (0)


Значення параметра func дорівнює:
#define IO_FUNC_GIO 0 // Загальна I/O
#define IO_FUNC_PERIPH 1 // Периферійний ввод/вивід


Налаштуйте розташування периферійного пристрою вводу/виводу
#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(увімкнено) 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==INUM_ADC)   { ADCIE = on; }  
      інше якщо(інум==INUM_URX0)  { URX0IE = увімкнено; }  
      інше якщо(інум==INUM_URX1)  { URX1IE = увімкнено; }  
      інше якщо(inum==INUM_ENC)   { ENCIE = on; }  
      інше якщо(inum==INUM_ST)    { STIE = увімкнено; }  
      інше якщо(inum==INUM_P2INT) { (увімкнено) ? (IEN2 |=0x02) : (IEN2 &= ~0x02); }
      інше якщо(інум==INUM_UTX0)  { (увімкнено) ? (IEN2 |=0x04) : (IEN2 &= ~0x04); }
      інше якщо(inum==INUM_DMA)   { DMAIE = увімкнено; }  
      інше якщо(inum==INUM_T1)    { T1IE = увімкнено; }  
      інше якщо(інум==INUM_T2)    { T2IE = увімкнено; }  
      інше якщо(inum==INUM_T3)    { T3IE = увімкнено; }  
      інше якщо(inum==INUM_T4)    { T4IE = увімкнено; }  
      інше якщо(inum==INUM_P0INT) { P0IE = увімкнено; }  
      інше якщо(інум==INUM_UTX1)  { (увімкнено) ? (IEN2 |=0x08) : (IEN2 &= ~0x08); }
      інше якщо(інум==INUM_P1INT) { (увімкнено) ? (IEN2 |=0x10) : (IEN2 &= ~0x10); }
      інше якщо(inum==INUM_RF)    { (увімкнено) ? (IEN2 |=0x01) : (IEN2 &= ~0x01); }
      інше якщо(інум==INUM_WDT)   { (увімкнено) ? (IEN2 |=0x20) : (IEN2 &= ~0x20); }
   }поки (0)


/*Встановіть пріоритет відключення
-----------------------------------------
*/
#defineINT_PRIORITY(група, Pri)                     
   робити{                                               
      якщо(pri ==0) { IP0 &= ~group; IP1 &= ~група; }
      якщо(pri ==1) { IP0 |= група; IP1 &= ~група; }
      якщо(pri ==2) { IP0 &= ~group; 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==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_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_P0INT) ? P0IF:
   (інум==INUM_UTX1) ? UTX1IF :
   (інум==INUM_P1INT) ? P1IF:
   (інум==INUM_RF) ? S1CON &= ~0x03    :
   (inum==INUM_WDT) ? WDTIF :
   0                                             
)


/*Встановити прапорець переривання
-----------------------------------------
*/
#defineINT_SETFLAG(inum, f)                     
   робити{                                          
      якщо      (інум==INUM_RFERR) { RFERRIF= f; }
      інше якщо(inum==INUM_ADC)   { ADCIF = f; }
      інше якщо(інум==INUM_URX0)  { URX0IF = f; }
      інше якщо(інум==INUM_URX1)  { URX1IF = f; }
      інше якщо(inum==INUM_ENC)   { ENCIF_1 = ENCIF_0 = f; }
      інше якщо(inum==INUM_ST)    { STIF = f;  }
      інше якщо(inum==INUM_P2INT) { P2IF = f;  }
      інше якщо(інум==INUM_UTX0)  { UTX0IF= f;  }
      інше якщо(inum==INUM_DMA)   { DMAIF = f;  }
      інше якщо(inum==INUM_T1)    { T1IF = f;  }
      інше якщо(інум==INUM_T2)    { T2IF = f;  }
      інше якщо(inum==INUM_T3)    { T3IF = f;  }
      інше якщо(inum==INUM_T4)    { T4IF = f;  }
      інше якщо(inum==INUM_P0INT) { P0IF = f;  }
      інше якщо(інум==INUM_UTX1)  { UTX1IF= f;  }
      інше якщо(інум==INUM_P1INT) { P1IF = f;  }
      інше якщо(inum==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, options)      
   робити{                                                         
      якщо((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 |= receiveEnable;                           
                                                               
      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 = data;            
   }поки (0)
#defineUART0_SEND(data) UART_SEND(0,data)
#defineUART1_SEND(data) UART_SEND(1,data)


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

[url=] [/url]
/***********************************************************
                       Керування потужністю та тактовим сигналом
**********************************************************
*/
//Візьміть кросовер годинника
#defineCLKSPD (CLKCON та 0x07)


//Встановіть режим живлення
#defineSET_POWER_MODE(режим)                  
   робити{                                       
      якщо(режим ==0) { SLEEP &= ~0x03; }
      інше якщо(режим ==3) { SLEEP |=0x03;  }
      інше{ SLEEP &= ~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 (SLEEP & 0x40)


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


//Встановіть головну тактову частоту
#defineSET_MAIN_CLOCK_SOURCE(джерело)
   робити{                              
      якщо(джерело) {                    
        CLKCON |=0x40;               
        поки(! HIGH_FREQUENCY_RC_OSC_STABLE);
        якщо(TICKSPD ==0){            
          CLKCON |=0x08;            
        }                             
        СОН |=0x04;               
      }                              
      інше{                          
        SLEEP &= ~0x04;               
        поки(! XOSC_STABLE);         
        asm("NOP");                  
        CLKCON &= ~0x47;              
        СОН |=0x04;               
      }                              
   }поки (0)


//Значення джерела параметра дорівнює:
#defineКРИСТАЛ 0x00   //Кристалічний осцилятор
#defineRC 0x01   //RC-осцилятор
[url=] [/url]

[url=] [/url]
/***********************************************************
                       Таймер 1
**********************************************************
*/
//Таймер 1 дозволяє переривати переповнення підрахунку
#defineTIMER1_ENABLE_OVERFLOW_INT(Вал)
   (TIMIF = (val) ? 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)) | value); } while(0)


//Значення вартості дорівнює:
#defineTIMER1_TICK_32M 0x00  //32 МГц
#defineTIMER1_TICK_16M 0x08  //16 МГц — значення за замовчуванням для скидання системи
#defineTIMER1_TICK_8M 0x10  //8MHz
#defineTIMER1_TICK_4M 0x18  //4МГц
#defineTIMER1_TICK_2M 0x20  //2MHz
#defineTIMER1_TICK_1M 0x28  //1МГц
#defineTIMER1_TICK_500k 0x30  //500 кГц
#defineTIMER1_TICK_250k 0x38  //250 кГц

//Встановіть кросовер 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 мс
#defineM_SEC_15 0x02     //Після 15 мс
#defineM_SEC_2 0x03     //Після 2 мс


//Процедури годування собак
#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
**********************************************************
*/
//Налаштуйте один АЦП
#defineADC_SINGLE_CONVERSION(налаштування)
   робити{ ADCCON3 = налаштування; }поки(0)

//Налаштування параметрів складається з наступних комбінацій:
//Опорна напруга
#defineADC_REF_1_25_V 0x00     //Внутрішня опорна напруга 1,25 В
#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_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()
            Порожнеча timer1_init()
            void uart0_init(порожнеча);
            void Uart0SendString(непідписані символи *s);
            Float adc_start(порожнеча)
            void get_temperature(незнаковий символ *вихід, temp float);
            void watchdog_init(порожнеча);
*Змінені записи:
**********************************************************
*/

#ifndef MODULE_H
#defineMODULE_H


#include"hal.h"


/***********************************************************
                        LED
**********************************************************
*/
//Визначте світлодіодні контакти
#defineLED1 P1_0         
#defineLED2 P1_1         
#defineLED3 P1_2         
#defineLED4 P1_3   

//Світлодіодне світло і вимкнення
#defineLED_OFF 1
#defineLED_ON 0

//Ініціалізація світлодіодів
Порожнечаled_init(Порожнеча);




/***********************************************************
                        timer1
**********************************************************
*/
//Використовується для встановлення значення періоду переповнення таймера
#defineTIMER1_OVF_2SEC 0xF424   //2s
#defineTIMER1_OVF_1SEC 0x7A12   //1s
#defineTIMER1_OVF_dot5SEC 0x3D09   //0,5 с   

//Таймер 1 ініціалізується
Порожнеча  timer1_init(Порожнеча);
                  

/***********************************************************
                        UART0
**********************************************************
*/
//Ініціалізація UART0
Порожнеча  uart0_init(Порожнеча);                    

//Рядок передачі послідовного порту
Порожнеча  Uart0SendString(без підписуchar*s);
   

/***********************************************************
                        ADC-14
**********************************************************
*/
//Використовується для перетворення даних, отриманих АЦП, у температуру Цельсія
#defineADC_TO_CELSIUS(temp) (temp * 0.06229 - 311.43)

//Ініціація конверсії ADC
Поплавокadc_start(Порожнеча);

//Переобладнання
Порожнеча  get_temperature(без підпису)char*вихід,Поплавоктимчасово);


/***********************************************************
                        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 як загальні порти введення/виведення
  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: Дозволено прийом, 115200 біт/с, однобітний стоп-біт, без парності
  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(без підписуchar*s)
{
  поки(*s !=0)         
    UART0_SEND(*s++);
}


/***********************************************************
*Назва функції: adc_start
*Функція функції: Початок конвертації АЦП
*Параметри входу: Відсутні
*Параметр експорту: float
            Значення температури на планшеті
**********************************************************
*/
Поплавокadc_start(Порожнеча)
{
  Без підписуintтимчасовий;
  
  //Еталонна напруга становить 1,25 В, точність дискретизації — 14 біт, а цільова мета перетворення — датчик температури на мікросхемі
  ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);
  
  ADC_STOP();                           //Встановіть метод тригера для конвертації АЦП у ручне
  
  ADC_START();                           //Ініціація конверсії ADC
  
  поки(! ADC_SAMPLE_READY());            //Чекайте на завершення конверсії
  
  temp = ADCL >>2;                     //Збережіть результати конвертації в температурі
  temp |= (((без знакуint) ADCH) <<6);
  
  ПоверненняADC_TO_CELSIUS(тимчасовий);           //Повертає фактичне значення температури після перетворення
}


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


/***********************************************************
*Назва функції: watchdog_init
*Функція функції: Ініціалізація сторожового собаки
*Параметри входу: Відсутні
*Параметри експорту: відсутні
**********************************************************
*/
Порожнечаwatchdog_init(Порожнеча)
{
  WDT_SET_TIMEOUT_PERIOD(SEC_1);   //Встановіть час тайм-ауту на 1s
  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(вихід,adc_start());    Перетворити температурне значення у масив символів, які потрібно вивести
   
  Uart0SendString(output);                Вихідне значення температури
  Uart0SendString("°C");  


  led2


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

  receive = U0DBUF;   
  
  if(type==1) // type=1, що означає, що отриманий символ використовується для встановлення періоду переповнення таймера
  {
    type=0;
    Перемикати (приймати)
    {
      випадок '0': // Період переповнення таймера — 0,5 с
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_dot5SEC);
        перерва;
      }
      випадок '1': // Період переповнення таймера — 1s
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_1SEC);
        перерва;
      }
      випадок '2': // Період переповнення таймера — 2 секунди
      {
        SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
        перерва;         
      }
    }
  }
  інакше 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);  
        перерва;
      }
    }
  }
  інакше if(type==0) // type=0, що означає, що отриманий символ — це тип команди керування: @ або $
  {
    if(receive=='@')  
    {
      type=1;     '@' отримується, щоб позначити, що наступний символ використовується для встановлення періоду переповнення
    }
    інакше if(receive=='$')
    {
      type=2;     Отримано '$', що означає, що наступний символ використовується для керування системним сном
    }
  }
  
  led3 = LED_OFF;
   
  EA=1;
}
=LED_OFF;
  
  TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR);   Звільніть знак переривання
  
  EA=1;                                   Відкрите переривання  
}
/* 主函数
-------------------------------------------------------*/
Основна порожнеча(порожнеча)
{
  SET_MAIN_CLOCK_SOURCE(КРИСТАЛ);  Встановіть системний тактовий сигнал на кристалічний осцилятор 32 МГц
  
  led_init();                      Ініціалізація світлодіодів
  
  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 увімкнено, а значення температури інструменту послідовного порту постійно генерується, а інтервал вибірки визначається як 2с:
(2) Контроль інтервалу дискретизації
Введіть "@1" у інструменті послідовного порту, потім перевірте інтервал дискретизації і побачте, що він став 1s; Вводите «@0», і інтервал дискретизації змінюється на 0,5 с.
(3) Контроль сну
Введіть "$1" у інструменті послідовного порту і побачите, що всі світлодіоди вимкнені, а температурний вибірковий процес припинено:
Після тестування система працює нормально і стабільно, і фактично відповідає вимогам.
Студенти, яким потрібен вихідний кодНатисніть тут, щоб завантажити
6. Висновок
У цій статті наведено дещо комплексний експеримент як приклад, щоб показати, як інтегрувати ресурси CC2430 на кристалі для створення відносно стандартизованої невеликої системи. За кілька днів я знайду час, щоб написати простий посібник користувача для hal.h, щоб я і всі могли легко користуватися CC2430.
Далі я завершу дослідження ресурсів CC2430 на чипі та присвячу себе вивченню стеку протоколу TI Z-Stack~
Написання блогу в цій серії наразі завершилося, але шлях Зігбі триватиме. Пейзажі попереду невідомі, але я вірю, що автор подолає перешкоди разом з усіма, відчує всі злети й падіння, і будуть здобутки.
Слідкуйте за оновленнями: блог-пости «Приєднуйтесь до TI Z-Stack»!















Попередній:Zigbee Journey (9): Кілька важливих базових експериментів CC2430 — систематичний сон і перерване неспання
Наступний:Сьогодні Гелловін, як ти збираєшся розважати?
Опубліковано 31.10.2014 08:04:14 |
Вибач, що нічого не розумію
Застереження:
Усе програмне забезпечення, програмні матеріали або статті, опубліковані Code Farmer Network, призначені лише для навчання та досліджень; Вищезазначений контент не повинен використовуватися в комерційних чи незаконних цілях, інакше користувачі несуть усі наслідки. Інформація на цьому сайті надходить з Інтернету, і спори щодо авторських прав не мають до цього сайту. Ви повинні повністю видалити вищезазначений контент зі свого комп'ютера протягом 24 годин після завантаження. Якщо вам подобається програма, будь ласка, підтримуйте справжнє програмне забезпечення, купуйте реєстрацію та отримайте кращі справжні послуги. Якщо є будь-яке порушення, будь ласка, зв'яжіться з нами електронною поштою.

Mail To:help@itsvse.com