logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

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

KamBys 04 Sie 2009 13:44 4780 7
REKLAMA
  • #1 6855716
    KamBys
    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:

    #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:
    #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)
  • REKLAMA
  • #2 6855829
    wdogli
    Poziom 18  
    Hej.
    Tak sie zastanawiam choć całkowicie nie znam sie na komendach at ale po komendach :

    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
  • REKLAMA
  • #4 6858071
    KamBys
    Poziom 23  
    zgodnie z waszymi poradami zmodyfikowalem program:
    procedura unicjujaca po zmianie:

    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:

    #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.
  • REKLAMA
  • #5 6858388
    wdogli
    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:

    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
  • REKLAMA
  • #6 6858821
    KamBys
    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
  • #7 6858832
    maly_elektronik
    Poziom 23  
    Ten twój send string jest strasznie zamotany :(
    zamiast tak:
    
    void UARTSendString(char *data)
    {
       int dlugosc, k =0 ;
       dlugosc = strlen(data);
       for(k = 0; k<dlugosc; k++)
        {
             UARTSendChar(data[k]);
        }
    } 
    

    nie lepiej zrobić tak
    
    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
  • #8 7123811
    kony85
    Poziom 11  
    Aby telefon odpowiadal potrzeba podpiac do masy nozke CTS w jego zlaczu
REKLAMA