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.

ATmega + Terminal GSM Siemens MC55

21 Kwi 2009 02:06 4971 3
  • Poziom 11  
    Mam następujący problem:
    Zadaniem docelowym jest wysyłanie wiadomości sms przez podłączony do ATmega32 terminal GSM przez RS-232. Problem polega na tym, że modem nie odpowiada na komendy AT wysyłane z ATmegi.

    PARAMETRY UKłADU:
    - Terminal Siemens MC55:
    - Atmega32, zewnętrzny kwarc 8MHz.

    Komunikacja Terminal GSM -> PC działają poprawnie. Wysyłająć z PC przez hyperterminal komendy do terminala GSM, np. "AT" - odpowiada OK, niezależnie od parametrów transmisji w hyperterminalu (jest to prawdopodobnie zasługą wykrywania szybkości transmisji autobaundrate).

    Wysyłanie i odbiór znaków z ATmegi do kompa również działa OK.

    Problem pojawia się, gdy łączę ATmegę z terminalem. Prosty program w C wysyła "AT"+CR do terminala i oczekuje na odbiór znaku, po czym powinien zamrugać 3 razy diodą. Do mrugania jednak nie dochodzi bo program wiesza się na odbiorze znaku z terminala (listing poniżej). Próbowałem również wysyłać pojedyncze znaki, które teoretycznie terminal powinien odsyłać ze względu na włączone echo.

    Dodam jeszcze, że PC łączą z ATmegą kablem żeńsko-żeńskim z przeplotem, a PC z terminalem GSM, oraz terminal z ATmegą mesko-żenskim bez przeplotu. Na płytce z ATmega mam wyprowadzone piny, które odpowiednio zwierając zworkami mogę robić przeplot między liniami TXD, RXD (wyjścia z MAX232) a pinami 2,3 gniazda DB9 (RS-232) zatem raczej nie jest to problem kabla.

    Gdyby ktoś mógł pomóc będę bardzo wdzięczny :-)

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

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


    void UART_Init()
    {
       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 SendChar( unsigned char data )
    {
       /* Wait for empty transmit buffer */
       while ( !( UCSRA & (1<<UDRE)) )
       ;
       /* Put data into buffer, sends the data */
       UDR = data;
    }


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


    int main()
    {
       UART_Init();
       DDRA |= _BV(PA2);      // PA2 jako wyjście

       // potrzebne do stdio.h:
       FILE uart_str = FDEV_SETUP_STREAM(SendChar, ReceiveChar, _FDEV_SETUP_RW);
       stdout = stdin = &uart_str;

       PORTA &= ~_BV(PA2);   // zapal diode


          printf("at\c", 0x0D);   // wyslij "at"+CR
          
          ReceiveChar();      // tu program sie wiesza

          PORTA |= _BV(PA2);   // zgaś diode
          _delay_ms(1000);
          PORTA &= ~_BV(PA2);   // zapal diode
          _delay_ms(1000);

          PORTA |= _BV(PA2);   // zgaś diode
          _delay_ms(1000);
          PORTA &= ~_BV(PA2);   // zapal diode
          _delay_ms(1000);

          PORTA |= _BV(PA2);   // zgaś diode
          _delay_ms(1000);
          PORTA &= ~_BV(PA2);   // zapal diode
          _delay_ms(1000);


       while(1)
       {   

       }

       return 0;
    }
  • Poziom 20  
    Trochę zmieniłem twój program, nie kompilowałem więc może się coś wkradło ale wydaje mi się że lepiej będzie odbierać znaki w przerwaniu.
    Code:
    #include <avr/io.h> 
    
    #include <util/delay.h>
    #include <stdio.h>
    #include <string.h>
    #include <avr/interrupt.h>

    #define F_CPU 8000000ul                              // 8Mhz
    #define UART_BAUD        19200ul                       // prędkość transmisji bit/s
    #define UART_CONST       (F_CPU/(16ul*UART_BAUD))-1
    #define uchar         unsigned char
    volatile unsigned char bufffull=0;

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


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


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

       {

          unsigned char receive_char;
          receive_char = (UDR);
    //      #if USART_ECHO
          SendChar(receive_char);
    //      #endif
          bufffull=1;
          
       }
       return;
       
    }
    //--------------------------------

    int main()
    {
       UART_Init();
       DDRA |= _BV(PA2);      // PA2 jako wyjście
    sei();

       // potrzebne do stdio.h:
       FILE uart_str = FDEV_SETUP_STREAM(SendChar, ReceiveChar, _FDEV_SETUP_RW);
       stdout = stdin = &uart_str;

       PORTA &= ~_BV(PA2);   // zapal diode


          printf("at\c", 0x0D);   // wyslij "at"+CR
           
    //      ReceiveChar();      // tu program sie wiesza


       while(1)
       {   
    if (bufffull==1)
    {
          PORTA |= _BV(PA2);   // zgaś diode
          _delay_ms(1000);
          PORTA &= ~_BV(PA2);   // zapal diode
          _delay_ms(1000);

          PORTA |= _BV(PA2);   // zgaś diode
          _delay_ms(1000);
          PORTA &= ~_BV(PA2);   // zapal diode
          _delay_ms(1000);

          PORTA |= _BV(PA2);   // zgaś diode
          _delay_ms(1000);
          PORTA &= ~_BV(PA2);   // zapal diode
          _delay_ms(1000);
    bufffull==0;
    }
    else
     printf("at\c", 0x0D);   // wyslij "at"+CR
       }

       return 0;

    }
  • Poziom 11  
    Skompilowałem ten program, (z małymi zmianami - zastępując "ISR (USART_RX_vect) " na "SIGNAL (SIG_UART_RECV)") i nadal nic.
    Komunikacja ATmegi z kompem oraz terminala z kompem działa - sprawdzalem w hyperterminalu i dodatkowo napisalem prosty program w VisualC++ obsługujący RS-232. Do terminala wysyłam komendy z kompa i dostaje prawidłowe odpowiedzi. Do ATmegi wysyłam/odbieram komendy i też wszystko śmiga bez problemu, program wchodzi do przerwania i mruga diodą. Jak podłączam ATmege do terminala to do przerwania nie wchodzi i ATmega "wisi". Nie mam pojęcia co to może być.
    Myślełem, że jest to wina połączenia, więc próbowałem różnych konfiguracji pinów do komunikacji RS-232:
    a) łączyłem RXD, TXD, GND i reszte zostawiałem wiszącą
    b) oprócz RXD, TXD i GND łączyłem
    - 7 z 8 (RTS, CTS)
    - 1 z 4 i 6 (CD, DTR, DSR)
    Ale efekt marny w obu przypadkach.
  • Poziom 11  
    Rozwiązałem problem. Okazało się, że terminal po uruchomieniu znajduje się w stanie Sleep i aby go załączyć należy podać zbocze opadające na linię DTR (Data Terminal Ready). Polecam dokładne czytanie dokumentacji :)
    Co ciekawe stworzenie nowego połączenia w hyperterminalu powodowało załączenie terminala, dzięki czemu jego komunikacja z PC była możliwa.
    Wysyłanie SMSów z układu już działa. Jedyny dodatkowy problem jaki napotkałem to znak zakończenia wprowadzania tekstu wiadomości. Korzystam z książki "Moduły GSM w systemach mikroprocesorowych" Jacka Bogusza i jest w niej napisane, że znakiem tym jest <ctrl+Z> - kod 0x06. W hyperterminalu to rzeczywiście działa wciskając <ctrl+Z> ale jego wartość w kodzie ASCII to nie 0x06 tylko 0x26 :)

    Dziękuję za pomoc i pozdrawiam.