Forum: Mikrocontroller und Digitale Elektronik UART Interrupt


von Myster L. (myster_l)


Lesenswert?

Hallo,
Ich habe ein Programm mit Bascom geschriben, bei dem ich am Anfang einen 
Befehl über die UART einlese. Dies habe ich bisher mit
1
 
2
  NeueDaten = IsCharWaiting ()                      'Neue Daten Empfangen
3
  if NeueDaten = 1 then
4
     Input , Datain
Wie ihr sehen könnt lasse ich mir den String dabei immer zurückgeben und 
mir ist aufgefallen, dass immer mal wieder das 3.Zeichen fehlt.
Also hab ich mal IsCharWaiting() rausgeschmissen und siehe da, es 
funktioniert. Jetzt ist aber mein Programmablauf zu lang, also habe ich 
nach Alternativen für IsCharWaiting() gesucht. (Inkey hat das gleiche 
Problem)
und bin auf UART Interrupts gestoßen, die wohl genau diesem fehlen von 
Zeichen vorbeugen soll.
Aber ich konnte niergends einen erklärten Befehlssatz finden, maximal 
ein paar Beispielprogramme, aber anhand derer verstehe ich leider nicht, 
was genau ich jetzt für mein Programm wo an Befehlen brauche.
Ich nutze einen ArduinoNano mit einem Bascom Programm.
Ich wäre euch für Befehle, mitsamt Erklärung echt dankbar.
Also schon mal Danke im Vorraus
Myster_Levoltie

von Adam P. (adamap)


Lesenswert?


von Uart overlay (Gast)


Lesenswert?

Von Rowalt.de.

Perfekt!


'0011.BAS: Optimierter String-Empfang
$Regfile = "2313def.dat"
$Crystal = 3686400
$Baud    = 9600

Dim s As String*10 At &H60
Dim b(11) As Byte At &H60 Overlay
Dim n As Byte

On URXC OnRxD
Enable URXC
Enable Interrupts

Main:
  If n > 9 Then
    Print s
    n = 0
  End If
Goto Main

OnRxD:
  Incr n
  b(n) = UDR
Return

von Myster L. (myster_l)


Lesenswert?

Thx Adam P.
Der 1.Link war zwar nur Taster und Timer interrupts, aber im 2. Hab ich 
was gefunden.
Keine Ahnung, wieso ich diese seiten bei meiner eigenen Recherce nicht 
gefunden hab, ist saß da schon ne weile Dran, vermutlich bin ich blind, 
blöd, oder beides xD.
Auf jeden Fall danke für die Hilfe

von Peter D. (peda)


Lesenswert?

Uart overlay schrieb:
> Dim s As String*10 At &H60

Sicher, daß man Strings händisch plazieren muß, bzw. überhaupt darf?
Das sollte ja der Compiler besser machen können. Z.B. beim ATmega328 ist 
an &H60 noch gar kein RAM. Händisches Plazieren kann also schnell mal in 
die Hose gehen.

Eine feste Zeichenzahl ist recht unflexibel. Typisch liest man Strings 
bis zum CR/LF ein.
Natürlich muß man auch auf Pufferende testen, damit nicht der RAM 
überschrieben wird.

von Myster L. (myster_l)


Lesenswert?

Adam P. schrieb:
> - http://staff.ltam.lu/feljc/electronics/bascom/BASCOM_Tutorial_2.pdf

Also ich hab es jetzt mit dem von diesem Link gemacht und das klappt 
auch soweit, aber wenn ich das 1.Mal nach dem Starten des Programms/µC 
einen Befehl hinsende fehlt immernoch das 3. Zeichen, bei jeglichen 
danach, funktioniert es jetzt einwandfrei.
Irgendwelche Ideen Adam?

von Adam P. (adamap)


Lesenswert?

Myster L. schrieb:
> Irgendwelche Ideen Adam?

Sorry, ich programmier in C.

Grundsätzlich:
Wird ein Interrupt für den Empfang benutzt,
dann sollten eigentlich keine Zeichen verloren gehen.

von Peter D. (peda)


Lesenswert?

Myster L. schrieb:
> Also ich hab es jetzt mit dem von diesem Link gemacht

Zeig Deinen echten Code.

von Myster L. (myster_l)


Lesenswert?

Ich hab leider keine Wahl als Bascom zu nehmen. :/ (Azubi eben)
Also ich mach es wie im code oben auch, ich setzt mir in der URXC 
einfach wieder das Merker-Bit und werte es im Hauptprogramm aus, weil 
sonst später zu viel Zeit verloren geht, wenn ich das in der ISR machen 
würde.
(Ganz nebenbei, dass ich denke, dass es gar nicht geht, die Zeichen alle 
auf einmal in der ISR auszulesen, weil für Input-Befehl URXC disabled 
sein muss)

