Эта статья является зеркальной статьёй машинного перевода, пожалуйста, нажмите здесь, чтобы перейти к оригиналу.

Вид: 10835|Ответ: 1

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

[Скопировать ссылку]
Опубликовано 30.10.2014 23:47:44 | | | |
После написания книги «Zigbee Journey (9)» 3 марта автор изначально планировал немедленно начать небольшой эксперимент по «системе мониторинга температуры» как краткое изложение серии разбросанных точек знаний, ранее встречавшихся. Однако я также понял, что хотя каждый из предыдущих небольших экспериментов был подробно описан, нормативный и структурный характер его кода можно назвать невыносимым. Поскольку это резюме, нам следует двигаться вперёд на исходной основе, а не механически собирать предыдущие мелкие знания. Поэтому я отложил свой первоначальный план, потратил время на изучение общих техник встроенной разработки и написал два эссеВстроенная спецификация программирования C51" и "Иерархия встроенной структуры кода проекта》。 Этот журнал не только представляет собой краткое изложение первой поездки Zigbee, но и включает опыт автора в последние дни, надеясь быть полезным новичкам в Zigbee.
Полный текст организован в соответствии с базовым процессом разработки программного обеспечения: анализ требований, проектирование контуров, детальное проектирование, реализация кода и тестирование.
1. Анализ спроса
После обсуждения между «заказчиком» и «разработчиком» было определено следующее описание функции системы:
… Текущая комнатная температура собирается узлами на базе CC2430, и её значения температуры можно контролировать через ПК
… Сам узел CC2430 должен обладать определённой степенью стабильности и может автоматически возвращаться в нормальное состояние
… Интервал дискретизации и управление энергопотреблением узла могут контролироваться ПК
2. Дизайн контуров
Согласно вышеуказанному анализу требований, систему можно разделить на два модуля:узел CC2430иPC
  [узел CC2430]  
… Внешние параметры можно регулярно собирать и отправлять на ПК
… Автоматический сброс при выключении машины
… Команды с ПК могут быть получены и обработаны соответствующим образом: изменение интервала сэмпла/управления энергопотреблением
  [ПК]  
