PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Daten von Software UART empfangen



Jon
03.01.2007, 10:51
Hallo,
ich möchte mit einem ATMEGA8 vom Software UART Daten empfangen.
Mit dem Hardware UART mache ich es so:

$regfile = "m8def.dat"
$crystal = 4000000
$baud = 19200

$framesize = 42
$swstack = 42
$hwstack = 42

Dim Eingang As Byte

Open "COMD.7:19200,8,N,1" For Output As #1
Open "COMB.0:19200,8,N,2" For Input As #2

Do
If Usr.rxc = 1 Then
Eingang = Udr
Select Case Eingang
Case "1" : Print #1 , "1" 'iv
Case "2" : Print #1 , "2" 'iru
Case "3" : Print #1 , "3" 'il
Case "4" : Print #1 , "4" 'ire
Case "5" : Print #1 , "5" 'is
Case Else : Print "???"
End Select
End If
Loop

End
Die Daten werden auch schon über Software UART weitergesendet. Aber ist es in dieser Art auch möglich Datren über SOFTWARE UART zu empfangen?

Freue mich auf jede Antwort!!

jon

P.S.:Kenn jemand einen Bootloader, mit dem ich den ATMega8 über meine ER400TRS brogrammieren kann?
Der Bootloadert von Frank kennt nur den ATMEGA32 :(

Jon
03.01.2007, 13:55
Ich weiß, es sind erst 3Std vergengen, aber kann mir niemand helfen???
Ich langweile mich :(

jon

p_mork
03.01.2007, 14:30
Hallo Jon,
mit dem Befehl "SERIN var , byteanzahl , port , pin, baud , parity , dbits , sbits" kannst du Variablen per Sw-UART empfangen.
parity ist normaleweise 0, dbits 8 und s(top)bits 1.
Ich hoffe ich konnte dir weiterhelfen.

MfG Mark

Jon
03.01.2007, 16:02
Werd ich mal ausprobieren.
Danke für die Antwort!!

jon

Jon
29.01.2007, 15:06
Ich habe das jetzt schon vor längerer Zeit ausprobiert und es ging auch ganz gut^^
Jetzt habe ich das Problem, dass nicht immer was kommt. Ich will die kommenden Daten also nur abfragen, wenn auch welche kommen ;)
Im moment ist es so, dass er solange wartet, bis Daten kommt. Wenn da aber nichts kommt, soll er das einfach überspringen.

Am liebsten wäre mir so eine Variante wie oben in meinem Programm. Auch so, dass ich nur ein Byte empfange.

jon

p_mork
29.01.2007, 17:23
Hallo Jon,
wenn du den SW-Uart wie den HW-Uart butzen willst, dann musst du RxD an einen Interrupt-Pin drangängen. Bei einer fallenden Flanke muss dann ein Interrupt ausgelöst werden, der das Byte empfängt und in eine Variable speichert. Eine zweite Variable kann dann als UCSRA1 dienen. Alternativ ginge es auch an jedem Pin, wenn du einen Timer einstellt, der ständig den RxD-Pin abtastet(normaleweise mit 3-facher Baud). Das ginge dann aber auf Kosten der CPU-Leistung sowie des Timers.

MfG Mark

Jon
29.01.2007, 17:29
Danke für deine Antwort.
Das wäre eine Möglichkeit mit dem Interrupt. Das werde ich mal probieren. Im moment sind nur meine Akkus leer :(
Was ist UCSRA1?
Und das mit dem Teimer fällt raus, da es so schnell wie möglich gehen soll.

jon

p_mork
29.01.2007, 18:00
Hallo Jon,
UCSRA steht für UART Control and Status Register. dort werden Sachen des jeweiligen UART vermerkt wie z.b. ob ein byte empfangen wurde,ob der UART bereit ist ein byte zu senden usw. Eigentlich sollte es im obrigen Code UCSRA.rxd heissen, keine Ahnung wieso es in Bascom Usr heisst.

MfG Mark

Jon
29.01.2007, 18:21
Hast du dazu mal ein Beispielprogramm oder ist das in der Hilfe von BASCOM genannt (mit Beispiel)?

jon

p_mork
29.01.2007, 18:40
Hallo Jon,
ich habe leider kein Beispielprogramm, weil ich in C programmiere. Ob das in der BASCOM-Hilfe steht weiss ich nicht. Du könntest es vllt so machen:
einfach Interrupt bei fallender Flanke aktivieren(wie das in Bascom geht, weiss ich nicht), in der ISR steht dann z.b.
serin UDR1, UCSRA1.rxd=1, return. die Variablen UCRSA1 und UDR1(Uart Dara Register) müssen zuvor natürlich deklariert werden.
wenn du dann eine gucken willst, ob ein byte empfangen wurde kannst du es mit "if UDR1.rxd=1 then..." abfragen. Das byte selbst steht dann in UDR1. Vergiss nicht, das UCSR1.rxd wieder zu löschen, wenn du im Hauptprogramm UDR1 ausliest.
Ich verspreche jedoch nicht, dass dieses Programm funktionieren wird.

Such mal bei google nach "software-uart bascom" vllt findest du was.

MfG Mark

Jon
29.01.2007, 19:12
Danke!!
dann werde ich mir mal die BASCOM-Hilfe anschauen und es mal probieren.

jon

Jon
30.01.2007, 20:25
Ich habe schon die BASCOM-Hilfe durchforstet, aber nichts gefunden :(
Jetzt bin ich aber auf die Idee gekommen über ein Low-Signal dem ATMega zu "sagen", dass was empfangen werden soll und er erst in eine Schleife geht, wenn das Signal wirklich anliegt.
Aber da ich diese Signalleitung auch zum Resetten (<--mit doppeltem "t"???) verwende, habe ich die Frage, wie lange ich den Reset-Pin auf low ziehen kann, ohne dass er resettet.
Ich werde gleich aber auch nochmal ins DB schauen :)

jon

Bluesmash
30.01.2007, 20:45
für den empfang mit der software uart kann ich nur die version mit dem interrupt empfehlen... bin gerade an nem projekt indem ich es verwende...

hier ein kleiner auszug aus meinem code must ihn halt noch abändern für deinen prozi... wichtig ist einfach dass der port für den empfang an einem interrupt pin hängt... bei mir wird der anfang der zu empfangenen daten mit einer 1 erkannt...



Open "Comb.6:9600,8,n,1" For Input As #2

Config Int0 = Falling
On Int0 Int0_isr
Enable Int0

Enable Interrupts

do

loop

Int0_isr:

Temp = Inkey(#2)

If Temp = 1 Then
Temp = 0

Servo1 = Waitkey(#2)
Servo2 = Waitkey(#2)
Speed = Waitkey(#2)
End If
Return



gruss bluesmash

Jon
30.01.2007, 20:47
Das blöde ist nur, dass bei mir schon alle Interrupt-Ports belegt sind :(
Sonst hätte ich es auch erst so versucht.

jon

Bluesmash
30.01.2007, 21:49
was hast du denn alles an den interrupts? ev. könnte man ja 2 zusammenfassen... indem man 2 auf einen interrupt legt und zusätzlich die beiden signale auf je einen normalen port legt, dann in der interrupt routine die beiden ports abfragen und schauen welcher interrupt ausgelöst hat....

gruss bluesmash

-tomas-
31.01.2007, 11:48
@Jon
Bluesmash hat den richtigen Weg beschrieben. Du solltest es in einer ISR abfangen.

Da Du auch mit einem ATMEGA8 arbeitest, verweise ich mal zur Info auf mein ATMEGA8-Projekt mit Software + Hardware UART:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=26041

Jon
31.01.2007, 14:19
Ich verwende keine Interrupts. Ich habe nur noch einen Pin frei, den habe ich jetzt mit dieser Signal-Leitung belegt.
Weshalb ich kein Interrupt verwenden kann:
1.Kein Pin frei, der Interrupt hat
2.Kann ich nicht immer einen Interrupt vertragen, da ich auch die Signale abfragen muss, die von der Fernbedienung kommen. Und wenn er mich dann bei Vorwärtsfahren unterbricht, dann kann ich nicht bremsen. Kommt also eine Kannte, habe ich ein Problem.
Ich könnte zwar den Bot stoppen, aber das möchte ich nicht.

Ich werde es jetzt so mal probieren und schauen, was herauskommt.

jon

-tomas-
31.01.2007, 18:40
Ich verwende keine Interrupts.
Hallo Jon,

wie schon Bluesmash andeutete - es war nur ein guter Rat.
Wenn Du Dich mit Interrupts beschäftigst, wirst Du erkennen, das eine ISR der einzige Weg ist, um diese Unterbrechungen von INKEY/WAITKEY/GETRC5 o.ä. zu vermeiden.

Was benutzt Du für eine Fernsteuerung?


Das blöde ist nur, dass bei mir schon alle Interrupt-Ports belegt sind
Wirklich? Der Atmega8 besitzt mind. 4 Eingänge um Level-Interrupts zu erzeugen.
Eingänge: INT0, INT1, Analog Comparator ANA_COMP und noch den Timer/Counter1 Capture Event ICP1 (TIFR.ICF1)

Jon
31.01.2007, 19:39
Was benutzt Du für eine Fernsteuerung?
Diese (http://imadeit.roboterbastler.de/fernbedienung.html) O:)


Wirklich? Der Atmega8 besitzt mind. 4 Eingänge um Level-Interrupts zu erzeugen.
Eingänge: INT0, INT1, Analog Comparator ANA_COMP und noch den Timer/Counter1 Capture Event ICP1 (TIFR.ICF1)
Der muss aber auch mit 4µCs und über Funk kommunizieren. Da ist kaum weiterer Platz...

Aber ich habe es jetzt geschafft. Ich habe es hinbekommen, wenn ich mit dem Prog fertig bin, kann ich es mal auf meine Seite stellen.

jon

coCo
03.03.2007, 19:14
für den empfang mit der software uart kann ich nur die version mit dem interrupt empfehlen... bin gerade an nem projekt indem ich es verwende...

hier ein kleiner auszug aus meinem code must ihn halt noch abändern für deinen prozi... wichtig ist einfach dass der port für den empfang an einem interrupt pin hängt... bei mir wird der anfang der zu empfangenen daten mit einer 1 erkannt...



Open "Comb.6:9600,8,n,1" For Input As #2

Config Int0 = Falling
On Int0 Int0_isr
Enable Int0

Enable Interrupts

do

loop

Int0_isr:

Temp = Inkey(#2)

If Temp = 1 Then
Temp = 0

Servo1 = Waitkey(#2)
Servo2 = Waitkey(#2)
Speed = Waitkey(#2)
End If
Return



gruss bluesmash


Hi,
wie wird das von dem anderen Controller angesteuert? Also wie sendest du die Bytes? Ich hab folgenden Code für den Servocontroller:


$regfile = "attiny2313.dat"
$crystal = 8000000


Waitms 100


Config Servos = 4 , Servo1 = Portb.0 , Servo2 = Portb.1 , Servo3 = Portb.2 , Servo4 = Portd.6 , Reload = 10

Config Portb = Output
Config Portd.6 = Output


Config Int0 = Falling
On Int0 Int0_isr
Enable Int0


Enable Interrupts


Servo(1) = 100
Servo(2) = 100
Servo(3) = 100
Servo(4) = 100

Dim Temp As Byte
Dim New As Bit
Dim Servo_num As Byte
Dim Servo_pos As Byte

Open "Comd.2:9600,8,n,1" For Input As #2

Do
If New = 1 Then
Servo(Servo_num) = Servo_pos
New = 0
End If
Loop

Int0_isr:

Temp = Inkey(#2)

If Temp = 1 Then
Temp = 0

Servo_num = Waitkey(#2)
Servo_pos = Waitkey(#2)
New = 1
End If
Return


Und das is der Code von dem Controller, der dem Servocontroller die "Befehle" gibt:


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

Waitms 100


Do
Print 1
Print 1
Print 170

Wait 2

Print 1
Print 1
Print 70

Wait 2
Loop
End


Dadurch sollte der Servo sich immer vor und zurückdrehn. Allerdings bewegt er sich keinen Millimeter. Es muss am Soft-UART liegen, wenn ich den Servo direkt ansteuer gehts. Ich denke mal dass die "Print"-Befehle nicht in Ordnung sind.

Kann mir jemand helfen?

MfG

Jon
03.03.2007, 19:34
Ich denke mal dass die "Print"-Befehle nicht in Ordnung sind.
Genau. Die Zahlen müssen in "" sein. Also z.B.: Print "1"

jon

coCo
03.03.2007, 19:40
Hi Jon,
habs grad probiert, geht trotzdem net.

MfG

Jon
03.03.2007, 19:56
Ist Pind.2 überhaupt ein Interruptfähiger Pin?

jon

coCo
03.03.2007, 20:04
Ja, das is beim Tiny2313 Int0.

MfG

Jon
03.03.2007, 20:10
Gut.
Versuche mal zw. die Printbefehle 10ms Pausen zu setzten.
Dann sähe das Programm so aus:


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

Waitms 100


Do
Print "1"
waitms 10
Print "1"
waitms 10
Print "170"

Wait 2

Print "1"
waitms 10
Print "1"
waitms 10
Print "70"

Wait 2
Loop
End


Noch ne blöde Frage:
Hast du bei den Fusebits auch die 8MHz eingestellt?

Mehr finde ich im Moment nicht.

jon

coCo
03.03.2007, 20:22
Hi,
danke für deine Hilfe. Klappt aber leider nicht. Fusebits sind ok, Kommunikation mit dem PC klappt.

Es reicht schon wenn ich den TxD Pin des Mega8 mit dem RxD Pin des Tiny2313 verbinde oder sollte ich die beiden anderen auch miteinander verbinden (die bräuchte ich eigentlich nur wenn ich vom Tiny2313 etwas zum Mega8 senden will oder?)?

MfG

Jon
03.03.2007, 20:24
Es reicht schon wenn ich den TxD Pin des Mega8 mit dem RxD Pin des Tiny2313 verbinde oder sollte ich die beiden anderen auch miteinander verbinden (die bräuchte ich eigentlich nur wenn ich vom Tiny2313 etwas zum Mega8 senden will oder?)?
Die eine Leitung reicht. Mehr brauchst du ja nicht.

jon

coCo
03.03.2007, 23:22
Hat sonst vielleicht jemand noch eine Idee wieso es nicht klappt?

MfG

coCo
04.03.2007, 11:55
Hi,
ich hab jetzt versucht auf hardware UART umzusteigen. Allerdings funktionierts immer noch nicht :(

Hier mal mein Code vom Empfänger:



$regfile = "attiny2313.dat"
$crystal = 8000000
$baud = 9600


Waitms 100


Config Servos = 4 , Servo1 = Portb.0 , Servo2 = Portb.1 , Servo3 = Portb.2 , Servo4 = Portd.6 , Reload = 10

Config Portb = Output
Config Portd.6 = Output
Config Portd.1 = Output
Portd.1 = 1

On Urxc Onrxd
Enable Urxc
Enable Interrupts



Servo(1) = 130
Servo(2) = 130
Servo(3) = 130
Servo(4) = 130

Dim I As Byte
Dim Servo_data(2) As Byte

I = 0


Do
If I > 1 Then
Servo(servo_data(1)) = Servo_data(2)
I = 0
End If

Loop


Onrxd:
Incr I
Servo_data(i) = Udr
Toggle Portd.1
Return


End

An Portd.1 hängt eine LED, um zu schaun ob die ISR überhaupt aufgerufen wird. Allerdings wird sie nicht aufgerufen, die LED ändert nicht ihren Zustand.

Code vom Sender:



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

Waitms 100



Do
Print "1"
Waitms 10
Print "170"

Wait 2

Print "1"
Waitms 10
Print "70"

Wait 2

Loop
End


Ich weiß echt nicht mehr was ich machen soll. Es will einfach nicht klappen. ](*,) ](*,)

Hoffe mir kann jemand helfen.

MfG

Jon
04.03.2007, 11:59
Fehlt bei den Prog für den sender nicht noch das "Startsignal"?
Du musst doch erst eine Zahl >1 senden, damit er in die IF-Schleife geht.

jon

coCo
04.03.2007, 12:08
Ne, sobald ein Zeichen ankommt, wird das in dem Array Servo_data gespeichert. I ist nur der Zähler für die Array Elemnte, wenn I also größer als 1 ist, sind 2 Bytes (Servo Nummer und Position) angekommen und das Programm geht in die if-Schleife wo es den Servo ansteuert. Das Problem is ja, dass die ISR gar nicht aufgerufen wird...

MfG