Atmel/BASCOM: Empfangenes Zeichen aus UART auslesen?

  • Hallo,


    das Thema ist sicher off-topic, aber vielleicht kann mir jemand von Euch helfen:
    Ich werkele seit dem letzten Jessener Bastelwochenende an einem Programm, um SMS'en über eine RS-232- Schnittstelle in einen Atmega- Prozessor einzulesen.


    Dazu verwende ich das myAVR-Board MK1 LPT, ein Datenkabel und ein Nokia- Handy,
    das die SMSen intern im Textformat (nicht PDU) speichert. Programmiersprache ist BASCOM-AVR


    Im folgenden Programm funktioniert das Senden von Befehlen vom Atmega über die RS232 an das Handy: Ich kann eine Nummer wählen und eine SMS versenden.
    Es gelingt mir aber nicht, Daten über die RS232 zu empfangen, z.B. um sie dann auf dem Display darzustellen.


    Kann mir evtl jemand einen Tip geben?


    Danke & vy 73''- Frank, DL9VF


    Hier der BASCOM- Code:



    $regfile = "m8def.dat"
    $crystal = 3686400
    $baud = 9600


    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
    Config Lcdbus = 4


    Dim S As String * 10, i as Byte


    On URXC OnRxD:
    Enable URXC
    Enable Interrupts


    ' ---------------------------------------------------------------
    ' ---------------- 1. Teil: Rufaufbau. funktioniert -------------
    ' ---------------------------------------------------------------


    'Locate 1 , 1
    'Lcd "Sende ATZ"
    'Print "atz"
    'Waitms 200


    'Locate 1 , 1
    'Lcd "Sende ATDT 0172xxxxxxx"
    'Print "atdt 0172xxxxxxx"
    'Waitms 200


    ' ---------------------------------------------------------------
    ' ---------------- 2. Teil: SMS senden. funktioniert ------------
    ' ---------------------------------------------------------------


    'Locate 1 , 1
    'Lcd "SMS senden... "
    'Waitms 2000


    'Locate 1 , 1
    'Lcd "Textmodus... "
    'Print "at+cmgf=1" ; Chr(13)
    'Waitms 200


    'Locate 1 , 1
    'Lcd "Rufnummer... "
    'Print "at+cmgs=" ; Chr(34) ; "0172xxxxxxx" ; Chr(34) ; Chr(13)
    'Waitms 200


    'Locate 1 , 1
    'Lcd "SMS-Text... "
    'Print "Hier steht der Text der SMS" ; Chr(13)
    'Waitms 200
    'Print Chr(26) ; Chr(13)
    'Wait 10


    ' ---------------------------------------------------------------
    ' ---------------- 3. Teil: SMS empfangen: klappt nicht ---------
    ' ---------------------------------------------------------------


    Cls
    Locate 1 , 1
    Lcd "SMS-Empfang: "
    Waitms 1000


    Locate 1 , 1
    Lcd "Echo ein "
    Print "ate1"
    Waitms 1000


    Locate 1 , 1
    Lcd "Textmodus ein "
    Print "at+cmgf=1"
    Waitms 1000


    Do
    Locate 1 , 1
    Lcd "Handy abfragen:"
    Print "at+cmgl"
    Waitms 5000 'nur alle 5s das Handy abfragen
    Loop


    Onrxd:
    i= udr
    S=S+chr(i)
    Locate 2 , 1
    Lcd S
    Return



    End

    Speaky, BCR, FP, DRK, ... 8)

  • Hallo Frank,


    ich würde mal hier was ändern:


    Onrxd:
    i= udr
    S=S+chr(i)
    Locate 2 , 1
    Lcd S
    Return


    Ich könnte mir vorstellen, das es hier ein Zeitproblem mit dem Display gibt, wenn mehr
    als 1 Zeichen von der URAT kommen und somit das Display aussteigt.


    Bau mal um:


    Do
    Locate 1 , 1
    Lcd "Handy abfragen:"
    Print "at+cmgl"
    Waitms 500
    Locate 2,1
    Lcd S
    Waitms 4500 'nur alle 5s das Handy abfragen
    Loop


    Onrxd:
    i= udr
    S=S+chr(i)
    Return




    Ein versuch ist es wert.....


    73
    Robert, DL5FCE

  • Hallo,


    benutzt du die Software UART?


    ich benutze für die UART die folgende Config:


    Config Com1 = "deine Baudrate" , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
    'Config Serialout = Buffered , Size = 254
    'Config Serialin = Buffered , Size = 254
    Enable Interrupts


    der 8er hat doch ,glaube ich, auch eine HW UART...

  • Meine BASCOM-Versuche liegen zwar etwas länger zurück,aber ich versuchs mal:
    Zunächst würde ich in deine OnRXD Routine nur einen einzigen Befehl, wie zB:
    Print "Zeichen ist da", reinschreiben.
    Dann bist Du erstmal sicher das der Interrupt überhaupt feuert.
    Der Mega8 hat soweit ich weiß nur einen RX-Pin der einen Interrupt feuert. Das müßte
    beim PDIP Gehäuse der Pin2 sein.(Hardware-UART)
    Wenn andere Pins als Software-UART benutzt werden müssen diese per INKEY() Befehl gepollt werden.(Meine ich jedenfalls)


    Das ist ein alter Testcode denich noch auf meinen Rechner hatte.
    Asc(udr) = 35 entspricht '#'
    CHR(1) und CHR(3) entspricht STX und ETX (Start of Text, End of Text)
    Ich hatte damals erst den ganzen String zusammengebaut und ihn erst dann an das LCD geschickt.


    ******************
    Onrxd:
    If Asc(udr) = 35 Then
    Print "Start " ;
    Startread = 1


    End If
    If Startread = 1 Then
    If Asc(udr) <> 3 Then
    Inputstring = Inputstring + Chr(udr)
    Else
    Startread = 0


    Inputstring = Mid(inputstring , 2 , 8 )
    Print Inputstring


    Inputstring = ""
    End If
    End If
    Return
    *********************
    vy 73 de Wolfgang

    4 Mal editiert, zuletzt von dj5zws ()

  • Hallo Frank,
    mir ist folgendes aufgefallen:
    du S als String * 10 definiert. Das verbraucht im Speicher 11 Byte. Dahinter liegt dann der Speicher für die Variable I. Die Variable S wird aber ständig vergrößert. Es findet keine Abfrage auf die Länge von S statt. Das bedeutet ab der Größe 11 läuft die Variable über den vorgesehen Speicherbereich hinaus. Wenn das passiert, wird die Variable I überschrieben. Wächst die Variable weiter, dann bleibt I erhalten bis man an Ende des Speicherbereiches kommt. Jetzt wird auch der String an das Display übergeben. Auch da liegen Speicherbereiche hinter. Was genau passiert, wenn der Speicher an das Ende kommt, weiß ich nicht so genau. Wenn es dann wieder bei Null anfängt, werden die Interrupt-Vektoren überschrieben. Einen Runtime-Error oder Overflow gibt es nicht.
    Dann habe ich sehen, dass auf dem Port D auch die Interrupt-Anschlüsse für die Timer und so sind. Vielleicht kannst du das Display besser auf Port C legen.
    Edit Ergänzung
    So ich habe dein Programm mal im Simulator laufen lassen. Es macht Probleme mit Port.D, wenn ich es auf Port.C umstelle klappt es. Du kannst da gut sehen, wie der Speicherbereich überschrieben wird. Ich passe das Programm mal ein wenig an und poste es nachher.

    vy73 Jürgen

    Einmal editiert, zuletzt von DJ4JZ ()

  • Hi Frank,
    hier mal ein Beispiel der bei mir im Simulator läuft.
    Für den realen Betrieb musst du noch ein wenig Anpassungsarbeit vornehmen.



    -----------snipp----------------------------------------------------------
    $regfile = "m8def.dat"
    $crystal = 8000000
    $baud = 9600


    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7 , E = Portc.3 , Rs = Portc.2
    Config Lcdbus = 4


    Dim S1(17) As Byte , I As Byte , Flag As Byte


    On Urxc Onrxd:
    Enable Urxc
    Enable Interrupts


    Cls
    Locate 1 , 1
    ' Die LCD-Ausgabe auf 16 Zeichen auffüllen
    ' kann hier nicht so gut sehen
    ' Die Waits für realen Betrieb anpassen
    ' in der Simulation läuft eh alles langsamer
    '
    Lcd "SMS-Empfang: "
    Waitms 10


    Locate 1 , 1
    Lcd "Echo ein "
    Print "ate1"
    Waitms 10


    Locate 1 , 1
    Lcd "Textmodus ein "
    Print "at+cmgf=1"
    Waitms 10


    ' Die Variable S1 mit einem definierten Wert füllen
    For I = 1 To 17
    S1(i) = " "
    Next I


    ' Anzeigen nur wenn ein Zeichen kommt
    Do
    ' Die Abfrage auf einen Timer legen
    ' sonst können die Zeichen aus dem Onrxd nicht angezeigt werden
    ' die kommen vom Handy mit der eingestellen Baudgeschwindigkeit
    ' aber hier gibt es verschiedenste Realisierungsmöglichkeiten
    Locate 1 , 1
    Lcd "Handy abfragen: "
    ' das blende ich mal für die Simulation aus
    ' Print "at+cmgl"
    ' Waitms 10 'nur alle 5s das Handy abfragen


    ' Anzeigen nur wenn ein Zeichen kommt


    If Flag = 1 Then
    Locate 2 , I 'und Ausgabe
    For I = 1 To 16 '2 Zeile
    S1(i) = S1(i + 1) 'um 1 Zeichen nach links schieben
    Locate 2 , I 'und Ausgabe
    Lcd Chr(s1(i)) 'auf LCD-Display
    Next I
    Flag = 0
    End If
    Loop



    Onrxd:
    S1(17) = Udr
    Flag = 1
    Return
    End
    -------------------------snipp-------------------------------------------------------


    Wenn was nicht klappt, schreibe mir eine PN

    vy73 Jürgen

  • Hallo,
    erstmal vielen Dank für Eure Antworten.


    DL5FCE:
    Robert, ich fürchte auch, daß das LCD-Display zu langsam für die Schleife ist.
    Wenn ich die Doku richtig verstanden habe, wird die Marke OnRxd nach jedem empfangenen Zeichen angesprungen.
    Probleme mit dem Anzeigen mehrerer Zeichen hätte ich nicht erwartet.
    Habe Deinen Code mal gebrannt, hat bei mir aber auch nicht funktioniert.


    DJ1YR:
    René, ich benutze die Hardware- UART.
    Mit Config Com1 = "deine Baudrate" , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0 wird m.E. die Software- UART initialisiert ?


    dj5zws:
    Wolfgang, ich habe Deinen Code noch nicht ganz verstanden: Was war bei Dir 'auf der anderen Seite der UART'? Fingen bei Dir die empfangenen Daten immer mit einem # an ?
    Ich habe Deinen Code auf meine Verhältnisse abgewandelt:
    Ich sende nur ein "AT" und warte auf die Zeichen "O" und "K".
    Funktioniert noch nicht, aber ich probiere das weiter.
    Muß ich hinter das 'print "AT"' evtl noch ein Steuerzeichen setzen, damit das Ende der Zeichenkette erkannt wird ?


    DJ4JZ
    Jürgen, danke für die Erklärungen zum Speicherbereich. Mir war gar nicht bewußt, wie wichtig beim Dimensionieren der Variablen die Reihenfolge ist.
    Ich bin *sehr* gespannt auf das Ergebnis Deines Versuchs.
    Hoffentlich kann ich das Programm auf meinem myAVR-Board von Port.D auf Port.C umstellen. Ich dachte eigentlich, das Display ist fest verdrahtet.
    Ich versuche jetzt mal, das Display auf Port C zu legen.


    vy 73''- Frank, DL9VF

    Speaky, BCR, FP, DRK, ... 8)

  • Zitat

    Original von DL9VF


    Hoffentlich kann ich das Programm auf meinem myAVR-Board von Port.D auf Port.C umstellen. Ich dachte eigentlich, das Display ist fest verdrahtet.
    Ich versuche jetzt mal, das Display auf Port C zu legen.


    vy 73''- Frank, DL9VF


    Frank,
    wenn es das board au der Lausitz ist, das ich auch habe, dann musst du das als erstes machen. Bei dem Lausitzboard blockiert das LCD die Interrupts.

    73/2 de Peter, DL2FI
    Proud member of Second Class Operators Club SOC and Flying Pig Zapper #OOO (Certificated Kit Destroyer)


  • nein das ist die Config für die HW UART, die UART und Steuer-Pins vom Display an einem Port kann Probleme geben.


    wenn du hinter den Printbefehl, also Print x schreibst wird CR hinten angehangen, also "ENTER", wenn du dahinter ein ";" setzt wird dieses "ENTER" unterdrückt.


    ich benutze HTerm ( http://www.der-hammer.info/terminal/ ) für experimente mit der UART

    2 Mal editiert, zuletzt von DJ1YR ()

  • Hallo Peter,


    ja, es ist das Board aus der Lausitz. Jetzt mit einer RS232 und den richtigen Pegeln,
    das war ja mein Fehler beim letzten Mal in Jessern.
    Wenn ich es richtig sehe, ist das Display aber über den Erweiterungsstecker
    fest mit PortD verdrahtet.


    Bleibt wohl nur, die LCD-Steuerleitungen zwischen Board und LCD- Platine frei verdrahtet von PortC (am Board) auf PortD (an der LCD-Platine) umzuschwenken ...


    vy 73''- Frank, DL9VF

    Speaky, BCR, FP, DRK, ... 8)

  • Hallo Frank
    Deine Vermutung ist richtig. Das Telegramm das ich an den Atmel schickte sah so in der Art aus: #<STX>1234567<ETX> und kam aus einer PC-Software.


    Falls Peter nicht schon den Grund für dein Problem genannt hat, würde ich an deiner Stelle erst mal mit einem PC und einem Terminalporgramm(Hyperterminal ist auf jedem Windowsrechner dabei) irgendein Zeichen über die RS232 an den Atmel schicken und gucken ob du das aufs Display bekommst.


    Dann bist du zumindestens sicher das die Atmel-Seite prinzipiell funktioniert.
    Dann würde ich mit dem Terminalprogramm den AT Befehl an das Handy schicken. Dann siehstDu schon mal ob was zurück kommt und wie die Antwort aussiehst.


    Falls nämlich das Problem auf beiden Seiten liegen sollte (zB Atmel liest nicht ein und Handy antwortet nicht weil AT Befehl falsch war) suchst du dich tot.:-)


    vy 73 de Wolfgang

    Einmal editiert, zuletzt von dj5zws ()

  • Hi Frank
    hier eine Version die auf die Interrupts verzichtet. Bei sollte das LCD Klappen.
    Im Simulator haut das auf jeden Fall hin.


    -------------snipp-----------------



    $regfile = "m8def.dat"
    $crystal = 3686400
    $baud = 9600


    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2


    Config Lcdbus = 4


    Dim S1(17) As Byte , I As Byte , Flag As Byte , S As Byte
    Dim Nm As String * 1
    Dim S_eingabe(160) As Byte
    Dim Zeile(17) As Byte


    S = 1


    Cls
    Locate 1 , 1
    ' Die LCD-Ausgabe auf 16 Zeichen auffüllen
    ' Die Waits für realen Betrieb anpassen
    ' in der Simulation läuft eh alles langsamer
    '
    Lcd "SMS-Empfang: "
    Waitms 10


    Locate 1 , 1
    Lcd "Echo ein "
    Print "ate1"
    Waitms 10


    Locate 1 , 1
    Lcd "Textmodus ein "
    Print "at+cmgf=1"
    Waitms 10


    ' Die Variable S1 mit einem definierten Wert füllen
    For I = 1 To 17
    S1(i) = " "
    Next I


    Locate 1 , 1
    Lcd "Handy abfragen: "


    ' Anzeigen nur wenn ein Zeichen kommt
    Do
    If Ischarwaiting() = 1 Then
    Nm = Waitkey() 'Zeichen aus Puffer holen
    S1(17) = Nm 'Zeichen in Eingabe String übertragen
    Flag = 1
    End If


    ' Anzeigen nur wenn ein Zeichen kommt
    Waitms 10
    If Flag = 1 Then
    Locate 2 , I 'und Ausgabe
    For I = 1 To 16 '2 Zeile
    S1(i) = S1(i + 1) 'um 1 Zeichen nach links schieben
    Locate 2 , I 'und Ausgabe
    Lcd Chr(s1(i)) 'auf LCD-Display
    Next I
    Flag = 0
    End If
    Loop


    End
    ---------snipp--------------------


    Wenn du das selbst im Simulator erprobst, dann darfst du die Zeichen nur sehr langsam eingeben.
    Um aber jetzt ein lauffähiges Programm zuerstellen brauchen wir noch die Länge der SMSen die reinkommen. In eine SMS passen ja 160 Zeichen. Um die dann auf den Display anzuzeigen muss man noch eine Routine schreiben, die den Text der reinkommt, qusai darüber skrollt.

    vy73 Jürgen