Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Atmega8 + gsm obsługa połączeń przychodząc, mini lokalizator kluczy i pilota rtv

14 Maj 2005 01:24 5732 31
  • Poziom 10  
    Witam wszystkich

    Na wstepnie o tym co zrobilem...Zmontowalem ukladzik do zdalnej rejestracji temp, tzn. do Atmega8 podlaczylem 2 czujnik DS18B20 i siemensa s55...na sms'a o okreslonej tresci, pobierana jest temp. i wysylana nadawcy sms'a....

    Uporalem sie z czujnikami i teraz siedze nad komunikcja z siemensem...

    Mam to zrobione na razie tak, ze kazdy przychodzacy sms, wyswietlam na LCD...niestety nie moge odebrac kazdego sms'a...tzn. raz odbieram wszystko dobrze a kiedy indziej same krzaczki....nie wiem kompletnie o co chodzi...

    bylbym bardzo wdzieczny za pomoc...dodam ze, pracuje na wew. generatorze 8MHz..czy problem tkwi wlasnie w nim??

    mam podlaczony zew. rezonator 11,0592 MHz ale nie jest wlaczony..troche boje sie go wlaczyc....dodalem go taka na wszelki wypadek..

    Z gory dziekuja za pomoc

    Ponizej zamieszczam kod.

    Code:

    #include <stdlib.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    #include <avr/pgmspace.h>

    #include "uart.h"
    #include "lcd.h"

    /* define CPU frequency in Mhz here if not defined in Makefile */
    #ifndef F_CPU
    #define F_CPU 8000000UL
    #endif

    /* 19200 baud */
    #define UART_BAUD_RATE      19200     

       unsigned int c=0;
       char sms[260];
       char tresc[260];

       char temp_nr[13]={0,0,0,0,0,0,0,0,0,0,0,0,'\0'};
       
    void zerujTabSms()
    {
       int m=0;
       
       for(m=0;m<260;m++)
       {
          sms[m]=0;
          tresc[m]=0;
       }
    }

    void zerujNumer()
    {
       int w=0;
       
       for(w=0;w<12;w++)
          temp_nr[w]=0;
    }


    void waitms(unsigned int czas)      //tutaj nie ma ograniczenia przedzialu czasu do 255 :-)
    {
       for(;czas>0;czas--)
       {
          unsigned char   x=10;
          for(;x>0;x--)               //petla 1000us=1ms
          {
             TCCR0=0x02;                  //zliczamy impulsy 1us dla fosc=8MHz, clk/8
             TCNT0=155;
           
            while(bit_is_clear(TIFR,TOV0));//czy licznik przekrecony?
               TIFR=1<<TOV0;               //kasowanie flagi przepe-nienia
          }
       }
    }

    unsigned int str2num(char *addr)
    {
       char temp[2]={0,0};
       unsigned int num=0;
       
       temp[0] = *addr;
       temp[1] = *(addr+1);
       sscanf(temp, "%X", &num);
       return (num);
    }


    void odczytajSms()
    {
       unsigned int k=0;
       char ch_1=0,ch_2=0,n=0,pos=0;
       char *smsptr=&sms[2];
       int j=0;

       smsptr=strchr(smsptr,'\x0d')+2;
       
       for (j=22;j<=33;j++)
          temp_nr[j-22]=*(smsptr+j);
          
       k = str2num(smsptr);    //przesunięcie wskaźnika poza numer SCA (centrum usług)
       smsptr += 2 * k + 4;   //i pierwszy oktet
          
       k = str2num(smsptr);    //przes. wskaźnika poza pola: typ  numeru nadawcy, numer
       smsptr += 22 + k + k % 2; //nadawcy,id.protokołu,schemat kodowania,znacznik czasu
          
       k = str2num(smsptr);   //wyznaczenie długości łańcucha
       smsptr += 2;   //wskazanie do pierwszej pozycji tekstu SMS
          
       while(pos<k)    //dopóki nie przekroczono rozmiaru łańcucha
       {
          ch_1 = str2num(smsptr); //zamiana łańcucha na kod znaku
          n = pos % 8;   //obliczenie liczby przesunięć dla 1-go znaku
          ch_1 <<= n;                     //przesunięcie 1-go znaku w lewo n razy
          ch_1 += ch_2;   //maskowanie najstarszego bitu oraz uwzględnienie bitów
          ch_1 &= 0x7F;   //przeniesienia (przy kodowaniu)
          tresc[pos]=ch_1;

          n = 7 - n;    //wyliczenie ilości przesunięć następnego znaku dla odzyskania
          ch_2 = str2num(smsptr) >> n;   //bitów utraconych przy kodowaniu
          if (n == 0)    //cyklicznie - 8 znak brany jest w całości
          {
             ch_2 = 0;
             smsptr-=2;
          }
          pos++;      //następna pozycja w dekodowanym ciągu
          smsptr+=2;
       }
    }

       

    int main(void)
    {

       int i=0;
       
       zerujTabSms();
       
       lcd_init(LCD_DISP_ON);
       
       lcd_clrscr();
     
        /*
         *  Initialize UART library, pass baudrate and avr cpu clock
         *  with the macro UART_BAUD_SELECT()
         */
        uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
       
        /*
         * now enable interrupt, since UART library is interrupt controlled
         */
        sei();
       
        /*
         *  Transmit string to UART
         *  The string is buffered by the uart library in a circular buffer
         *  and one character at a time is transmitted to the UART using interrupts.
         *  uart_puts() blocks if it can not write the whole string to the circular
         *  buffer
         */
          uart_puts("ATE0\x0d");
          waitms(200);
          uart_clear();
          uart_puts("AT+CPMS=MT\x0d");
          waitms(100);
          uart_clear();
          uart_puts("AT+CNMI=1,1,0,2\x0d");
          waitms(100);
          uart_clear();
          
          waitms(2000);
       

          for(;;)
          {
             /*
              * Get received character from ringbuffer
              * uart_getc() returns in the lower byte the received character and
              * in the higher byte (bitmask) the last receive error
              * UART_NO_DATA is returned when no data is available.
              *
              */
             c = uart_getc();
             if ( c & UART_NO_DATA )
             {
                /*
                 * no data available from UART
                 */
                char notice[7]={0,0,0,0,0,0,'\0'};
                unsigned int d=0;
                int nr_sms=0;
                char nr[4]={0,0,0,'\0'};
                char buf[4]={0,0,0,'\0'};
                int y=0;

                notice[0]=sms[2];
                notice[1]=sms[3];
                notice[2]=sms[4];
                notice[3]=sms[5];
                notice[4]=sms[6];
                notice[5]=sms[7];
                
                if (strncasecmp(notice,"+CMTI:",6)==0)
                {
                   nr[0]=sms[14];
                   nr[1]=sms[15];
                   nr[2]=sms[16];
                
                   nr_sms=atoi(nr);
                   itoa (nr_sms,buf,10);
                   
                   uart_clear();
                   uart_puts("AT+CMGR=");       //odbierz sms
                   uart_puts(buf);
                   uart_putc('\x0d');
                   zerujTabSms();
                   zerujNumer();
                   waitms(500);
                   
                   lcd_puts(buf);
                   lcd_putc(':');
                   
                   for (;;)
                   {
                      d = uart_getc();
                      if ( d & UART_NO_DATA )
                      {
                         odczytajSms();
                         break;
                      }
                      else
                      {
                         sms[y]=d;
                         y++;
                      }
                   }

                   uart_clear();
                   uart_puts("AT+CMGD=");          //kasuj sms z pamieci
                   uart_puts(buf);
                   uart_putc('\x0d');
                   waitms(100);
                   uart_clear();
                   
                   if (strncasecmp(tresc,"ebok",4)==0)
                   {

                      lcd_putc(tresc[18]);
                      lcd_putc(tresc[19]);
                      lcd_putc(tresc[20]);
                      lcd_putc(tresc[21]);
                      lcd_putc(tresc[22]);
                      waitms(3000);
                   }
                   else
                   {
                      waitms(3000);
                      lcd_puts("blad!!!");
                   }
                      
                }
                zerujTabSms();
                zerujNumer();
                i=0;
                y=0;
                d=0;
                uart_clear();
                waitms(1000);
                lcd_clrscr();
             }
             else
             {
                /*
                 * new data available from UART
                 * check for Frame or Overrun error
                 */
                sms[i]=c;
                i++;
                
                if ( c & UART_FRAME_ERROR )
                {
                   /* Framing Error detected, i.e no stop bit detected */
       //            lcd_puts("UART Frame Error: ");
                }
                if ( c & UART_OVERRUN_ERROR )
                {
                   /*
                    * Overrun, a character already present in the UART UDR register was
                    * not read by the interrupt handler before the next character arrived,
                    * one or more received characters have been dropped
                    */
       //            lcd_puts("UART Overrun Error: ");
                }
                if ( c & UART_BUFFER_OVERFLOW )
                {
                   /*
                    * We are not reading the receive buffer fast enough,
                    * one or more received character have been dropped
                    */
       //            lcd_puts("Buffer overflow error: ");
                }

             }
          }
    //   }
       
    }
    Darmowe szkolenie: Ethernet w przemyśle dziś i jutro. Zarejestruj się za darmo.
  • VIP Zasłużony dla elektroda
    Nie ma że "boję się" ;). Wewnetrzny oscylator potrafi latać "jak Żyd po pustym sklepie", w zależności od temperatury i zmiany napięcia zasilania. Użycie zewnetrznego oscylatora zdecydowanie poprawi sytuację.
  • Poziom 13  
    Widze że używasz biblioteki którą stworzył Peter Fleury. Osbługa uarta odbywa się w przerwaniach, może masz ustawione za duże bufory w kodzie uart.c i przekroczony zostaje 1k ram w Atmega8? Z drugiej strony spróbuj zmienić lokalne tablice z funkcji main() na globalne, bo zmienne lokalne są tworzone na stosie i może tu leży problem.
  • Poziom 10  
    UART_TX_BUFFER_SIZE i UART_RX_BUFFER_SIZE mam ustawione na 128
    Chyba mieszcze sie w 1KB...

    zrobilem rowniez wszystkie zmnienne globalnymi i dalej nic...raz odbiera dobrze-raz krzaki a innym razem tak jakby nic nie odebral....
  • Poziom 13  
    Możesz opisać w wyniku jakiego ciagu czynności dostajesz krzaki np:
    1. właczam zasilanie
    2. odbiór sms - ok
    3. odbiór sms - krzaki
    4. odbiór sms - zawieszka totalna :-)
    Czy manipulujesz też zasilaniem telefonu? Czy sygnały S55 mają poziomy TTL (może być że interfejs jest na 3V) i czasami coś sie blokuje.
  • Poziom 10  
    nie ma reguly kiedy otrzymam krzaki...wlaczam zasilanie...odbieram pierwszego sms, drugiego...piedziesiatnego (tez testowalem) i jest ok...za jakis czas moge odebrac 3 sms's i 4-ty to krzaki albo cisza....

    co do zasilania to uzywam bufora 74HC125N..telefon normalnie pracuje przy 3.6V i tyle mniej wiecej dostarczam (ok. 3.58V)
  • Poziom 13  
    Rzeczywiście tajemnicze zachowanie... a czy procek też na 3,6V pracuje? Wygląda to raczej na coś "sprzętowego". Jaki masz układ resetu? Czy i jak ustawiałeś w procku 'brownout detector"? Zrób jeszcze prosty test... w tym programie zrób modfikację aby co np. 1sek wypisywał coś na wyświetalczu... mam podejrzenia że może dobrze odbierać a zawiesza sie na procedurach LCD (kiedyś miałem podobny problem).
  • Poziom 10  
    procek pracuje przy 5V. dlatego uzywam tego buforka...pomiedzy atmega a tym buforem umiescilem jeszcze po jednym rezystorku 1k na lini RX i TX....

    zmienialem program i LCD dziala prawidlowo, tzn co 1 sekunde cos mia tam wyswietla...

    Nie ustawialem 'brownout detector" i nie mam ukladu resetu..
  • VIP Zasłużony dla elektroda
    Linia Reset nie może pływać, a przy duzych zakłócniach wewnętrzny rezystor nie pomoże, podciągnij 4k7 do Vcc.
  • Poziom 10  
    na rysunku brakuje linii reset przy programatorze ISP...ale ogolnie oczywscie on jest
  • Poziom 13  
    A bufor 74HC125 z jakiego napięcia jest zasilany?
  • Poziom 10  
    bufor jest zasilany z 5V ale poprzez diode zenera no i w ostatecznosci sie robie ok. 3.6V...
  • Poziom 13  
    Problem może być w poziomach logicznych interfejsu szeregowego telefonu. Założyłbym że linie te są typu CMOS 3V, stan wysoki na lini TX telefonu to bedzie jakieś 2,6V i to bedzie na granicy "uznania" przez HC125 jako stan wysoki z zależności 0,7*VDD dla układów CMOS. Spróbuj zasilić HC125 na 3,3V, lecz nie wiem czy nie bedzie sie zacinać. Osobiście jednak stosuje poniższe rozwiązanie.
  • Poziom 10  
    no tak, ale zastanawia mnie to ze, skoro jest blad sprzetowy to dlaczego raz odbiera a raz nie? jakby bylo cos zle, to w ogole by chyba nie dzialalo...
  • Poziom 24  
    Hej,
    99,9% przyczyną jest zegar. Przejðź na kwarc.
    Pozdrowienia
  • Poziom 13  
    hektor80 napisał:
    no tak, ale zastanawia mnie to ze, skoro jest blad sprzetowy to dlaczego raz odbiera a raz nie? jakby bylo cos zle, to w ogole by chyba nie dzialalo...

    To jak wytłumaczysz to co się dzieje :-), kwarc też jest problemem sprzętowym skoro jest taki niestabilny. Uruchom zewnętrzny kwarc i daj znać czy wszytko działą OK :-)
  • Poziom 10  
    skoro to wszytko jest wina braku kwarcu, to dlaczego nic sie dzieje podczas odczytu temperatury z ds'ow.??? tam zaleznosci czasowe sa chyba wieksze a wszystko sie ladnie odczytuje na wew. generatorze....

    wiec dlaczego??
  • VIP Zasłużony dla elektroda
    Podstawą rozwoju techniki są eksperymenty... ;) Nikt za ciebie niektórych spraw nie ruszy. Wewnętrzny generator jest z leksza niekompatybilny z prędkościami UART, bo powinien dzielić się bez reszty przez 16•dana prędkość transmisji, aby uzyskać zupełną dokładność. Jakbyś zajrzał do noty od DS-a to byś łatwo mógł stwierdzić, że jednak 1-wire jest bardziej tolerancyjny czasowo od UART. Slot czasowy tam wynosi minimalnie 60µs, co daje prędkości ≤ 16,667kbps.
  • Poziom 10  
    co musze zmienic w programie jezeli bede uzywal kwarcu 11.0592MHz??
  • VIP Zasłużony dla elektroda
    Code:
    #define F_CPU 11059200UL
    No i oczywiście odpowiednio ustawić Fusebits - najpierw odczytać ich stan, potem ustawić : wszystkie CKSELn mają być niezaprogramowane, a CKOPT zaprogramowany.
  • Poziom 10  
    a w funkcji waitms nic nie zmieniam??
  • VIP Zasłużony dla elektroda
    Jeżeli to twoja własna, to trzeba ją poprawić... ;) Najlepiej na taką, co sama będzie tworzyła odpowiedni kod wyjściowy na podstawie wartości F_CPU.
  • Poziom 10  
    chodzilo mi o ta funkcje.....

    Code:

    void waitms(unsigned int czas)      //tutaj nie ma ograniczenia przedzialu czasu do 255 :-)
    {
       for(;czas>0;czas--)
       {
          unsigned char   x=10;
          for(;x>0;x--)               //petla 1000us=1ms
          {
             TCCR0=0x02;                  //zliczamy impulsy 1us dla fosc=8MHz, clk/8
             TCNT0=155;
           
            while(bit_is_clear(TIFR,TOV0));//czy licznik przekrecony?
               TIFR=1<<TOV0;               //kasowanie flagi przepe-nienia
          }
       }
    }
  • VIP Zasłużony dla elektroda
    Podrzuce coś do przemyślenia (przerwanie T0OVRFLOW co 1 ms) :
    Code:
    #define Trise      0x07
    
    #define Tfall      0x06
    #define Tdiv1024   0x05
    #define Tdiv256      0x04
    #define Tdiv64      0x03
    #define Tdiv8      0x02
    #define Tdiv1      0x01
    #define Tstop      0x00
    #define usDiv      1000000   // microsecond divisor
    #define msDiv      1000   // milisecond divisor

    #define T0div      Tdiv256
    #define T0Tick      1
    #define T0TickDiv   msDiv // usDiv or msDiv

    #define T0Scale   (1024*(T0div==Tdiv1024)+256*(T0div==Tdiv256)+64*(T0div==Tdiv64)+8*(T0div==Tdiv8)+(T0div==Tdiv1))
    #define T0dly      (T0Tick*F_CPU)/(T0TickDiv*T0Scale)
    #define T0cnt      ~(T0dly)
    .
    .
    .
    void waitms(unsigned int czas)
    {
    TIFR=1<<TOV0;
     for(;czas>0;czas--)
       {
          TCCR0=T0div;
          TCNT0=(unsigned char)T0cnt;
          while(bit_is_clear(TIFR,TOV0));//czy licznik przekrecony?
          TIFR=1<<TOV0;   //kasowanie flagi przepełnienia
       }
    }
    Najlepiej nie stosować w kodzie wartości "na sztywno", niech kompilator je wylicza...
  • Poziom 10  
    no ale ja naprawde jestem poczatkujacy i nie rozumiem tego co napisales....
    czy moglbys mi to jasno napisac co mam konkretnie zrobic?? co zmienic w tej funcji waitms....
    chcialbym to juz wreszcie skonczyc bo termin oddania pracy sie juz zbliza..

    z gory dziekuje....
  • Poziom 10  
    jak wladowalem ta funckje do programu to mi sie nie kompiluje. wyskakuje taki blad:
    Code:

    ....undefined reference to `lo8'...


    Dodano po 4 [godziny] 12 [minuty]:

    chcialem sobie ta funkcje sprawdzic najpierw na wew. generatorze 8Mhz i nie dziala......w tej funkcji zmienilem tylko TCCR0..co mam wpisac do TCNT0? ma tak zostac?

    Code:

    void waitms(unsigned int czas)
    {
    TIFR=1<<TOV0;
     for(;czas>0;czas--)
       {
          TCCR0=0x02;
          TCNT0=(unsigned char)T0cnt;
          while(bit_is_clear(TIFR,TOV0));//czy licznik przekrecony?
          TIFR=1<<TOV0;   //kasowanie flagi przepełnienia
       }
    }
  • VIP Zasłużony dla elektroda
    Co nie działa ? Jakie błedy ? Szklana kula mi się schowała... ;)
  • Poziom 10  
    jak dam np.
    Code:

    waitms(2000);
    lcd_puts("OK");
    lcd_clrscr();


    to nie wyswielta mi tekstu co 2 sek. tylko caly czas....obraz szybko migocze....
  • VIP Zasłużony dla elektroda
    A te #define są wszystkie w kodzie ?