PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Datenempfang über UART



extremesports
16.12.2011, 15:29
So, jetzt hab ich gleich noch mal ein Thema:

Code lässt sich Fehlerfrei compilieren. Die Durchlauf-LED blinkt auch gelegentlich, wie sie soll.
Probleme bereitet mir das Empfangen über UART und das Auswerten der Daten.
Des öfteren hängt sich das Ganze auch auf und die LED leuchtet dauerhaft.

Vielleicht kann jemand den Fehler entdecken... Ich bin für den Moment am Ende mit meinen Ideen.

Vielen Dank!

Kampi
16.12.2011, 15:37
Poste mal bitte deinen Code.

extremesports
16.12.2011, 22:43
Oh mann - wie ich doch neben mir gestanden hab - man sollte doch nie in Eile was posten.

Danke für den Hinweis Kampi!
Hier wird der Code nachgereicht:


' ################################################## ###########
' #### USB-IO-plus
' #### by Jonathan Lorenz $PROG &H00,&H00,&H00,&H00' generated. Take care that the chip supports all fuse bytes.$PROG &H00,&H00,&H00,&H00' generated. Take care that the chip supports all fuse bytes.$PROG &H00,&H00,&H00,&H00' generated. Take care that the chip supports all fuse bytes.$PROG &H00,&H00,&H00,&H00' generated. Take care that the chip supports all fuse bytes.
' #### USBtoUART -> AVR
' #### Interface: GPIO, ADC, PWM, I2C, etc. (->Datasheet AVR)
' ################################################## ###########
' #### empfange Anweisungen vom PC über USBtoUART
' #### setzen oder lesen der Pins
' #### Steuerung der Schnittstellen
' ################################################## ###########
' #### getting instructions from PC over USBtoUART
' #### writing or reading the pins
' #### driving the Interfaces
' ################################################## ###########
' #### Bascom-AVR IDE [1.11.9.8]
' ################################################## ###########

$regfile = "M8def.dat" '.dat-file ATmega8'
$crystal = 8000000 'Taktfrequenz 8MHz'
$hwstack = 350 'Größe Hardwarestack'
$swstack = 350 'Größe Softwarestack'
$framesize = 200 'Größe Frame'

$baud = 19200 'Baudrate UART



'Tccr1a = &B10100010 'initialisieren der PWM-Frequenz 30,52 Hz bei 9 Bit
'Tccr1b = &B10000010 'initialisieren der PWM-Frequenz 30,52 Hz bei 9 Bit


Declare Sub Empfang()
Declare Sub Verarbeitung()
Declare Sub Setzen()


'Config Adc = Single , Prescaler = Auto , Reference = Avcc
'Start Adc


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


Config Portd.6 = Output
Config Portd.7 = Output
Config Portb.0 = Output


Dim I as Byte ' Splitting der Hauptschleife
Dim Empfang_string As String * 10
Dim Port As String * 10
Dim Wert As String * 10
Dim B_port As Byte
Dim B_wert As Byte

Dim Zaehler As Byte


Portd.6 = 0
Portd.7 = 0
Portb.0 = 0
Zaehler = 0


'On Urxc Onrxd 'Interrupt-Routine setzen
'Enable Urxc 'Interrupt URXC einschalten
'Enable Interrupts 'Interrupts global zulassen


Cls
Cursor On Blink
Lcd "USB-IO_plus"
Waitms 150
Locate 2 , 1
Lcd "."
Waitms 150
Locate 2 , 2
Lcd "."
Waitms 150
Locate 2 , 3
Lcd "."
Waitms 150
Locate 2 , 4
Lcd "initialisiert"


' ################################################## ###########
' #### Hauptprogramm
' ################################################## ###########

Do
Toggle Portb.0 'Blinkende LED zur Kontrolle des Programmdurchlaufes
For I = 0 To 200
Waitms 1
Next I

Empfang

Verarbeitung

Setzen
Loop

End 'end program


' ################################################## ###########
' #### UART Empfang
' ################################################## ###########

Sub Empfang()
If Ischarwaiting() = 1 Then
Input Empfang_string
If Zaehler < 3 Then
Incr Zaehler
Else
Zaehler = 0
End If
Else
!nop
End If
End Sub

