- fchao-Sinus-Wechselrichter AliExpress         
Ergebnis 1 bis 10 von 33

Thema: Optimieren von UART-Komunikation, bitte um Meinungen

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    08.07.2008
    Beiträge
    6
    Oh, das weiss ich nicht, da ich Bascom nicht benutze. Ich arbeite mit GCC. GCC ist auch nicht schwerer als Basic. Ich habe früher mit verschiedenen Basic-dialekten gearbeitet und finde C auf Dauer besser, wenn auch an manchen Stellen gewöhnungsbedürftig (wie Kurzschreibwesen i++ --> i=i+1, wobei das noch harmlos ist.) . Aber es müsste im Forum etwas ähnliches geben. Der Vorteil der Fleury Lib ist, daß die von vielen Usern getestet ist und funktioniert.
    Ich kann mich erinnern, dass es früher bei Turbo-Pascal die Möglichkeit gab, C- und / oder Assembler Routinen in den Code einzubinden möglicherweise auch in Bascom?

    Gruss Hambone

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    53
    Beiträge
    765
    Inline ASM geht. C-Code lässt sich nicht so einfach einbinden. Ich habe unter Bascom mit dem UART keinerlei Probleme. Das hier beschriebene Problem kann überall liegen, da der Code nicht komplett da steht. Auch möglich, dass der AVR ins Nirvana läuft und dann neustartet und daher die Ausgabe passt.

    Ich nutze wie gesagt die IsCharWaiting() Methode ohne Interrupts. Evlt. noch buffered Empfang einstellen. Dann geht nichts verloren. Mein X300T Programm lässt nach dem Starten erstmal eine Meldung mehrere Sekunden übers Display laufen bevor es in die Mainloop geht und trotzdem kann ich einfach schon Daten losschicken. Da geht nichts verloren.
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  3. #3
    RN-Premium User Fleißiges Mitglied
    Registriert seit
    19.05.2012
    Ort
    Sigmaringen
    Beiträge
    169
    So... der komplette code wäre dann:
    Es ist ohne diese Verzögerung in serial0charmatch.

    Das Funkmodul ist an sich schon in betrieb und ich kann dann wahlweise über Kabel oder Funk die Verbindung testen.

    Der Hinweis auf die Register ist von mir noch nicht geprüft...
    Da muss ich mich erst noch bissl einarbeiten... hab mich mit den Registern noch nicht wirklich beschäftigt.

    Was ich auch etwas seltsam finde...
    Wenn ich vom pc aus den port öffne und sende... ok. kommt an wie gedacht"... wenn ich den port aber trenne und
    ein zweites mal öffne sind irgendwelche "zeichen" im buffer, die mir das ganze array zerschiessen.
    wird beim trennen des ports auf der tx/rx-leitung noch was gesendet ??


    Code:
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    'Programmname:    UART-Schnittstelle.bas
    'Letzte Änderung: 03.03.2013
    'Funktion:        Empfang von gesamt 18Byte,
    '                 ausgabe als echo über seriell und lcd zur kontrolle
    'Mikrocontroller: Mega8
    '
    'Input:
    'Output:
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    'Den Atmega mit den passenden Daten füttern.
    '-------------------------------------------------------------------------------
    $regfile = "m8def.dat"                                      'eingesetzter Mikrocontroller
    $crystal = 8000000                                          'eingestellte Taktfrequenz (8MHz)
    $hwstack = 100                                              'Standardwert
    $swstack = 100                                              'Standardwert
    $framesize = 100                                            'Standardwert
    $baud = 9600
    
    '-------------------------------------------------------------------------------
    'Ports/Pins/Configs
    '-------------------------------------------------------------------------------
    
    '-------------------------------------------------------------------------------
    'Timer/OCR/PWM/ISR usw. setzen
    '-------------------------------------------------------------------------------
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
    Config Lcd = 16 * 2
    Config Serialin = Buffered , Size = 18 , Bytematch = 123    '123={
    Enable Interrupts
    
    '-------------------------------------------------------------------------------
    'Variablen
    '-------------------------------------------------------------------------------
    Dim Temp_byte As Byte
    Dim Datenblock(16) As Byte
    Dim Indexposition As Byte
    Dim Startzeichen As String * 1
    Startzeichen = "{"
    Dim Endzeichen As String * 1
    Endzeichen = "}"
    Dim Datenblock_komplett As Bit
    Dim Datenblock_laenge As Byte
    Datenblock_laenge = 16
    Dim Lcd_position As Byte
    Dim Datenblock_string As String * 16
    
    '-------------------------------------------------------------------------------
    'Hauptprogramm
    '-------------------------------------------------------------------------------
    Cls
    Waitms 100
    
    Do
       If Datenblock_komplett = 1 Then
       'UART-Datenblock in String füllen
          For Indexposition = 1 To Datenblock_laenge Step 1
             Insertchar Datenblock_string , Indexposition , Datenblock(indexposition)
          Next
       Disable Interrupts
       'Ausgabe/Abarbeiten des UART-Datenblock
          Cls
          Waitms 100
          For Indexposition = 1 To 3 Step 1
             Lcd_position = Indexposition
             Locate 1 , Lcd_position
             Lcd Chr(datenblock(indexposition))
          Next
          For Indexposition = 3 To Datenblock_laenge Step 1
             Lcd_position = Indexposition - 8
             Locate 2 , Lcd_position
             Lcd Chr(datenblock(indexposition))
          Next
       'Echo zurücksenden zur Kontrolle
          Print Datenblock_string
          Datenblock_string = ""
          Datenblock_komplett = 0
       Enable Interrupts
       End If
    Loop
    End
    
    '-------------------------------------------------------------------------------
    'Interrupt
    '-------------------------------------------------------------------------------
    
    Serial0charmatch:
    
    While Ischarwaiting() = 1
       Temp_byte = Inkey()
       Waitus 2000
    
       Locate 2 , 13
       Lcd Chr(temp_byte)
       Wait 1
    
       If Temp_byte = Asc(startzeichen) Then
          Indexposition = 0
          Datenblock_komplett = 0
       Elseif Temp_byte = Asc(endzeichen) Then
          Datenblock_komplett = 1
       Else
          Indexposition = Indexposition + 1
          Datenblock(indexposition) = Temp_byte
       End If
       If Indexposition = Datenblock_laenge Then
          Datenblock_komplett = 1
          Clear Serialin
       End If
    Wend
    
    If Indexposition < Datenblock_laenge Then
       Do
          Indexposition = Indexposition + 1
          Datenblock(indexposition) = 22
       Loop Until Indexposition = Datenblock_laenge
       Datenblock_komplett = 1
       Clear Serialin
    End If
    
    Return
    Das bytematch ist 123 (also wie das Startzeichen { )

    Nachtrag: ... bei dem jetzigen code... wenn ich die verzögerung rausnehm...

    Ich sende {xyz1234567890123}
    es kommt die ersten 2 vorgänge nur "leerstellen" ins array... ab dem dritten dritten mal ist dann
    "y} " im Array
    Geändert von JoeM1978 (04.03.2013 um 18:05 Uhr)
    JAAAA... Microchips kann man essen... aber der Geschmack ist furchtbar.

  4. #4
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Eine Wartezeit wie ein Waitus 2000 sollte nicht im Interrupts sein. Auch die Ausgabe auf das LCD ist ggf. ein Problem, auch wenn das wohl eher eine HIlfe zur Fehlersuche ist. So wie es jetzt gemacht ist, wird die Wartezeit gebraucht damit in der Zeit die zur Verarbeitung von 1 byte schon das Nächste byte ankommt. Entsprechend sollte die Wartezeit zusammen mit der Laufzeit auf die Bautrate abgestimmt sein. Dabei kann der recht langsame LCD Befehl ggf. die extra Wartezeit auch ganz ersetzen, was vor allem Zeigt das man LCD(...) in der ISR vermeiden sollte.

    Die Interrupt Routine sollte so schnell sein, das immer nur 1 Byte verarbeitet wird - die while Schleife ist also eigentlich überflüssig. Damit muss natürlich dann auch die Abfrage auf das vorzeitige Ende eines Datenblocks anders gelöst werden, z.B. in die IF Abfrage mit ASC(endzeichen).

  5. #5
    RN-Premium User Fleißiges Mitglied
    Registriert seit
    19.05.2012
    Ort
    Sigmaringen
    Beiträge
    169
    Was an sich meine erste Vermutung dann bestätigen würde...
    nämlich das die abarbeitung zu schnell abläuft und das nächste zeichen noch garnicht im Buff vorliegt.

    Wenn das dann so stimmt weiss ich ja, wo ich ansetzen muss...
    JAAAA... Microchips kann man essen... aber der Geschmack ist furchtbar.

  6. #6
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    53
    Beiträge
    765
    Da ist auch ein Wait 1 in der isr...

    So würde ich es wohl probieren: (ungetestet, da nur Laptop hier und keine Hardware)
    Code:
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    'Programmname:    UART-Schnittstelle.bas
    'Letzte Änderung: 03.03.2013
    'Funktion:        Empfang von gesamt 18Byte,
    '                 ausgabe als echo über seriell und lcd zur kontrolle
    'Mikrocontroller: Mega8
    '
    'Input:
    'Output:
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    'Den Atmega mit den passenden Daten füttern.
    '-------------------------------------------------------------------------------
    $regfile = "m8def.dat"                                      'eingesetzter Mikrocontroller
    $crystal = 8000000                                          'eingestellte Taktfrequenz (8MHz)
    $hwstack = 40                                               'Standardwert
    $swstack = 40                                               'Standardwert
    $framesize = 20                                             'Standardwert
    $baud = 9600
    
    
    '-------------------------------------------------------------------------------
    'Ports/Pins/Configs
    '-------------------------------------------------------------------------------
    
    '-------------------------------------------------------------------------------
    'Timer/OCR/PWM/ISR usw. setzen
    '-------------------------------------------------------------------------------
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
    Config Lcd = 16 * 2
    Config Serialin = Buffered , Size = 18
    Enable Interrupts
    
    '-------------------------------------------------------------------------------
    'Variablen
    '-------------------------------------------------------------------------------
    Dim Temp_byte As Byte
    Dim Datenblock(16) As Byte
    Dim Indexposition As Byte
    Const Startzeichen = 123
    Const Endzeichen = 125
    Const Datenblock_laenge = 16
    Dim Datenblock_komplett As Bit
    Dim Lcd_position As Byte
    Dim Datenblock_string As String * 16
    Dim Datenblock_byte(16) As Byte At Datenblock_string Overlay
    
    '-------------------------------------------------------------------------------
    'Hauptprogramm
    '-------------------------------------------------------------------------------
    Cls
    Waitms 100
    
    Do
       If Ischarwaiting() = 1 Then
          Gosub Empfangen
       End If
       If Datenblock_komplett = 1 Then
          Reset Datenblock_komplett
          Gosub Anzeige
       End If
    Loop
    End
    
    Anzeige:
          Cls
          Waitms 100
          For Indexposition = 1 To 3 Step 1
             Lcd_position = Indexposition
             Locate 1 , Lcd_position
             Lcd Chr(datenblock(indexposition))
          Next
          For Indexposition = 3 To Datenblock_laenge Step 1
             Lcd_position = Indexposition - 8
             Locate 2 , Lcd_position
             Lcd Chr(datenblock(indexposition))
          Next
       'Echo zurücksenden zur Kontrolle
          Print Datenblock_string
    
    
    Return
    
    
    Empfangen:
       Temp_byte = Inkey()
       If Temp_byte > 12 Then                                   'unter 13 sind nur Sonderzeichen
          If Temp_byte = Startzeichen Then
             Indexposition = 0
          Elseif Temp_byte = Endzeichen Then
             Gosub Auswerten
          Else
             Incr Indexposition
             Datenblock(indexposition) = Temp_byte
          End If
          If Indexposition = Datenblock_laenge Then
             Gosub Auswerten
          End If
       End If
    
    Return
    
    Auswerten:
       Dim Dummy As Byte
       Datenblock_string = String(datenblock_laenge , 0)
       Dummy = Memcopy(datenblock(1) , Datenblock_byte(1) , Indexposition)
       Datenblock(1) = String(datenblock_laenge , 22)           'Wozu?
       Indexposition = 0
       Set Datenblock_komplett
    Return
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  7. #7
    RN-Premium User Fleißiges Mitglied
    Registriert seit
    19.05.2012
    Ort
    Sigmaringen
    Beiträge
    169
    Als erstes danke ich euch mal für eure Mühe...
    und natürlich auch für den vorgelegten Code.

    das...
    Datenblock(1) = String(datenblock_laenge , 22) 'Wozu?
    War dazu gedacht, das ich auch kurze Messages senden kann und der rest mit "lückenfüller" neutralisiert wird.

    Hab den Code von dir versucht... bis auf die Ausgabe auf lcd ist das anscheinend funktionierend.
    Wobei das LCD eh nur für Testzwecke dranhängt bis die Komunikation fehlerlos steht.
    Das LCD ist aber schnell angepasst.

    Was mir gedanken macht daran... sollte aus irgendeinem Grund 2 oder mehr Datenblöcke kurz nacheinander gesendet werden
    und das hauptprogramm hatte noch keine zeit den Buffer auszulesen...
    Wird dann alles, was zuviel gesendet wird einfach verworfen ?

    Dann sollte ich mir sozusagen ein "manuelles handshake" einbauen... das die pc-software weiss,
    wann der client wieder empfangsbereit ist.

    Das war der ursprüngliche grund, weshalb ich den Buffer "so schnell wie möglich" auslesen wollte mit der ISR.
    JAAAA... Microchips kann man essen... aber der Geschmack ist furchtbar.

  8. #8
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    53
    Beiträge
    765
    Zitat Zitat von JoeM1978 Beitrag anzeigen
    Was mir gedanken macht daran... sollte aus irgendeinem Grund 2 oder mehr Datenblöcke kurz nacheinander gesendet werden
    und das hauptprogramm hatte noch keine zeit den Buffer auszulesen...
    Wird dann alles, was zuviel gesendet wird einfach verworfen ?
    Bei 9600 Baud und 8 MHz langweilt der sich zwischendurch. Da geht normal nichts verloren. Wenn du aus der Hauptschleife Subs aufrufst, welche lange Pausen beinhalten, oder die Pausen gar in die Hauptschleife legst, dann besteht die Gefahr, dass der Buffer überläuft. Ich teste die Geschwindigleit meiner Programme gern mit einem blinkenden Herz auf dem LCD. Alle 1000 Durchläufe wird das Herz dargestellt oder ausgeblendet. Selbst meine umfangreichen Projekte kommen da gefühlt auf 1000 Durchläufe die Sekunde. Handshaking nutze ich selbstgemacht. Wenn der Raspberry was zum AVR schickt, dann wird eine Antwort passend zum gesendeten erwartet. Kommt diese, aus welchen Gründen auch immer, nicht, dann wird das zuletzt gesendete wiederholt. Da beißt sich auch nichts. Mein Protokoll berücksichtigt auch bereits gestartete Übertragungen, z.B. wenn die Fernbedienung oder eine Taste am Gerät "was zu melden hat".

    Ich sende dafür nicht aus jeder Sub direkt per print, sondern schreibe die Daten in einen Sendepuffer. Jeder Durchgang der Hauptschleife ruft eine Sub auf, welche prüft, ob es was zu senden gibt und sendet dann chronologisch nach FIFO art. Der Raspberry macht es ähnlich. Da nutze ich zum Senden ein eigenes C-Programm, welches prüft, ob es evtl. schon in einer anderen Instanz läuft und falls ja, wird eine Pause eingelegt. Meine Tests mit 100 "gleichzeitigen" Aufrufen liefen fehlerfrei. Soviel kommen in der Realität aber gar nicht vor.
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Zitat Zitat von JoeM1978 Beitrag anzeigen
    Was an sich meine erste Vermutung dann bestätigen würde...
    nämlich das die abarbeitung zu schnell abläuft und das nächste zeichen noch garnicht im Buff vorliegt.
    Wie schon gesagt, das ganze Konzept ist kompletter Käse, Du hast das Prinzip Interrupt-gesteuerter Verarbeitung überhaupt nicht verstanden.
    Der BYTEMATCH ist normalerweise dafür vorgesehen, das Ende einer Übertragung zu erkennen. Es ist nicht dafür gedacht den Anfang zu erkennen und dann solange in der ISR rumzurödeln und alles andere zu blockieren, bis man die Zeichenkette empfangen hat. Wofür soll dann der gepufferte Empfang überhaupt noch gut sein?
    Das hier ist jetzt in ein paar Minuten entstanden und sollte eigentlich funktionieren. "Eigentlich", weil nicht auf Hardware getestet, aber vielleicht siehst Du die Idee.
    Code:
    $regfile = "m8def.dat"
    $crystal = 8000000
    $hwstack = 100
    $swstack = 100
    $framesize = 100
    $baud = 9600
    
    Const block_wait = 0
    Const block_receive = 1
    Const block_length = 16
    Const False = 0
    Const True = 1
    
    Dim rx_state As Byte
    Dim buff(block_length) As Byte
    Dim data_block(block_length) As Byte
    Dim db_index As Byte
    Dim rcvd_char As Byte
    Dim rcv_complete As Bit
    Dim tmp As Byte
    
    rx_state = block_wait
    db_index = 0
    rcv_complete = False
    
    On URXC UART_Get_Char
    Enable URXC
    Enable Interrupts
    
    Do
      If rcv_complete = True Then
        Printbin data_block(1)
          rcv_complete = False
      End If
    Loop
    
    UART_Get_Char:
      rcvd_char = UDR
        Select Case rx_state
          Case block_wait:
            If rcvd_char = "{" Then rx_state = block_receive
          Case block_receive:
            If rcvd_char <> "}" Then
              If db_index < block_length Then
                Incr db_index
                  buff(db_index) = rcvd_char
              Else
                db_index = 0
                  rx_state = block_wait
              End If
            Else
              If db_index > 0 Then
                tmp = memcopy(buff(1) , data_block(1) , db_index)
                  rcv_complete = True
              End If
                db_index = 0
                  rx_state = block_wait
            End If
        End Select
    Return

Ähnliche Themen

  1. Daten von Software UART nach Hardware UART weiterleiten
    Von kusli im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 8
    Letzter Beitrag: 06.10.2008, 21:24
  2. Anfängerprojekt - Bitte um Hilfe und Meinungen
    Von Al_Andaluz im Forum Vorstellung+Bilder+Ideen zu geplanten eigenen Projekten/Bots
    Antworten: 22
    Letzter Beitrag: 20.06.2007, 10:27
  3. frequenzverhalten von mosfets optimieren...
    Von Bibiman im Forum Elektronik
    Antworten: 3
    Letzter Beitrag: 18.03.2007, 10:37
  4. Erster UART Versuch... schaut mal bitte kurz drüber...
    Von popi im Forum C - Programmierung (GCC u.a.)
    Antworten: 19
    Letzter Beitrag: 25.07.2006, 20:16
  5. BL-521 - Bluetooth RS232 Converter (Eure Meinungen Bitte !!)
    Von PabloEscoba im Forum Allgemeines zum Thema Roboter / Modellbau
    Antworten: 1
    Letzter Beitrag: 11.05.2006, 16:56

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress