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

[atmega][c] odczyt z usart - modem gsm

04 Sie 2009 13:44 4624 7
  • Poziom 23  
    mam problem z odczytem danych z telefonu. wysylanie komend at do telefonu (siemens s45) odbywa sie bez problemu - aparat reaguje prawidlowo. linia Tx kontrolera polaczona z telefonem poprzez opornik i zenera 3,3V. Linia odbiorcza polaczona bezposrednio.
    komunikacja z telefonem za pomoca terminala rowniez dziala prawidlowo.

    biblioteka uart:

    Code:
    #include <avr/io.h> 
    
    #include <util/delay.h>
    #include <stdio.h>
    #include <string.h>

    #define FOSC 11059200                           
    #define UART_BAUD        19200ul                 // prędkość transmisji bit/s
    #define UART_CONST       (F_CPU/(16ul*UART_BAUD))-1
    #define uchar         unsigned char

    unsigned char bufor[32];

    void UARTInit()
    {
       UBRRH = (unsigned char)(UART_CONST>>8);
       UBRRL = (unsigned char)UART_CONST;
       
       /* Enable receiver and transmitter */
       UCSRB = (1<<RXEN)|(1<<TXEN);
       /* ustawienie 8 bitów danych i 1 bity stopu */
       UCSRC = (1<<URSEL)|(3<<UCSZ0);
    }


    void UARTSendChar( unsigned char data )
    {
       /* Wait for empty transmit buffer */
       while ( !( UCSRA & (1<<UDRE)) )
       ;
       /* Put data into buffer, sends the data */
       UDR = data;
    }

    void UARTSendString(char *data)
    {
       int dlugosc, k =0 ;
       dlugosc = strlen(data);
       for(k = 0; k<dlugosc; k++)
        {
             UARTSendChar(data[k]);
        }
    }

    unsigned char UARTReceiveChar( void )
    {
       /* Wait for data to be received */
       while ( !(UCSRA & (1<<RXC)) )
       ;
       /* Get and return received data from buffer */
       return UDR;
    }

    void UARTReceiveString(void)
    {
    unsigned char i=0;

    do
    {

    if ((bufor[i] = UARTReceiveChar()) == '\n') break; //dodaje odebrane znaki do tablicy, jesli odbierze '\n' to przerywa petle i wychodzi z funkcji

    i++;

    }while (i < 32); // zeby nie przepelnic bufora

    }


    program odczytujacy:
    Code:
    #include <avr/io.h> 
    
    //#include <avr/interrupt.h>
    #include <stdlib.h>
    #include "hd44780.h"
    #include "twi.h"
    #include "bcd.h"
    #include <avr/delay.h>
    #include <stdio.h>
    //#include <avr/sleep.h>
    #include <avr/signal.h>


    int main(void)    //Program główny
    {
    unsigned char napis[16];
    //unsigned int value;
    unsigned char napis2[5];
    unsigned char napis3;

    LCD_Initalize(); 
    UARTInit();


    while (1)
    {





    //UARTSendString("AT^SMSO");
    UARTSendString("AT+CGMM");
    UARTSendChar(0x0D);

     napis3 = UARTReceiveChar();
        //  if(napis3 == 0x0D)         // jesli odebrano ENTER czyli LF
          {
        // napis3=UARTReceiveString();
         } 

    LCD_GoTo(0,1);
    LCD_WriteText(napis3);
    _delay_ms(100);
     //LCD_Clear();

    }

    return (0);            //Powrót do początku programu
    }


    niestety program zawiesza sie przy odczycie, nie moge dojsc do ladu zeby odczytac cos z telefonu (w tym przypadku imei)
  • Poziom 18  
    Hej.
    Tak sie zastanawiam choć całkowicie nie znam sie na komendach at ale po komendach :

    Code:
    UARTSendString("AT+CGMM"); 
    
    UARTSendChar(0x0D);


    od razu sprawdzasz czy nie przyszły jakieś dane do bufora i co dalej w momencie gdy nie ma żadnych danych program sie zawiesza pętla while . Może powinieneś zdefiniować sobie przerwanie zewnętrzne od bufora danych przychodzących i wtedy mikrokontroler reagował by tylko wtedy gdy coś przyjdzie do bufora UDR.
    Pozdrawiam
  • Poziom 33  
    zgadzam się z przedmówcą ,włącz przerwania i odbieraj dane w przerwaniach ,dodaj :

    Code:
    UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE);

    oraz :

    Code:
    ISR(USART_RXC_vect)          //przy odebraniu znaku 
    
    {
       bufor = UDR ;
    }
  • Poziom 23  
    zgodnie z waszymi poradami zmodyfikowalem program:
    procedura unicjujaca po zmianie:

    Code:
    void UARTInit() 
    
    {
       UBRRH = (unsigned char)(UART_CONST>>8);
       UBRRL = (unsigned char)UART_CONST;
       
       /* Enable receiver and transmitter */
       UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE);
       /* ustawienie 8 bitów danych i 1 bity stopu */
       UCSRC = (1<<URSEL)|(3<<UCSZ0);
    }


    program glowny:

    Code:
    #include <avr/io.h> 
    
    //#include <avr/interrupt.h>
    #include <stdlib.h>
    #include "hd44780.h"
    #include "twi.h"
    #include "bcd.h"
    #include <avr/delay.h>
    #include <stdio.h>
    //#include <avr/sleep.h>
    #include <avr/signal.h>

    #define VREF _BV(REFS0) //napiecie referencyjne podłaczone do vcc

    #define UART_MAXBUFF 10

    // bufor znaków polecenia
    char uart_rx_buffer[UART_MAXBUFF+1];
    // flaga informująca, czy bufor zawiera całe polecenie
    volatile unsigned char uart_rx_complete;
    // zmienna zawierająca długość polecenia w buforze
    volatile unsigned char uart_rx_len;

    void adc_init()
    {
     
       ACSR=0x80;
       SFIOR=0x00;

       ADMUX=VREF;
       ADCSRA=0x85;
    }

    unsigned int read_adc(unsigned char adc_input)
    {
        ADMUX=adc_input|VREF;             
       ADCSRA|=0x40;                                     
       while ((ADCSRA & 0x10)==0);
       ADCSRA|=0x10;
       return ADCW;
    }

    //SIGNAL(SIG_UART_RECV)
    ISR(USART_RXC_vect)
    {
       char ch = UDR;
       // jeśli ostatnie polecenie nie zostało przetworzone - odrzuć bajt
       if(uart_rx_complete)
          return;

       // jeśli przyszedł znak końca linii - zakończ odbiór
       if(ch == 0x0D)
       {
          uart_rx_buffer[uart_rx_len] = 0;
          uart_rx_complete = 1;
          return;
       }

    // opcjonalne odrzucanie innych znaków
    // if(ch < 0x20 || ch >= 0x80)
        //return;
       
       // jeśli bufor pełny - też zakończ odbiór
       if(uart_rx_len == UART_MAXBUFF)
       {
          uart_rx_buffer[UART_MAXBUFF] = 0;
          uart_rx_complete = 1;
          return;
       }
       
       // można przetworzyć bajt, nie jest to koniec linii i jest miejsce w buforze - dodaj bajt
       uart_rx_buffer[uart_rx_len++] = ch;
    }


    int main(void)    //Program główny
    {
    unsigned char sek;
    unsigned char godz;
    unsigned char min;
    unsigned char napis[16];
    unsigned char napis2[5];
    unsigned char napis3;
    unsigned int themp;

    uart_rx_complete=0;
    LCD_Initalize(); 
    twiinit();
    adc_init();
    UARTInit();
    sei();



    _delay_ms(1000);
    UARTSendString("AT+CGMM");
    //UARTSendString("AT^SMSO");
    UARTSendChar(0x0D);


    while (1)
    {

    if(uart_rx_complete)
          {
                     napis3 = uart_rx_buffer;
             // zwolnienie buforu
             uart_rx_len = 0;
             uart_rx_complete = 0;
          } 



    LCD_GoTo(0,1);
    LCD_WriteText(napis3);
    _delay_ms(100);


    }

    return (0);            //Powrót do początku programu
    }



    niestety program nie dizala prawidlowo - przerwanie wykonuje sie zawsze, w odpowiedzi oczywiscie bezsensowne dane.
  • Poziom 18  
    Ja bym sprawdził jeszcze coś takiego.
    Przypisz zmiennej ch jakaś stała wartość i zobacz czy na wyświetlaczu zostanie wyświetlony poprawny znak odpowiadający tej wartości.
    Druga sprawa to zastanowił bym się nad parametrami transmisji chodzi mi o wartość UBRR. Jak widzę prędkość transmisji masz założoną na 19.2k, kwarc masz 11.0592 MHz i nie ustawiasz bitu U2X a więc wartość UART_CONST będzie wynosiła 35 => 0x0023 proponuję wpisać ją na sztywno pod UART_CONST.

    Trzecia sprawa ta deklaracja:

    Code:
    char ch = UDR;


    zmienna
    char może przechowywać wartości od -128 do 127 a ty UDR będziesz miał liczbę całkowitą nie ujemną a więc powinieneś zastosować
    unsigned char która przechowuje wartości od 0 do 255
    Pozdrawiam
  • Poziom 23  
    od konca:
    poprawilem na unsigned char (2 miejsca, bez zmian)

    zmiana UART_CONST tez nic nie daje, z reszta jak pisalem komunikacja do telefonu jest bez zarzutu

    przypisanie stalej wartosci do "ch" nic nie zmienilo, wiecj est problem z przetwarzaniem odebranych danych. sprawdzilem kod i nic nie znalazlem. gdy w miejsce wyniku przetwarzania, czyli "uart_rx_buffer" wpisze wartosc to jest ona wyswietlana poprawnie. z wyswietlaniem jest wszystko w porzadku - poprawnie wyswietla temp., czas itp co tez mam uzytwe w programie
  • Poziom 23  
    Ten twój send string jest strasznie zamotany :(
    zamiast tak:
    Code:

    void UARTSendString(char *data)
    {
       int dlugosc, k =0 ;
       dlugosc = strlen(data);
       for(k = 0; k<dlugosc; k++)
        {
             UARTSendChar(data[k]);
        }
    }

    nie lepiej zrobić tak
    Code:

    void UARTSendString(char *data)
    {
      while(*data)
      UARTSendChar(*data++);
    }

    Tak będzie prościej i optymalnie bo nie trzeba angażować funkcji srtlen :)

    Pozdrawiam maly_elektronik
  • Poziom 10  
    Aby telefon odpowiadal potrzeba podpiac do masy nozke CTS w jego zlaczu