ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
21 ноября
1440137 Топик полностью
Гyдвин, волшебник (01.06.2024 22:48, просмотров: 308) ответил Гyдвин на Данунахер... 4 года 24/7 на даче работает проектик на MSP430. Беспроводные датчики 868 Мгц, пара реле, GPRS модем. Отсылает статус каждые 2 минуты, принимает команды управления. Следит за коннектом и переподключается в случае необходимости. Без всяческих РТОС. Вот объем кода:
Да вот, собственно, и весь код... 
////////////////////////////////////////////////////////////////////////////
#define	  VER       2     //  Telit  868 МГц  
#define	  INTERVAL 160    // 2 минут * количество 0.75 тиков в минуту = 80    
#define   IDS1           0x265a    // ID "земляного"   датчика
#define   IDS2           0x264F    // ID "воздушного"  датчика
#define   IDB            0x1F11    // ID брелока управления насосом
//#define   RF_POWER        0x40   // -5 dBm
//#define   RF_POWER        0x80   //  4 dBm
//#define   RF_POWER        0xC0   //  12 dBm
#define   RF_POWER        0x50   //  0 dBm
#define   OK              0x009A
#define   ACT             0x027D 
#define   REG             0x0233 
#define   CONNECT         0x020A
//#define   HTTPOK2          0x036A
//#define   HTTPOK         0x036B  // Inovetica
#define   HTTPOK           0x036B    //SWEB
//#define   NOACT           0x027C 
//#define   NOREG1          0x0232  
//#define   NOREG2          0x0234 
#define   T_ON             25     // температура включения вентилятора по-умолчанию
#define   TIMEV            100    // время выключения вентилятора  * 0.75 сек
//////////tst/////////////////////
// 3.5V  LF oscillator
// 20C - 10.14 kHz
//-10C -  9.17 kHz
//+45C - 11.29 kHz
//////////////////////////////////
#include <string.h>
#include "io430.h"
#include "cc110X.h"
#include "stdio.h"
#pragma diag_suppress=Pa082
void reset_modem(void);//
void init_modem(void); //
void debug(unsigned int c); // 
#pragma location=0x1000  
__no_init const unsigned short MY_ID; // серийный номер по адресу 0x1000
volatile unsigned int cnt_t=0; 
volatile unsigned int code =0; 
volatile unsigned char cnt_ch;
volatile unsigned int timeout =0; 
volatile unsigned int del_075;
volatile unsigned int pattern =0; 
volatile unsigned int pump =0; 
volatile unsigned int vent =0; 
volatile unsigned int tON_vent; 
volatile unsigned int cnt_s_pump=0;
volatile unsigned int cnt_s_vent=0;
unsigned char cnt_err;
unsigned char fl_hand_pump=0;
unsigned char fl_hand_vent=0;
unsigned short bat1;  // напряжение батареи 1
unsigned short bat2;  // напряжение батареи 2
unsigned short imp1;  // импеданс 1 
unsigned short imp2;  // импеданс 2
signed   char  tm1;   // температура 1
signed   char  tm2;   // температура 2
//volatile unsigned short deb_code = 0; //for debug2
//volatile unsigned char  fl_code =0; //for debug2
struct {
unsigned short id;   // ID датчика
unsigned short bat;  // напряжение батареи
unsigned short imp;  // импеданс 
signed   char  tm;   // температура
unsigned char  xxx[3] ;    
} rec_rx; 
void work_sens(void)
{
  char len;
  
  WDTCTL = WDT_ARST_1000;// пересброс wdt
 
  if (FL_CC)
   {
    CLR_FL_CC;
    len=8; 
    if(RFReceivePacket((char*)&rec_rx,(char*)&len))
    {
      if (len==7)
      {
       if (rec_rx.id == IDS1)
        {
           bat1=rec_rx.bat;   
           imp1=rec_rx.imp;   
           tm1=rec_rx.tm;    
        }
       if (rec_rx.id == IDS2)
        {
           bat2=rec_rx.bat;   
           imp2=rec_rx.imp;   
           tm2=rec_rx.tm;    
           if(tm2 > tON_vent) vent=TIMEV;  // включить вентилятор     
           // сам выключится через TIMEV, если температура упадет
        }
       if (rec_rx.id == IDB)
        {
          if ((rec_rx.imp==333) && (rec_rx.tm==0))
          { 
              fl_hand_vent=0;
              fl_hand_pump=0;
              P1OUT&=~BIT0; // выключить насос вручную
              P2OUT&=~BIT2; // выключим вентилятор     
          }
          if ((rec_rx.imp==334) && (rec_rx.tm==0))
          {
              fl_hand_pump=1;
              P1OUT|=BIT0; // включить насос вручную,
          }  
          
          if ((rec_rx.imp==335) && (rec_rx.tm==0))
          {
              fl_hand_vent=1;
              P2OUT|=BIT2; // вентилятор включен
          }  
          
        }
      //debug(rec_rx.imp + (rec_rx.tm<<8));
      //debug(rec_rx.id); 
      } 
    } 
    TI_CC_SPIStrobe(TI_CCxxx0_SRX);  // перезапустим прием
   } 
}
void clear_data(void)     // обнуление данных 
{
   bat1=imp1=tm1=0; 
   bat2=imp2=tm2=0; 
}
void delay(unsigned int del)
{
  del_075=del;
  while(del_075)
  {
    work_sens();
  }  
}  
void soft_reset(void)
{
   WDTCTL = WDT_MRST_0_064;              
   while(1);
}
void putchr(char c)
{
   while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
   UCA0TXBUF = c;  
}
void Send_UART(char * byte)
{
	for (;*byte;++byte) putchr (*byte);
	putchr(13);
}
void init_uart(void)
{
//////////////// настроим последовательный порт//////////////////////////////
        UCA0STAT=0;          // c загрузчиком датчиков сбросим uart
        UCA0CTL1 |= UCSWRST; // c загрузчиком датчиков сбросим uart
  
        P1SEL |=  BIT1 + BIT2 ;                    // P1.1 = RXD, P1.2=TXD
        P1SEL2 |= BIT1 + BIT2 ;                    // P1.1 = RXD, P1.2=TXD
        UCA0CTL1 |= UCSSEL_2;                     // SMCLK
        UCA0BR0 = 65;                             // 8MHz 9600 
        UCA0BR1 = 3;                              // 8MHz 9600
        UCA0MCTL|= UCBRS0;                        // Modulation UCBRSx = 1
        UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
        IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
}
void debug(unsigned int c) 
{
  char i;
  #define z 34*8  // 28800
  
  P2OUT|=BIT2; //1
  __delay_cycles(z); 
  P2OUT&=~BIT2; //0      //startt
  __delay_cycles(z); 
  for (i=0;i<8;i++)
   {
    if (c & 1) P2OUT|=BIT2; //1
       else P2OUT&=~BIT2; //0 
     c=c>>1;   
    __delay_cycles(z); 
   } 
  P2OUT|=BIT2; //1 stop
  __delay_cycles(104*8); 
  P2OUT&=~BIT2; //0      //startt
  __delay_cycles(z); 
  for (i=0;i<8;i++)
   {
    if (c & 1) P2OUT|=BIT2; //1
       else P2OUT&=~BIT2; //0 
     c=c>>1;   
    __delay_cycles(z); 
   } 
  P2OUT|=BIT2; //1 stop
  __delay_cycles(104*8); 
}
int command(char * str, unsigned int time, unsigned int patt)
{
  code=0;
  cnt_ch=0;
  timeout=time;
  pattern=patt;
  Send_UART(str);  
  while(timeout)
   {
    work_sens(); 
    if (pattern==0) return(1); 
   }
  if (cnt_ch==0) 
   {
     reset_modem();
     init_modem();
   }  
 return(0);
}
void rf_recal(void)         // рекалибровка радио
{
    TI_CC_SPISetup();
    TI_CC_On(); // инициализация радио
    TI_CC_SPIStrobe(TI_CCxxx0_SRX);  // перезапустим прием
    CLR_FL_CC;
}
void reset_modem(void)
{
   IE2 &= ~UCA0RXIE;         // Didable USCI_A0 RX interrupt
   P1SEL&=  ~(BIT1 + BIT2) ; // переключим в режим GPIO   // P1.1 = RXD, P1.2=TXD
   P1SEL2&= ~(BIT1 + BIT2) ; // переключим в режим GPIO   // P1.1 = RXD, P1.2=TXD
   UCA0CTL1=0;               // выключить UART
   P2OUT|=BIT1;              // выключить стабилизатор 3.9В
   P1OUT&=~BIT2;             // Port ноги TXD = 0; 
   delay(15);// здесь пауза 10 сек
   P2OUT&=~BIT1;              // включить стабилизатор 3.9В
   init_uart();
   delay(3);
   cnt_err=0;   
}
void init_modem(void)
{
   command("AT", 2, OK);
   command("AT", 2, OK);
   command("AT+CGDCONT=1,\"IP\",\"internet\"",2,OK);
   command("AT#HTTPCFG=0",2,OK);
   command("AT#DTMF=0", 2, OK);
   command("AT+CLIP=0", 2, OK);
}
char http_send(void)
{
 int rez = 0;
 char httpstr[100];
 
 if (command("AT+CREG?", 2, REG)) 
  {   
    if (command("AT#SGACT?", 2,  ACT) == 0) command("AT#SGACT=1,1", 20, OK);
    if (command("AT#SGACT?", 2,  ACT) != 0) 
     {
       delay(2);
    // if (command("AT#SD=1,0,80,\"simcon.xyz\"", 20, CONNECT))
       
     if (command("AT#SD=1,0,80,\"goodwin.ru\"", 20, CONNECT)) //SWEB
       {
         delay(2);
    sprintf(httpstr,"GET /test.php?temp=%d,%u,%u,%d,%u,%u,%u,%u, HTTP/1.0\r\nHost: goodwin.ru\r\n\r\n",tm1,imp1,bat1,tm2,imp2,bat2,pump,vent);  // //SWEB
         cnt_s_pump=0;
         cnt_s_vent=0;
         // fl_code=1; //debug2
         rez = command(httpstr, 40, HTTPOK);
         delay(2);
         if (rez)
          {
           // deb_code=333; //debug2
            if (cnt_s_pump > 10) pump=(cnt_s_pump-10)*75;     // время полива в минутах * (0.75 сек * 75 = 60 сек)
            if (cnt_s_vent > 10) tON_vent=(cnt_s_vent-10)+20; // температура включения вентилятора
          } 
       }
     }  
  }
  return(rez); 
 
}
int main( void )
{
 
   WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
   BCSCTL1 = CALBC1_8MHZ;                    // Set DCO 8 MHz
   DCOCTL  = CALDCO_8MHZ;
   
   P2SEL=0; //отключим кварц 
// запретим возможно использованную ранее в загрузчике периферию////// 
   __disable_interrupt();   
   TA0CTL=0;
   TA1CTL=0;
   UCA0CTL0=0; 
   UCA0CTL1=0;
   UCA0MCTL=0;
   UCB0CTL0=0;
   UCB0CTL1=0;
   
   P1REN=0;
   P2REN=0;
   P1SEL=0;
   P1SEL2=0;
  
   IE2=0;
   
///////////////////////////////////////////////////////// 
 
   // это  для  "Telit" GL 868 dual
   // P1.0 - выход реле 1  (out, 0)
   // P1.1 - RX            (in)
   // P1.2 - TX            (out, 1) 
   
   // P2.1 - reset модем   (out, 0) (при сбросе контроллера НЕ сбрасываем модем)
   // P2.2 - выход реле 2  (out, 0) 
 
   
   P1OUT = 0x1E; // 0001 1110 
   P1DIR = 0xBD; // 1011 1101 // биты 2,3,4 вывод единицы, бит 1 вход с подтяжкой к 1  - для RX, бит 1 - реле 1=0
   P1REN |= BIT6; // подтянем вход   MISO к земле     
    
   P2OUT = 0x50; // 0101 0000
   P2DIR = 0x57; // 0101 0111 // для cc1101  
   
/////////////////////////////////////////////////////////////////   
   BCSCTL3 |= LFXT1S_2;                // LFXT1 = VLO (ACLK)  
   
   
     
   
   WDTCTL = WDT_ARST_1000;             // Reset Watchdog Timer to 3 s
   CCTL0 = CCIE;                             // CCR0 interrupt enabled
   CCR0 = 65210;
   TACTL = TASSEL_2 + MC_2;                  // SMCLK, contmode
  
   __enable_interrupt();
   
   
   tON_vent=T_ON;
   clear_data();      // обнуление данных 
   rf_recal();
   init_uart();
   delay(3);
   init_modem();
   
//------------------------------------------------------------
   
   ///   MAIN LOOP  //////
   while (1)
    {
      
     if(http_send())  // посылка отправлена
      {
        rf_recal();     // здесь периодическая рекалибровка радио
        clear_data();   // обнуление данных после успешной посылки 
        cnt_err=0;
        delay(INTERVAL);  // интервал * 0.75 сек.
      }
       else 
       {
         delay(4); // повторить попытку отправки через 3 сек.      
         cnt_err++;
         if (cnt_err> 10)
          {
             reset_modem();
             init_modem();
          }
       }  
    }
 
} 
#pragma vector=USCIAB0RX_VECTOR
__interrupt void usart_interrupt(void)
{
  unsigned char ch;
  ch = UCA0RXBUF; 
  cnt_ch++;
  if (ch!=0x0A)
   {
    if (ch==0x0D) 
     {
      if (code !=0 )
      {
        
       //  deb_code= code;   // debug2        
       //if (fl_code==1)deb_code= code;
       //fl_code=0; 
        
      // debug(code);////////////////////////////////////////////////////////////
       if (code == pattern) pattern=0;     
       code=0;
      }  
     }
     else code=(code+ch);
    if(ch == '}') cnt_s_pump++; // считаем количество символов "}" в ответе PHP скрипта сервера
    if(ch == '{') cnt_s_vent++; // считаем количество символов "{" в ответе PHP скрипта сервера
   } 
}
#pragma vector=NMI_VECTOR
__interrupt void nmi_interrupt(void)
{
  soft_reset();// пересброс  
 // ((void (*)())0x170)(); // Invalid fetch ("call #0170h") // пересброс
}
// Timer A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
  CCR0 += 65210;                            // Add Offset to CCR0
  cnt_t++;
  if (cnt_t==92)
  {
   cnt_t=0;
  
   ////// 
   
  // P1OUT ^= 0x01;                            // Toggle P1.0 Тест
   
   /////
   
   if (timeout) timeout--;
   if (del_075) del_075--; 
  
   if(!fl_hand_pump)
   { 
    if (pump){pump--;P1OUT|=BIT0;} // насос включен, если установлено время  
     else P1OUT&=~BIT0; // выключим насос после окончания времени     
   }
   else pump=0;
   if(!fl_hand_vent)
   { 
    if (vent){vent--;P2OUT|=BIT2;} // вентилятор включен, если установлено время  
     else P2OUT&=~BIT2; // выключим вентилятор     
   }  
   else vent=0;
  }
 
}