' ################################################## ###########
' #### Datenverarbeitung
' ################################################## ###########

Sub Verarbeitung()
Port = Left(empfang_string , 2) 'Byte 1 und 2 extrahieren
Wert = Mid(empfang_string , 3 , 2) 'Byte 3 und 4 extrahieren
B_port = Val(port) 'String zu Wert konvertieren
B_wert = Val(wert) 'String zu Wert konvertieren
End Sub

' ################################################## ###########
' #### Ausgänge setzen
' ################################################## ###########

Sub Setzen()
Select Case B_port 'zu setzenden Pin auswählen
Case 50 : If B_wert = 49 Then '50=2 | 49=1
Portd.6 = 1
Elseif B_wert = 50 Then ' | 50=2
Portd.6 = 0
End If
Case 51 : If B_wert = 49 Then '51=3 | 49=1
Portd.7 = 1
Elseif B_wert = 50 Then ' | 50=2
Portd.7 = 0
End If
Case Else : !nop
End Select
End Sub


' ################################################## ###########
' #### UART Interrupt
' ################################################## ###########

'Onrxd:
' I = Udr 'Byte aus der UART auslesen
'Return

' ################################################## ###########
' #### Stand 16|12|2011
' ################################################## ###########

Kampi
17.12.2011, 09:48
Was soll den das Programm machen?
Hast du eine kurze Erklärung für das Programm? Das würde die Fehlersuche erleichtern :)

MagicWSmoke
17.12.2011, 09:51
In den 200ms Delay in der Hauptschleife können ca. 380 Bytes eintrudeln, ohne dass reagiert werden kann, wie soll das überhaupt funktionieren ? Orientier' Dich doch an einem funktionierenden Beispiel wie es im Bascom-Samplesordner zu finden ist.

extremesports
17.12.2011, 09:55
Ja klar... hier die Beschreibung:

Die Hardware schaut folgendermaßen aus (noch auf dem Steckbrett) ATmega8: am UART ein UART-to-USB Converter; An den Pins D.6, D.7 und B.0 sind LEDs angeschlossen. Die an Pin B.0 blinkt bei jedem Durchlauf des Hauptprogramms. Die anderen beiden sollen an und ausgeschalten werden können.
Das wars eigentlich schon. Später soll noch folgen: Werte von I2C Sensoren über den UART-to-USB Converter an den PC übermitteln übermitteln, Nutzen der ADCs und ausgeben von PWM Signalen.

Kampi
17.12.2011, 10:12
So ich hab mal dein Programm bischen umgebaut.
Hier hast du den Code um den UART auszulesen.
Das ganze wird Interruptgesteuert gemacht, d.h. wenn ein Zeichen im Buffer liegt wird ein Interrupt ausgelöst, das Zeichen ausgelesen und in der Variable "Empfang_string" gespeichert und eine LED getoggled. Du kannst auch jede andere Variable für "Empfang_string" verwenden nur dann erhältst du im Terminal nur den ASCII-Wert des Zeichens. Du musst das Zeichen dann erst wieder in einen ASCII umwandeln.
Das Hauptprogramm läuft nun solange weiter bis ein Interrupt geschieht, bzw. bis ein Zeichen empfangen wurde. So hast du keine Warteverzögerungen :)

Hier das Programm:


$regfile = "M32def.dat"
$crystal = 16000000
$hwstack = 350
$swstack = 350
$framesize = 200

$baud = 19200

Config Portc.1 = Output
Config Portc.0 = Output

Dim I As Byte
Dim Empfang_string As String * 1

Portc.0 = 0
Portc.1 = 0

Enable Interrupts 'Interrupts Global zulassen
Enable Urxc 'Interrupt URXC einschalten

On Urxc Empfangen 'Interrupt-Routine setzen


Do
Toggle Portc.0
For I = 0 To 200
Waitms 1
Next I

Wait 1 '1 Sekunde warten

Loop

End


' ################################################## ###########
' #### UART Empfang
' ################################################## ###########

Empfangen:

Empfang_string = Waitkey() 'Zeichen aus dem Buffer einlesen

Print Empfang_string
Toggle Portc.1

Return


Der Code wurde mit einem RN-Control, TeraTerm und einem FT232 Modul getestet und funktioniert :)
Wenn du mehrere Zeichen hintereinander empfangen willst (z.B. ein Befehlswort) musst du die einzelnen Zeichen durchnummeriert in einem String speichern.

extremesports
17.12.2011, 10:16
Danke Kampi, ich werd es heut Abend oder morgen mal ausprobieren bzw. in meinen Code einbauen und dann wieder berichten.
Bis dahin... ;-)

MagicWSmoke
17.12.2011, 11:29
Empfang_string = Waitkey()


Um in einer UART-ISR ein Zeichen abzuholen, benötigt man kein Waitkey(), ein Inkey() tut's auch.
Hier böte sich an, in Bascom den gepufferten Zeichenempfang mit

Config Serialin = Buffered , Size = 20
einzuschalten.

Kampi
17.12.2011, 11:51
Um in einer UART-ISR ein Zeichen abzuholen, benötigt man kein Waitkey(), ein Inkey() tut's auch.
Hier böte sich an, in Bascom den gepufferten Zeichenempfang mit

Config Serialin = Buffered , Size = 20
einzuschalten.

Ja das mit dem Inkey hab ich vorhin auch gesehen :) aber danke für den Hinweis mit dem "Config SerialIn" :D
Bei der Lösung die ich gemacht habe handelt es sich nur um eine "Erstlösung" welche ich eben fix zusammengebastelt und getestet habe und die sicher auch noch Optimierungspotential bietet. Von daher bin ich für jeden Hinweis dankbar :D

extremesports
19.12.2011, 16:01
Hallo,