Naja, wenn ich eindeutig sagen kann, dass es nur beim 1. Befehl ist, 
dass lässt sich ja durch nen Dummy-Befehl, der beim Starten des Systems 
1. Hingesendet wird lösen. Hauptsache der Nutzer später hat kein Problem 
mehr.

Nochmal danke dir.

von Adam P. (adamap)


Lesenswert?

Falls du in dem Interrupt nur das Zeichen empfängst und dieses dann aber 
erst in der Hauptschleife einem String zuweist...dann kann es schon 
passieren.

von Adam P. (adamap)


Lesenswert?

Myster L. schrieb:
> ich setzt mir in der URXC
> einfach wieder das Merker-Bit und werte es im Hauptprogramm aus

Das ist dann zu spät.
Du musst im Interrupt das Zeichen nehmen und dem String anhängen.

von Myster L. (myster_l)


Lesenswert?

Peter D. schrieb:
> Zeig Deinen echten Code.

Teil im Hauptprogramm:
1
if NeueDaten = 1 then
2
         NeueDaten = 0
3
         Disable  URXC                                'Für Inupt-Befehl muss URXC aus sein
4
         Input , Datain ', noecho                     'Empfangene Daten in "Datain" String speichern
5
         Enable  URXC

Dazugehörige ISR:
1
Serialinterrupt:
2
   NeueDaten = 1
3
Return

von Myster L. (myster_l)


Lesenswert?

Adam P. schrieb:
> Das ist dann zu spät.
> Du musst im Interrupt das Zeichen nehmen und dem String anhängen.

Ich kann den String nicht im Interrupt auslesen, das würde zu viel Zeit 
kosten, das Programm hat später sehr viele Interrupts, da es einen 
Schrittmotor mit bis zu 4000U/min steuern muss und der darf halt echt 
nicht ruckeln.

von Adam P. (adamap)


Lesenswert?

Myster L. schrieb:
> Für Inupt-Befehl muss URXC aus sein

Das bezweifel ich...wer sagt das?

Mach die Zuweisung direkt im Interrupt.

von Adam P. (adamap)


Lesenswert?

Myster L. schrieb:
> da es einen
> Schrittmotor mit bis zu 4000U/min steuern muss

Dann würde ich es erst recht nicht mit Bascom machen...sag das mal 
deinem schlauen Ausbilder :-D

von Myster L. (myster_l)


Lesenswert?

Adam P. schrieb:
> Das bezweifel ich...wer sagt das?

Dein Link:
http://staff.ltam.lu/feljc/electronics/bascom/BASCOM_Tutorial_2.pdf
Seite 5, steht auch extra Rot dran...

von Adam P. (adamap)


Lesenswert?

Myster L. schrieb:
> Adam P. schrieb:
>> Das bezweifel ich...wer sagt das?
>
> Dein Link:
> http://staff.ltam.lu/feljc/electronics/bascom/BASCOM_Tutorial_2.pdf
> Seite 5, steht auch extra Rot dran...

Ah ok, interessant...aber bzgl. Zeit.

Ob du nun im Interrupt eine Variable auf 1 oder 0 setzt oder ob du einer 
Variable ein Zeichen zuweist...das sollte aufs gleiche hinauslaufen.

von Myster L. (myster_l)


Lesenswert?

Adam P. schrieb:
> Dann würde ich es erst recht nicht mit Bascom machen...sag das mal
> deinem schlauen Ausbilder :-D

Ich hab wie gesagt leider keine Wahl. Er ist auf Bascom spezialisiert, 
gelernt hab ich zwar auch C, aber hier muss ich leider Bascom verwenden. 
:/

von Myster L. (myster_l)


Lesenswert?

Adam P. schrieb:
> Ob du nun im Interrupt eine Variable auf 1 oder 0 setzt oder ob du einer
> Variable ein Zeichen zuweist...das sollte aufs gleiche hinauslaufen.

Auch bei einem String mit bis zu 12 Zeichen?

von Adam P. (adamap)


Lesenswert?

Myster L. schrieb:
> Auch bei einem String mit bis zu 12 Zeichen?

Ja weil im Empfangsregister nur 1 zeichen Platz hat.
Ein Interrupt Aufruf = 1 Zeichen.
Schau ins Datenblatt vom µC.
Da gibts kein Platz für nen String, nur 1 Zeichen.