… Машина C принимает и отображает данные через инструмент последовательного порта
… Инструкции могут быть отправлены микроконтроллеру через инструмент последовательного порта для управления скоростью дискретизации и управления энергопотреблением
3. Детальное проектирование
(1) Структура кода
Многослойность структуры кода этой системы на самом деле была описана в эссе «Иерархия встроенной структуры кода проекта», а копия выглядит следующим образом:
(1) Аппаратный уровень абстракции
      [ioCC2430.h] (система включена)Все SFR и векторы прерывания CC2430 определены
      [hal.h] Включает общие определения типов, распространённые макросы назначения и общую конфигурацию ресурсов на чипе CC2430 (ввод/вывод, последовательная связь, АЦП, таймер, управление питанием и др.)
  (2) Функциональный модульный слой
      [module.h] определяет встроенные ресурсы (таймеры, ввод-вывод), модули расширения вне чипа (LED) и объявления связанных функций
      [module.cРеализуйте инициализацию каждого модуля (LED).
  (3) Прикладной уровень
      [main.cОбратитесь к hal.h, ioCC2430.h и module.h для достижения конкретных требований, таких как оценка температуры, взаимодействие с ПК, а также отключение и сброс
(2) Методы реализации каждого модуля
В соответствии с модулями, разделёнными по контурному дизайну, внутренняя система может быть разделена на два основных модуля:узел CC2430иPC
Поскольку на ПК есть инструменты связи с последовательными портами, его функции могут соответствовать требованиям, поэтому нам не нужно делать эту часть ПК и анализировать её нет. Давайте поговорим о разделе CC2430 ниже
Метод реализации каждой подфункции точки:
… Используйте прерывание переполнения таймера для запуска таймерного отбора проб
… Режим UART0 с последовательным портом передаёт температурные данные на ПК
… Встроенная схема watchdog 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 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]
/***********************************************************
                       Порты ввода/вывода
**********************************************************
*/
/*Настройте направление порта ввода/вывода
-----------------------------------------
*/
#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_ADC)   { ADCIE = on; }  
      Другое если(инум==INUM_URX0)  { URX0IE = включено; }  
      Другое если(инум==INUM_URX1)  { URX1IE = on; }  
      Другое если(инум==INUM_ENC)   { ENCIE = on; }  
      Другое если(инум==INUM_ST)    { STIE = on; }  
      Другое если(инум==INUM_P2INT) { (on) ? (IEN2 |=0x02) : (IEN2 &= ~0x02); }
      Другое если(инум==INUM_UTX0)  { (on) ? (IEN2 |=0x04) : (IEN2 &= ~0x04); }
      Другое если(инум==INUM_DMA)   { DMAIE = on; }  
      Другое если(инум==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 &= ~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_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(бауд, клкDivPow) (     
    (бод==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 |= получитьВключить;                           
                                                               
      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) { 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 (СОН и 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 = (вал) ? 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  //8 МГц
#defineTIMER1_TICK_4M 0x18  //4МГц
#defineTIMER1_TICK_2M 0x20  //2МГц
#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




Конвертация АЦП завершена
#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()
            пустота uart0_init(пустота);
            void Uart0SendString(неподписанный символ *s);
            Float adc_start(пустота)
            void get_temperature(неподписанный символ *выход, поплавок temp);
            пустота 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(пустота);




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

//Таймер 1 инициализируется
пустота  timer1_init(пустота);
                  

/***********************************************************
                        UART0
**********************************************************
*/
//Инициализация UART0
пустота  uart0_init(пустота);                    

//Строка передачи последовательных портов
пустота  Uart0SendString(без знакаЧар*s);
   

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

//Инициировать конверсию АЦП
Платформа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_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 на 4 МГц
  
  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 bps, однобитный стоп-бит, без паритета
  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,25 В, точность дискретизации — 14 бит, а цель преобразования — датчик температуры на чипе
  ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);
  
  ADC_STOP();                           //Установите метод триггера для конвертации АЦП в ручное
  
  ADC_START();                           //Инициировать конверсию АЦП
  
  в то время как(! ADC_SAMPLE_READY());            //Ждите завершения конвертации
  
  temp = ADCL >>2;                     //Сохранить результаты преобразования в температуре
  temp |= (((без знакаint) ADCH) <<6);
  
  ВозвращениеADC_TO_CELSIUS(временная);           //Возвращает фактическое значение температуры после преобразования
}


/***********************************************************
*Название функции: get_temperature
*Функция: Обработать значение температуры и сохранить его в массиве символов для последовательного вывода
*Параметр ввода: неподписанный символ *вывод
            Используется для хранения преобразованного значения температуры
            Температура поплавка
            Значение температуры Цельсия
*Параметры экспорта: отсутствуют
**********************************************************
*/
пустотаget_temperature(без подписи)Чар*выход,Платформавременно)
{
  Выход[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(выход,adc_start());    Преобразуем значение температуры в массив символов, которые нужно выводить
   
  Uart0SendString(выход);                Значение выходной температуры
  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': // Период переполнения таймера — 1с
      {
        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(receive=='$')
    {
      type=2;     Получается '$', что означает, что следующий символ используется для управления системным сном
    }
  }
  
  led3 = LED_OFF;
   
  EA=1;
}
=LED_OFF;
  
  TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR);   Очистите знак прерывания
  
  EA=1;                                   Открытое прерывание  
}
/* 主函数
-------------------------------------------------------*/
Void main(void)
{
  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» в инструменте последовательного порта, затем проверьте интервал дискретизации и увидите, что он стал единицами; Появляется «@0», и интервал дискретизации меняется на 0,5 секунды.
(3) Контроль сна
Введите «$1» в инструменте последовательного порта, и все светодиоды выключены, а температурная дискретизация остановлена:
После тестирования система работает нормально и стабильно, и в целом соответствует требованиям.
Студенты, которым нужен исходный кодНажмите здесь, чтобы скачать
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