ich hab das jetzt mal versucht umzusetzen. Leider ohne irgendeinen Erfolg. Es tut sich einfach nichts... :(
Hab unten mal den aktuellen Code angehängt.
Eigentlich soll folgendes funktionieren:
Ich sende 4 Ziffern, bsp.:
5049 (50 für PORTD.6 und 49 für "an")
5050 (50 für PORTD.6 und 50 für "aus")
5159 (51 für PORTD.7 und ...)
Leider scheint bei der Übertragung so einiges nicht zu funktionieren. Ich verwende als UART-to-USB Converster ein mysmart USB MK II. Ich habe die RXD und die TXD Leitung angeschlossen und die Masse verbunden. Komischerweise hängt sich das Teil fast immer auf. Verbinde ich die Masse nicht passiert das nicht, aber dann bekomm ich für jedes gesendete Zeichen einen komischen Schnörkel zurück.


' ################################################## ###########
' #### USB-IO-plus
' #### by Jonathan Lorenz $PROG &H00,&H00,&H00,&H00' generated. Take care that the chip supports all fuse bytes.$PROG &H00,&H00,&H00,&H00' generated. Take care that the chip supports all fuse bytes.$PROG &H00,&H00,&H00,&H00' generated. Take care that the chip supports all fuse bytes.$PROG &H00,&H00,&H00,&H00' generated. Take care that the chip supports all fuse bytes.
' #### USBtoUART -> AVR
' #### Interface: GPIO, ADC, PWM, I2C, etc. (->Datasheet AVR)
' ################################################## ###########
' #### empfange Anweisungen vom PC über USBtoUART
' #### setzen oder lesen der Pins
' #### Steuerung der Schnittstellen
' ################################################## ###########
' #### getting instructions from PC over USBtoUART
' #### writing or reading the pins
' #### driving the Interfaces
' ################################################## ###########
' #### Bascom-AVR IDE [1.11.9.8]
' ################################################## ###########

$regfile = "M8def.dat" '.dat-file ATmega8'
$crystal = 8000000 'Taktfrequenz 8MHz'
$hwstack = 350 'Größe Hardwarestack'
$swstack = 350 'Größe Softwarestack'
$framesize = 200 'Größe Frame'

$baud = 19200 'Baudrate UART



'Tccr1a = &B10100010 'initialisieren der PWM-Frequenz 30,52 Hz bei 9 Bit
'Tccr1b = &B10000010 'initialisieren der PWM-Frequenz 30,52 Hz bei 9 Bit


'Declare Sub Empfang()
Declare Sub Verarbeitung()
Declare Sub Setzen()


'Config Adc = Single , Prescaler = Auto , Reference = Avcc
'Start Adc


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


Config Portd.6 = Output
Config Portd.7 = Output
Config Portb.0 = Output


Dim I as Byte ' Splitting der Hauptschleife
Dim Empfang_string As String * 10
Dim Port As String * 10
Dim Wert As String * 10
Dim B_port As Byte
Dim B_wert As Byte

Dim Zaehler As Byte


Portd.6 = 0
Portd.7 = 0
Portb.0 = 0
Zaehler = 0


Enable Interrupts 'Interrupts global zulassen
Enable Urxc 'Interrupt URXC einschalten
On Urxc Empfangen 'Interrupt-Routine setzen


Cls
Cursor On Blink
Lcd "USB-IO_plus"
Waitms 150
Locate 2 , 1
Lcd "."
Waitms 150
Locate 2 , 2
Lcd "."
Waitms 150
Locate 2 , 3
Lcd "."
Waitms 150
Locate 2 , 4
Lcd "initialisiert"


' ################################################## ###########
' #### Hauptprogramm
' ################################################## ###########

Do
' Toggle Portb.0 'Blinkende LED zur Kontrolle des Programmdurchlaufes
' For I = 0 To 200
' Waitms 1
' Next I

' Empfang

' Verarbeitung

' Setzen
Loop

End 'end program


' ################################################## ###########
' #### UART Empfang
' ################################################## ###########

'Sub Empfang()
' If Ischarwaiting() = 1 Then
' Input Empfang_string
' If Zaehler < 3 Then
' Incr Zaehler
' Else
' Zaehler = 0
' End If
' Else
' !nop
' End If
'End Sub

' ################################################## ###########
' #### Datenverarbeitung
' ################################################## ###########

Sub Verarbeitung()
Port = Left(empfang_string , 2) 'Byte 1 und 2 extrahieren
Wert = Mid(empfang_string , 3 , 2) 'Byte 3 und 4 extrahieren
B_port = Val(port) 'String zu Wert konvertieren
B_wert = Val(wert) 'String zu Wert konvertieren
End Sub

' ################################################## ###########
' #### Ausgänge setzen
' ################################################## ###########

Sub Setzen()
Select Case B_port 'zu setzenden Pin auswählen
Case 50 : If B_wert = 49 Then '50=2 | 49=1
Portd.6 = 1
Elseif B_wert = 50 Then ' | 50=2
Portd.6 = 0
End If
Case 51 : If B_wert = 49 Then '51=3 | 49=1
Portd.7 = 1
Elseif B_wert = 50 Then ' | 50=2
Portd.7 = 0
End If
Case Else : !nop
End Select
End Sub


' ################################################## ###########
' #### UART Interrupt
' ################################################## ###########

Empfangen:

Empfang_string = Waitkey() 'Zeichen aus dem Buffer einlesen

Verarbeitung

Setzen

Toggle Portb.0

Return

' ################################################## ###########
' #### Stand 16|12|2011
' ################################################## ###########

MagicWSmoke
19.12.2011, 18:47
Du wirst keinen String bekommen, sondern immer nur ein einzelnes Zeichen.

Empfang_string = Waitkey()
Damit gibt's auch nix mit den nachfolgenden Stringbefehlen zu verarbeiten.
Eine ISR soll so kurz wie möglich sein und nicht noch zwei weitere Subs aufrufen.

Empfangen:
Empfang_string = Waitkey() 'Zeichen aus dem Buffer einlesen
Verarbeitung
Setzen
Toggle Portb.0
Return

Also Flag in der ISR setzen und per Hauptschleife darauf reagieren.

extremesports
20.12.2011, 17:22
Danke für den Hinweis! Da hätte ich eigentlich selber drauf kommen müssen... *schäm*
Ich werd das nach Weihnachten mal umsetzen und dann hier wieder berichten!

Bis dahin... und allen ein frohes Fest!!!