von Peter D. (peda)


Lesenswert?

Myster L. schrieb:
> Dazugehörige ISR:
> Serialinterrupt:
>    NeueDaten = 1
> Return

Das ist Quatsch mit Soße.
Du mußt das Zeichen in einem Puffer ablegen und den Puffer weiterzählen.
Üblich nennt sich sowas FIFO.

von Adam P. (adamap)


Lesenswert?

Adam P. schrieb:
>> Dein Link:
>> http://staff.ltam.lu/feljc/electronics/bascom/BASCOM_Tutorial_2.pdf
>> Seite 5, steht auch extra Rot dran...

Da steht für den INPUT Befehl.
Das benutzt du doch gar nicht...somit nix mit deaktiveren.

von Myster L. (myster_l)


Lesenswert?

Also wie gesagt: in Kombination mit dem Hauptprogramm teil funktioniert 
es aktuell einwandfrei. Hab über 100 Befehle hingesendet, kein Zeichen 
hat gefehlt.

von Myster L. (myster_l)


Lesenswert?

Adam P. schrieb:
> Das benutzt du doch gar nicht...somit nix mit deaktiveren.

Doch, natürlich:

Myster L. schrieb:
> Teil im Hauptprogramm:

von Adam P. (adamap)


Lesenswert?

Myster L. schrieb:
> Also wie gesagt: in Kombination mit dem Hauptprogramm teil funktioniert
> es aktuell einwandfrei. Hab über 100 Befehle hingesendet, kein Zeichen
> hat gefehlt.

Ja wie nun...was hast jetz geändert?
Dachte es funktioniert nicht beim ersten mal...

von Myster L. (myster_l)


Lesenswert?

Myster L. schrieb:
> Teil im Hauptprogramm:if NeueDaten = 1 then
>          NeueDaten = 0
>          Disable  URXC
>          Input , Datain
>          Enable  URXC
>
> Dazugehörige ISR:
> Serialinterrupt:
>    NeueDaten = 1
> Return

Da hatte ich doch den Code gepostet

von Myster L. (myster_l)


Lesenswert?

Adam P. schrieb:
> Dachte es funktioniert nicht beim ersten mal...

Früher hat regelmäßig das 3. Zeichen gefehlt, jetzt fehlt es nur beim 
allerersten Befehl

von Adam P. (adamap)


Lesenswert?

Myster L. schrieb:
> Da hatte ich doch den Code gepostet

Ja und hast gesagt:

Myster L. schrieb:
> Also ich hab es jetzt mit dem von diesem Link gemacht und das klappt
> auch soweit, aber wenn ich das 1.Mal nach dem Starten des Programms/µC
> einen Befehl hinsende fehlt immernoch das 3. Zeichen

Myster L. schrieb:
> Früher hat regelmäßig das 3. Zeichen gefehlt, jetzt fehlt es nur beim
> allerersten Befehl

Also funktioniert es noch nicht!

: Bearbeitet durch User
von Karl B. (gustav)


Lesenswert?

Myster L. schrieb:
> Früher hat regelmäßig das 3. Zeichen gefehlt, jetzt fehlt es nur beim
> allerersten Befehl

Hi,
dann ist es aber immer noch nicht sauber.

Peter D. schrieb:
> Du mußt das Zeichen in einem Puffer ablegen und den Puffer weiterzählen.
> Üblich nennt sich sowas FIFO.

Oder Ringpuffer.

ciao
gustav

von Myster L. (myster_l)


Lesenswert?

Jo, das Korrekt.

Ausgangssituation bevor ich mich ans Vorum gewendet habe:
REGELMÄßIG fehlte bei hingesendeten Datenstring das 3. Zeichen

Jetzt, nachdem ich es mit deinem Link gemacht habe:
NUR beim 1. mal hinsenden, nach starten des Programmes/µC fehlt das 3. 
Zeichen.
Jeder Befehl danach ist sauber!

von Myster L. (myster_l)


Lesenswert?

Karl B. schrieb:
> Hi,
> dann ist es aber immer noch nicht sauber.

Das stimmt schon.
Aber es ist schon mal deutlich besser als vorher. ;)
Solange es nur der allererste Befehl ist, kann ich da mogeln und einfach 
einen Dummy-Befehl automatisch hinsenden lassen, sodass alle Befehle vom 
Benutzer dann funktionieren.
Nicht elegant, aber funktionsfähig. Mir geht halt leider die Zeit aus...

von Adam P. (adamap)


Lesenswert?

Myster L. schrieb:
> Jeder Befehl danach ist sauber!

