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

[Atmega32][Bascom] SIM900D, komunikacja UART

Elektronik_Kraków 09 Cze 2011 09:59 3916 7
REKLAMA
  • #1 9592340
    Elektronik_Kraków
    Poziom 13  
    Witam
    Napisałem sobie programik, który w założeniu ma sterować wyjściami i informować o zmianie wejść. Na razie wyjścia. Testując go przez UART PC, podpięty przez przejściówkę na FT232 działa całkiem nieźle. Odbiór z UART w przerwaniu
    Niestety po podpięciu do AtMega32, LCD nic nie wyświetla. Moduł jest ustawiony w trybie tekstowym - po wysłaniu z innego numeru, SMS'a na numer modułu, RealTerm pokazuje coś takiego

    +CMT: "+48790123456","","11/06/09,09:44:27+08"Test
    i jeszcze SMS'y odebrane nie są zapisywane w pamięci modułu.

    
    $regfile = "m32def.dat"
    $crystal = 8000000
    $baud = 19200                                               ' predkość transmisji
    $hwstack = 50                                               ' rozmiar stosu sprzętowego
    $swstack = 50                                               ' rozmiar stosu programowego
    $framesize = 32                                             ' rozmiar ramki
    
    Config Debounce = 30
    
    '********************* Konfiguracja wyświetlacza
    Config Lcdbus = 4
    Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7 , E = Portc.2 , Rs = Portc.3
    Config Lcd = 24 * 2
    
    '********************* Konfiguracja UART
    Enable Urxc
    On Urxc Uart_gsm
    
    Enable Interrupts
    
    '********************* Konfiguracja Timer1
    
    Config Timer1 = Pwm , Prescale = 256 , Compare A Pwm = Clear Down , Compare B Pwm = Disconnect
    
    Enable Timer1
    
    '********************* Konfiguracja wejść i wyjść
    Config Portd.7 = Output                                     'LCD1
    Set Portd.7
    Config Portd.6 = Output                                     'LCD2
    Set Portd.6
    Config Portd.5 = Output                                     'LCD3
    Set Portd.5
    Config Porta.0 = Input                                      'Przycisk W1
    Set Porta.0
    
    '********************* Deklaracje zmiennych
    Dim Rx As Byte
    Dim Ciag_rx As String * 65
    Dim Gsm As Byte
    Dim Gsm1 As String * 6
    Dim Numer1 As String * 12
    Dim Tekst1 As String * 15
    
    Dim A1 As String * 5
    Dim Lamp As String * 4
    Dim M As String * 30
    Dim Moc As Word
    
    '********************* Deklaracje podprogramów
    
    Declare Sub Led_1
    
    '********************* Deklaracje Aliasów
    Lcd1 Alias Portd.7
    Lcd2 Alias Portd.6
    Lcd3 Alias Portd.5
    W1 Alias Pina.0
    
    '********************* wartości stałe
    A1 = "+CMT:"
    Lcd1 = 1
    Lcd2 = 0
    'Lcd3 = 0
    
    '***************************** szukanie w stringu
    Cls
    Cursor Off
    Do
    
    Locate 1 , 1
    Lcd Numer1
    
    Locate 2 , 1
    Lcd Tekst1
    
    Locate 1 , 13
    Lcd Lamp
    
    Locate 2 , 13
    Lcd Ciag_rx
    
    
    Gsm = Instr(ciag_rx , A1)                                   ' szukaj w zmiennej Rs ciągu A1
    Gsm1 = Mid(ciag_rx , Gsm , 5)                               ' zwraca fragment tekstu ze zmiennej Rs
    
    '***************************** sterowanie
    
    If Lamp = "led1" Then
      Lcd2 = Moc
     End If
      If Lamp = "led2" Then
      Pwm1a = Moc
    End If
    
    Debounce W1 , 0 , Led_1 , Sub
    Waitms 10
    
    '***************************** odczytuje ze stringu
    
    If Gsm1 = "+CMT:" Then                                      ' jesli zmienna Ramka1 =  "$GPGGA" wtedy
    Numer1 = Mid(ciag_rx , 8 , 12)
    Tekst1 = Mid(ciag_rx , 46 , 15)
    Lamp = Mid(ciag_rx , 46 , 4)
    M = Mid(ciag_rx , 50 , 3)
    Moc = Val(m)
    
    End If
    
    
    
    
    Loop
    End
    
    '********************* Odbór danych z UART
    Uart_gsm:
    Ciag_rx = ""
    
    Do
        Rx = Inkey()
        Select Case Rx
           Case 0
           Case 10
           Case 13 : If Ciag_rx <> "" Then Exit Do              ' jeśli coś odebrane
           Case Else
            Ciag_rx = Ciag_rx + Chr(rx)                         ' utwórz ciąg
        End Select
    
      Loop
    
    
    Return
    
    Led_1:
        Toggle Lcd2
    
    Return
    


    Może ktoś wypowie się co robię nie tak - jakieś uwagi
  • REKLAMA
  • REKLAMA
  • #3 9595314
    Elektronik_Kraków
    Poziom 13  
    Mógłbyś trochę rozwinąć ?
    Niestety nie mogę tego ogarnąć - to już moje drugie podejście, po próbie połączenia UART z PWM, wtedy odpuściłem, bo blokowało mi wyjścia na czas połączenia.

    Przeglądając przykłady na tym forum wyszło coś takiego:
    
    '********************* Konfiguracja UART
    Config Serialin = Buffered , Size = 40 , Bytematch = All
    Enable Interrupts
    '********************* Deklaracje zmiennych
    Dim Rx As Byte
    Dim Ciag_rx As String * 40
    
    Do
    Locate 2 , 1
    Lcd Rx
    
    Locate 1 , 1
    Lcd Ciag_rx
    
    
    If Rs_flaga = 1 Then
       Reset Rs_flaga
       Rx = Inkey()
       Ciag_rx = Ciag_rx + Chr(rx)
      End If
    Loop
    End
    
    '*********************
    Serial0bytereceived:
      Set Rs_flaga
    Return
    

    Chyba, że źle to rozumie i INKEY odbierze całość z bufora.
    No ale Bytematch = All spowoduje ustawienie flagi po każdym znaku i odbiór przez Inkey, jedynie ilość odbieranych znaków jest określona przez
    Buffered , Size = 40 , czyli pojawienie się jakiegokolwiek znaku powoduje odczyt przez INKEY tego co siedzi w buforze - tylko czemu nie pojawia się cała zawartość bufora - tylko po jednym znaku na każde naciśnięcie ENTER. A może przez to, że linia Tx procesora nie jest podpięta do Rx modułu, może AtMega powinna wysyłać znak Entera do modułu.

    Efekt jest taki, że na pierwszych dwóch miejscach LCD wyświetlają się dwa dziwne znaczki. I teraz linie TX z modułu mam podpiętą jednocześnie do Rx AtMega i Rx PC, a linieTX PC do Rx modułu.
    I naciskając Enter w terminalu PC, za każdym razem dodaje mi w pierwszej linii jeden ( prawidłowy ) znak, a w drugiej kod ASCII tego znaku.
    Czyli wygląda to tak:
    odbiór SMS:
    znaczekznaczek+ ( naciskam ENTER )
    znaczekznaczek+C ( naciskam ENTER )
    znaczekznaczek+CM ( naciskam ENTER )
    znaczekznaczek+CMT ( naciskam ENTER )
    znaczekznaczek+CMT: ( naciskam ENTER )

    Te dziwne znaczki, o których pisałem wcześniej to są odpowiedniki ENTER, bo jak uzyskam na LCD cały ciąg z bufora to dalsze naciskanie ENTER powoduje wyświetlanie takich samych znaków.

    Ten ciąg, który przychodzi z modułu GSM to może być trudniejszy do analizy - treść SMS ( w tym przypadku słowo Test ) jest już w nowej linii - tak to przynajmniej prezentuje Terminal:

    +CMT: "+48790123456","","11/06/09,09:44:27+08"
    Test
  • #4 9596141
    Jaca
    Poziom 31  
    Sposób odbioru poprzez procedurę obsługi przerwania od URXC jest lepszy, ale:

    1. Nie możesz przy wejściu do procedury obsługi przerwania kasować zmiennej Ciag_rx ponieważ przerwanie od URXC jest wywoływane dla każdego odebranego znaku;
    2. Nie możesz w procedurze obsługi stosować Do...Loop ponieważ blokujesz odbiór i pętlę główną do czasu odebrania końca linii Chr(13) [Chr(10)]. Co się stanie w przypadku błędu transmisji i nieodebraniu znaku końca linii łatwo przewidzieć: zwiech totalny;
    3. Użyj Rx = UDR zamiast Rx = Inkey();
    4. Po odbiorze znaku Chr(13) ustawiaj własną flagę dla pętli głównej, że dane zostały odczytane (skompletowane w Ciag_rx) ale pamiętaj, że treść SMS'a stanowi drugą linię komunikatu również zakończoną końcem linii Chr(13) [Chr(10)]. Dlatego musisz wychwycić linię informacyjną SMS'a jak i linię jego treści;
    5. W pętli głównej, po każdym odbiorze (flaga ustawiona), analizujesz treść SMS'a, czyścisz zmienną Ciag_rx i zerujesz flagę.
  • REKLAMA
  • #5 9597156
    xury
    Specjalista automatyka domowa
    Jak dla mnie najlepszy sposób na odbiór to zastosowanie Bytematch=13 i odczyt z bufora przez Input, ale nie w przerwaniu tylko w pętli po sprawdzeniu flagi.
    Nie ma się co bać, że program zawiśnie na Input ponieważ odbiór następuje po sprawdzeniu flagi.
  • REKLAMA
  • #6 9598654
    Elektronik_Kraków
    Poziom 13  
    No właśnie przed to, że treść SMS'a jest w drugiej linii bardziej to komplikuje i tak trudne ( przynajmniej dla mnie ) zadanie.

    
    Config Serialin = Buffered , Size = 12 , Bytematch = 13 
    
    If Rs_flaga = 1 Then
       Rx = Inkey()
       Ciag_rx = Ciag_rx + Chr(rx)
       'Reset Rs_flaga        ' WYRZUCAM Resetowanie flagi
      End If
    
    Serial0charmatch:
      Set Rs_flaga
    
    Return
    


    Usunąłem resetowanie flagi Rs_flaga - efekt jest taki, że wyświetla całość z bufora, ale łapie coś do bufora i przed daje dwa znaczki coś jakby chińskie
    ZnaczekZnaczek+CNT:
    dalsza część ciągu jest poprawna - tyle ile miało się zmieścić w buforze.

    Może to co opisuje jest dla kogoś zrozumiałe, ale dla mnie stanowi problem ( spory w porównaniu do Timerów, termometrów, PWM, obsługi przetwornika ADC, czy zapisu na SD ).:cry:
    Może Kolega Xury poratuje konkretnym kodem, ewentualne jakieś punkty mógłbym przekazać. :D
  • #7 9598672
    xury
    Specjalista automatyka domowa
    Prosze bardzo, rzucam moim jakże skomplikowanym kodem :)

    Kod: text
    Zaloguj się, aby zobaczyć kod



    a potem w przerwaniu;

    Kod: text
    Zaloguj się, aby zobaczyć kod





    A gdzieś gdzie chcesz odebrać z bufora w pętli
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Jeśli chcesz odebrać drugą linijke dajesz kolejny Input
    Kod: text
    Zaloguj się, aby zobaczyć kod
    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #8 9607357
    krzysiekk_20
    Poziom 12  
    Witam,

    Napisałeś ,że smsy nie są zapisywane do pamięci telefonu, czy tak?
    Sprawdź co Ci odpowiada modem na komendę AT+CNMI?. Jeśli masz na drugiej pozycji +CNMI: 1,2,0,0,0 cyfrę "2" to znaczy, że smsy trafiają na port UART i nie zapisują się w pamięci. Musisz to zmienić na jedynkę czyli wysłać "AT+CNMI=1,1,0,0,0\r" wtedy dostaniesz tylko wiadomość +CMTI: <wybrana pamięć> <indeks>.że nadeszła nowa wiadomość. Dla zapisywania na sim jest domyślnie <SM> czyli np +CMTI: <SM>,<2>. Wtedy możesz sobie już odczytać inną komendą AT+CMGR.

    Mam taki sam modem i wszystko działa ale programuję w C.

    Wysyłam pdfa do tego modemu tam masz wszystko co potrzebujesz.
    Załączniki:
REKLAMA