Das ist trotzdem falsch...Kannst ja auch net sagen:
"Beim ersten Flugzeugstart an einem Tag fallen alle Instrumente aus, 
ABER danach läufts" :-D

Ich hab grad mein Sozialen...
Wie heißt die Entwicklungsumgebung bzw. Compiler?
Dann versuch ich das eben selbst und messe die Zeiten mit nem 
LogicAnalyser.

von Myster L. (myster_l)


Lesenswert?

Adam P. schrieb:
> Wie heißt die Entwicklungsumgebung bzw. Compiler?

Ich schätze es ist das hier:?
BASCOM-AVR IDE[2.0.7.7]

von Myster L. (myster_l)


Lesenswert?

Adam P. schrieb:
> "Beim ersten Flugzeugstart an einem Tag fallen alle Instrumente aus,
> ABER danach läufts" :-D

Naja, fliegen wird es dann vermutlich nicht mehr. :-D
Aber etwas Sport schadet ja nicht. xD

von Peter D. (peda)


Lesenswert?

Myster L. schrieb:
> Aber es ist schon mal deutlich besser als vorher. ;)

Du hast aber das Problem nicht gelöst. Es wird Dir daher wieder auf die 
Füße fallen, sobald das Programm etwas mehr zu tun hat.

So ist der Interrupt vollkommen sinnlos. Du kannst auch im Main das 
RXC0-Flag direkt testen.

von Myster L. (myster_l)


Lesenswert?

Peter D. schrieb:
> Du hast aber das Problem nicht gelöst. Es wird Dir daher wieder auf die
> Füße fallen, sobald das Programm etwas mehr zu tun hat.

Wie meinst du das, also von welcher Situation sprichst du genau?

von Adam P. (adamap)


Lesenswert?

Myster L. schrieb:
> also von welcher Situation sprichst du genau?

Von der die immer dann Eintrifft, wenn man am wenigstens damit 
rechnet...
und dann geht der ganze Spaß erst richtig los, weil man erstmal gar 
nicht weiß woran es liegt.

von Peter D. (peda)


Lesenswert?

Myster L. schrieb:
> Dazugehörige ISR:
> Serialinterrupt:
>    NeueDaten = 1
> Return

Der Interrupt ist nicht nur vollkommen nutzlos, er feuert auch 
ununterbrochen, bis die Mainloop das RXD ausliest. Das Main läuft dabei 
mit etwa 1% CPU Takt, also bei 8MHz Quarz effektiv mit 80kHz.
Daß da überhaupt noch irgendwas funktioniert, halte ich für ein Gerücht.

von Myster L. (myster_l)


Lesenswert?

Ich vertrau euch ehrlich gesagt mehr als mir selbst, was das hier 
angeht, daher bin ich grad am umschreiben mit
1
Serialinterrupt:
2
incr nDataina(n) = UDR
3
Return
damit sollte ich die Zeichen dann ja schon mal alle in dem Array haben. 
Meine  Verarbeitung basiert aber darauf, dass es ein String ist. Da 
direkt einen String zu verwenden ging nicht so einfach, also brauche ich 
ja theoretisch nur noch ne möglichkeit das Array jetzt in nen String zu 
konvertieren, richtig?

von Adam P. (adamap)


Lesenswert?

Wie wäre es damit?

https://halvar.at/elektronik/kleiner_bascom_avr_kurs/uart_rs232_vom_computer_2/

Das läuft im Interrupt.
Wenn du dir dann da noch nen tx_done flag setzt, sobald alles da ist, 
dann kannst dein Buffer/Array/String in der Hauptschleife 
interpretieren.

von Myster L. (myster_l)


Angehängte Dateien:

Lesenswert?

Adam P. schrieb:
> Wie wäre es damit?

Hab es grad eben angepasst einprogrammiert und bisher läuft es gut, aber 
ich habe 2 Fragen:
1. Wie lange braucht diese Interrupt Routiene?
2. Wie ist die Priorität dieser ISR? Ich habe eine Tabelle angehängt, du 
weißt nicht zuällig welche dieser Interrupts es ist, oder?
(Mir geht´s darum, ob höher, oder niedriger priorisiert als timer1 
compare)

aber bisher sieht es ganz gut aus.
(Nicht, dass ich besonders viel ahnung hätte. Ich bin zwar unter 
meinesgleichen ganz gut was Programmieren angeht, aber in 3Jahren und 
nur nebenbei, lernt man halt nur begrenzt viel :) )

von Pandur S. (jetztnicht)


Lesenswert?

Allenfalls kann man den Strin auch verarbeiten wehrend er reinkommt, 
dann erspart man sich das Abspeichern.

von Myster L. (myster_l)


Lesenswert?

Pandur S. schrieb:
> Allenfalls kann man den Strin auch verarbeiten wehrend er reinkommt,
> dann erspart man sich das Abspeichern.

Nope, dafür ist die verarbeitung viel zu groß. Ich habe alle 
Informationen auf geringe Zeichenmenge komprimiert, dass ist gut für die 
Übertragung, aber die Auswertung braucht halt länger.

Beitrag #6434453 wurde von einem Moderator gelöscht.
von AF (Gast)


Lesenswert?

Peter D. schrieb:
> Uart overlay schrieb:
>> Dim s As String*10 At &H60
>
> Sicher, daß man Strings händisch plazieren muß, bzw. überhaupt darf?

Ja, Bascom Overlays sind eine feine Sache.

> Das sollte ja der Compiler besser machen können. Z.B. beim ATmega328 ist
> an &H60 noch gar kein RAM. Händisches Plazieren kann also schnell mal in
> die Hose gehen.

Wozu dient wohl diese Zeile?;-)
$Regfile = "2313def.dat"

Natürlich soll das im RAM liegen, also DABLA wälzen.
Basom wird da aber schon meckern!

>
> Eine feste Zeichenzahl ist recht unflexibel. Typisch liest man Strings
> bis zum CR/LF ein.
> Natürlich muß man auch auf Pufferende testen, damit nicht der RAM
> überschrieben wird.

Ja, kommt immer darauf an was man will;-)

Beitrag #6434476 wurde von einem Moderator gelöscht.
von Peter D. (peda)


Lesenswert?

AF schrieb:
> Natürlich soll das im RAM liegen, also DABLA wälzen.

Oder den Compiler sich automatisch drum kümmern lassen, denn dazu ist er 
ja da. Warum ihm also ins Handwerk pfuschen, das ergibt doch keinen 
Sinn.
Laß das "At &H60" ganz einfach weg.

von Myster L. (myster_l)


Lesenswert?

AF schrieb:
>> Eine feste Zeichenzahl ist recht unflexibel. Typisch liest man Strings

Naja, ich weiß ja genau, welche Befehle gesendet/empfangen werden, d.h. 
kein Grund mehr Speicherplatz zu verschwenden, als nötig. ;)

von Peter D. (peda)


Lesenswert?

Myster L. schrieb:
> Naja, ich weiß ja genau, welche Befehle gesendet/empfangen werden, d.h.
> kein Grund mehr Speicherplatz zu verschwenden, als nötig. ;)

Das ist nicht der Punkt.
Eine feste Länge bietet keine Möglichkeit der Paketsynchronisation.
Schaltet man nicht beide Seiten gleichzeitig ein oder treten Störungen 
auf, bleibt man für alle Zeit asynchron und empfängt immer nur Mumpitz.
Ein Endezeichen ist quasi das minimalste Protokoll mit Fehlerbehebung.
Gerne fügt man vor dem Endezeichen auch noch 2 Hex-Digits als CRC ein.

von AF Overlay (Gast)


Lesenswert?

AF schrieb:
> Ja, Bascom Overlays sind eine feine Sache.

Man muß halt wissen was man tut;-)
https://avrhelp.mcselec.com/index.html?dim.htm

von AF Overlay (Gast)


Lesenswert?

Peter D. schrieb:
> Das ist nicht der Punkt.
> Eine feste Länge bietet keine Möglichkeit der Paketsynchronisation.
> Schaltet man nicht beide Seiten gleichzeitig ein oder treten Störungen
> auf, bleibt man für alle Zeit asynchron und empfängt immer nur Mumpitz.
> Ein Endezeichen ist quasi das minimalste Protokoll mit Fehlerbehebung.
> Gerne fügt man vor dem Endezeichen auch noch 2 Hex-Digits als CRC ein.

Absolut korrekt, dafür hat man auch mal ASCII Zeichen wie STX und ETX 
definiert.

Auf irgendwas muss man sich "synchronisieren".

von Audi10 (Gast)


Lesenswert?

Natürlich ist eine Synchronisation sinnvoll. Aber dafür braucht man, so 
viel ich den vorligenden Fall verstanden habe, keine variable Länge. 
Wenn das Schlusszeichen nicht mit dem Ende des Speichers zusammenfallt, 
hat man den Anfang verpasst. Wenn die Messagelänge immer gleich ist, 
dann heisst doch, dass pro "Burst" diese maximale Anzahl zeichen kommen, 
wenn nicht synchron, dann weniger.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.