Forum: Mikrocontroller und Digitale Elektronik Bascom Serialin


von Andreas (Gast)


Lesenswert?

Hallo,

ich nutze für ein Projekt schon länger folgenden Code von 
http://halvar.at/elektronik/kleiner_bascom_avr_kurs/uart_rs232_vom_computer_2/
1
$regfile = "m8def.dat"
2
$crystal = 8000000
3
$hwstack = 100
4
$swstack = 100
5
$framesize = 100
6
$baud = 38400
7
8
Declare Sub Serial0charmatch()
9
10
Config Serialin = Buffered , Size = 30 , Bytematch = 13
11
Enable Interrupts
12
13
'Hauptschleife
14
Do
15
   !NOP
16
Loop
17
End
18
19
20
Sub Serial0charmatch()
21
   Local Incoming_data As String * 35
22
23
   'Daten vom Buffer auslesen
24
   Input Incoming_data Noecho
25
   'Ausgelesene Daten zurück schicken
26
   Print Incoming_data
27
End Sub

Heute ist mir aufgefallen, sobald die eingegebenen Zeichen über den UART 
die Zahl bei Size (hier 30) übersteigen und dann mit CR bestätigt wird, 
hängt sich der Controller bei "Input Incoming_data Noecho" auf.

Aber warum eigentlich? Der Puffer sollte doch laut Bascom Hilfe ein 
Ringpuffer sein, also sollte es keine Probleme geben.

Hat jemand ne Ahnung warum das passiert? Wenn ja evtl. was man dagegen 
tun kann?

Gruß Andreas

von Joe (Gast)


Lesenswert?

CR ist das 31 Zeichen.
Der Buffer wird nur abgearbeitet, wenn CR erkannt wurde.

von Andreas (Gast)


Lesenswert?

Hm versteh ich jetzt nicht so ganz. Sobald CR empfangen wurde, wird
Serial0charmatch() aufgerufen und versucht den Buffer zu lesen.
Nur genau da bleibt der Controller hängen

von Steffen (Gast)


Lesenswert?

Andreas schrieb:
> Sub Serial0charmatch()
>    Local Incoming_data As String * 35
>
>    'Daten vom Buffer auslesen
>    Input Incoming_data Noecho
>    'Ausgelesene Daten zurück schicken
>    Print Incoming_data
> End Sub
> [/code]

liegt es vielleicht daran, das du den Quelltext nicht 100% übernommen 
hast?
1
 Local Incoming_data As String * 30

von Andreas (Gast)


Lesenswert?

Nope hab ich nur extra größer gemacht, dachte es liegt evtl. an der 
binären Null.

Das Problem ist sogar sehr gut im Simulator zu beobachten.

von Andreas (Gast)


Lesenswert?

Wäre nett wenns mal jemand schnell mit ner neueren Version simulieren 
könnte.
Ich arbeite noch mit 11.9.8.
Vielleicht taucht ja das Verhalten da nicht auf.

von Gästlein (Gast)


Lesenswert?

Programmier das mal selbst sauber mit einer ISR.
 Dann hast  Du den Überblick und die Kontrolle und es funktioniert 
immer.

von Gästlein (Gast)


Lesenswert?

Dann mach doch selbst mal eben schnell ein Update auf die aktuelle 
Version, dauert nur 5 Minuten.
Oder ist deine Version geklaut ?

von Klaus D. (kolisson)


Lesenswert?

AAAlllsoooo,
ich weis zwar nicht warum bei dir was nicht funktioniert, kann aber 
mitteilen was bei mir seit vielen jahren perfekt funktioniert.


Hier also die abgewandelte Version deines Programmes:
1
$regfile = "m8def.dat"
2
$crystal = 8000000
3
$hwstack = 100
4
$swstack = 100
5
$framesize = 100
6
$baud = 38400
7
8
----> das muss weg : Declare Sub Serial0charmatch()
9
10
Config Serialin = Buffered , Size = 30 , Bytematch = 13
11
Enable Interrupts
12
13
-----> das kommt neu
14
dim cr_received as byte
15
dim Incoming_data As String * 30
16
17
18
'Hauptschleife
19
Do
20
   
21
if cr_received = 1 then
22
Input Incoming_data Noecho
23
print Incoming_data
24
cr_received = 0
25
end if
26
27
28
Loop
29
End
30
31
Serial0charmatch:
32
Cr_received = 1
33
Return
34
35
36
* das unterhalb dieser Zeile kannst du dann knicken ***********
37
38
39
Sub Serial0charmatch()
40
   Local Incoming_data As String * 35
41
42
   'Daten vom Buffer auslesen
43
   Input Incoming_data Noecho
44
   'Ausgelesene Daten zurück schicken
45
   Print Incoming_data
46
End Sub

Immer bedenken:
ISR Routinen immer kurz halten und erst recht kein Print-Kommando da 
hereinpacken


Gruss Klaus de Lisson

: Bearbeitet durch User
von dorian (Gast)


Lesenswert?

?

wie soll da jemals die ISR "Serial0charmatch:"
angesprungen werden ?

von dorian (Gast)


Lesenswert?

sorry..

die label "SerialXcharmatch" sind bei bascom vordefiniert....

von Klaus D. (kolisson)


Lesenswert?

dorian schrieb:
> ?
>
> wie soll da jemals die ISR "Serial0charmatch:"
> angesprungen werden ?

genauso wie in dem Ursprungsquelltext die Sub Serial0charmatch() 
angesprungen wurde.

Das ist in Bascom intern so declariert und steht in der 
Bedienungsanleitung.

Gruss Klaus de Lisson

von Andreas (Gast)


Lesenswert?

Ok vielen Dank für die Hilfe.

Auch bei Klaus´ Code hängt der Simulator bei mir, sobald meine Eingabe 
länger als die 30 Zeichen ist. Wieder bei Input Incoming_data Noecho.

Ich werde später mal eine neuere Version ausprobieren.

von Klaus D. (kolisson)


Lesenswert?

Andreas schrieb:
> Code hängt der Simulator

Hallo,
zu Simulator kann ich nix sagen, da ich den in all den Jahren noch nie 
benutzt habe. In Hardware funktioniert es aber.

gruss

von Karl H. (kbuchegg)


Lesenswert?

> Heute ist mir aufgefallen, sobald die eingegebenen Zeichen über den UART die 
Zahl bei Size (hier 30) übersteigen

Ist halt immer die Frage, was die Implementierung des Ringbuffers in so 
einem Fall dann macht.
Wird das Zeichen dann nicht mehr im Ringbuffer gespeichert, weil der 
voll ist UND sucht INPUT auf jeden Fall nach dem Abschlusszeichen, dann 
hängt das natürlich.

Ist aber reine Spekulation. Dokumentiert ist in dieser Richtung nichts.

von theanddreas (Gast)


Lesenswert?

Klaus De lisson schrieb:
> zu Simulator kann ich nix sagen, da ich den in all den Jahren noch nie
> benutzt habe. In Hardware funktioniert es aber.

Hm ok nun Version 2.0.7.5 probiert. Immer noch das selbe Problem im 
Simulator. Na ja werds mal mit der Hardware versuchen.

von Andreas (Gast)


Lesenswert?

Karl Heinz schrieb:
> Wird das Zeichen dann nicht mehr im Ringbuffer gespeichert, weil der
> voll ist UND sucht INPUT auf jeden Fall nach dem Abschlusszeichen, dann
> hängt das natürlich.

Ja glaub auch, dass es daran liegt

von Isr (Gast)


Lesenswert?

Mach es Dir selbst, funktioniert garantiert ;-).

Code von Roland Walter:
1
'0011.BAS: Optimierter String-Empfang
2
$Regfile = "2313def.dat"
3
$Crystal = 3686400
4
$Baud    = 9600
5
6
Dim s As String*10 At &H60
7
Dim b(11) As Byte At &H60 Overlay
8
Dim n As Byte
9
10
On URXC OnRxD
11
Enable URXC
12
Enable Interrupts
13
14
Main:
15
  If n > 9 Then
16
    Print s
17
    n = 0
18
  End If
19
Goto Main
20
21
OnRxD:
22
  Incr n
23
  b(n) = UDR
24
Return

: Bearbeitet durch User
von Andreas (Gast)


Lesenswert?

Ja habs jetzt nochmal genauer angeschaut.

Anscheinend handelt es sich doch nicht um einen Ringpuffer. Der Puffer 
wird einfach komplett vollgeschrieben. Kommt das Bytematch Zeichen, wird 
Serial0charmatch aufgerufen, das Zeichen selbst wird jedoch nicht mehr 
in den Puffer geschrieben, da dieser bereits voll ist.

Input versucht jetzt den Puffer bis zum Bytematch Zeichen einzulesen. 
Das steht natürlich nicht drin -> Endlosschleife.

Da sich mein Programm beim Input Aufruf in der ISR Routine befindet, 
bleibt der Controller für immer hängen.

Das Programm von Klaus ruft Input allerdings nicht in der ISR Routine. 
Da Input den Puffer anscheinend zum Teil gelöscht hat, kann dieser 
wieder Zeichen aufnehmen. Kommt jetzt wieder ein Bytematch Zeichen, wird 
dies von Input ausgelesen und bleibt nicht mehr hängen.

Ja trotzdem irgendwie nicht zufriedenstellend.
Muss ich mir was anderes überlegen.

von Klaus D. (kolisson)


Lesenswert?

hier noch ne modifizierte MAIN zum testen:


'Hauptschleife
Do

if cr_received = 1 then
Input Incoming_data Noecho
print Incoming_data

Clear Serialin

cr_received = 0
end if


Loop
End

von Andreas (Gast)


Lesenswert?

Isr schrieb:
> Mach es Dir selbst, funktioniert garantiert ;-).

Danke werd ich morgen ausprobieren.

von Andreas (Gast)


Lesenswert?

Klaus De lisson schrieb:
> hier noch ne modifizierte MAIN zum testen:

Hilft leider auch nix, er bleibt ja schon bei "Input Incoming_data 
Noecho"
hängen. Erst wenn wieder ein Bytematch Zeichen empfangen wurde, gehts 
weiter.
Dann wird der Puffer durch Clear gelöscht, da is er aber schon leer, da 
ihn bereits Input gelöscht hat ;-).

von Klaus D. (kolisson)


Lesenswert?

Andreas schrieb:
> Erst wenn wieder ein Bytematch Zeichen empfangen wurde, gehts
> weiter.

Heeeee ?,

was denkst du denn wofür die Routine entwickelt wurde ?
genau zu diesem Zweck.

Gruss Klaus

von Andreas (Gast)


Lesenswert?

Klaus De lisson schrieb:
> Heeeee ?,

Simuliers doch einfach mal, dann wirst dus feststellen.
Oder lies dir mal meinen Beitrag 06.12.2013 um 22:53 Uhr mal genauer 
durch.

von Andreas (Gast)


Lesenswert?

Hab den Code von Roland Walter mal ein bisschen modifiziert. Jetzt 
funktionierts wies funktionieren soll. Die Routine ist wie diese hier
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Empfangen_.28RX.29 
aufgebaut.

1
$regfile "m644def.dat"
2
$crystal = 4000000
3
$hwstack = 400
4
$swstack = 400
5
$framesize = 400
6
$baud = 9600
7
8
Const Uart_input_max = 10
9
const char_match = 13
10
11
Const Uart_input_max_inc = Uart_input_max + 1
12
13
Dim Input_data As String * 10 At &H600
14
Dim B(uart_input_max_inc) As Byte At &H600 Overlay
15
Dim char_counter As Byte
16
Dim Message_received As Byte
17
18
19
On URXC OnRxD
20
Enable URXC
21
Enable Interrupts
22
23
Do
24
   If Message_received = 1 Then
25
      Message_received = 0
26
      Print Input_data
27
   End If
28
Loop
29
30
Onrxd:
31
    If Message_received = 0 Then
32
      If Udr = Char_match Or Char_counter >= Uart_input_max Then
33
         B(char_counter) = Udr
34
         B(char_counter + 1) = 0
35
         Char_counter = 0
36
         Message_received = 1
37
      Else
38
         B(char_counter) = Udr
39
         Incr Char_counter
40
      End If
41
    End If
42
Return

Zur Erklärung:
Es wird solange eingelesen, bis das char_match Zeichen empfangen wurde 
oder input_data voll ist. Ist input_data voll und noch nicht ausgelesen, 
werden weiterhin empfangene Zeichen einfach verworfen.

Die Adresse der Variablen muss eventuell angepasst werden.

von Isr (Gast)


Lesenswert?

Das freut mich,

das Beispiel von Roland Walter ist sehr strukturiert und die Nutzung von 
Overlays ist elegant.
Serielle Kommunikation ist so aufgebaut immer stabil.

von Andreas (Gast)


Angehängte Dateien:

Lesenswert?

Oh hab was vergessen:
Zeile "Dim Input_data As String * 10 At &H600"
muss durch "Dim Input_data As String * Uart_input_max At &H600"
ersetzt werden.

fertiger Code im Anhang

Gruß Andreas

von Isr (Gast)


Lesenswert?

Du solltest möglichst jede Verarbeitung aus der ISR rausnehmen und mit 
Flags arbeiten.
Den Verarbeitungsteil machst du dann im Hauptprogramm, soweit das geht.

von Andreas (Gast)


Lesenswert?

Isr schrieb:
> Du solltest möglichst jede Verarbeitung aus der ISR rausnehmen und mit
> Flags arbeiten.

Ja stimmt hab ich schon öfter gehört.

Habs jetzt in die ISR Routine, weils im AVR-GCC Tutorial auch so gemacht 
wird. In der Arduino Bibliothek siehts genauso aus.

Außerdem gehts bei meinem Projekt nicht so zeitkritisch zur Sache.
Ich finds so einfach übersichtlicher ;-)

Wer will kann ja in der ISR nur ein Flag für den Empfang eines Zeichens 
setzen und den String dann in der Main zusammenfügen.

von Isr (Gast)


Lesenswert?

Andreas schrieb:
> Isr schrieb:
>> Du solltest möglichst jede Verarbeitung aus der ISR rausnehmen und mit
>> Flags arbeiten.
>
> Ja stimmt hab ich schon öfter gehört.

Warum wohl;-)
>
> Habs jetzt in die ISR Routine, weils im AVR-GCC Tutorial auch so gemacht
> wird. In der Arduino Bibliothek siehts genauso aus.

Das bedeutet nicht, dass es nicht auch besser geht.

>
> Außerdem gehts bei meinem Projekt nicht so zeitkritisch zur Sache.
> Ich finds so einfach übersichtlicher ;-)

Kleiner Denkfehler;-):

auf die Geschwindigkeit der eingehenden Zeichen hast Du keinen Einfluss, 
außer über die Baudrate.

Deine Mainroutine wird eh vom Interrupt zum Schweigen gebracht.
Wenn nun aber die Zeichen so schnell eintrudeln, dass die ISR beim 
nächsten Zeichen noch gar nicht fertig ist, dann funktioniert das nicht 
mehr.
Dreh die Baudrate hoch und irgendwann läuft Dein , nicht vorhandener 
(hardwareabhängig), Puffer über.
Vielleicht geht das trotzdem noch bei max. Baudrate ( rechne das mal 
nach, schöne kleine Übung).

Du wirst erkennen, dass Du den Kollegen Zufall zu sehr strapazierst.
Machs sauber und professionell, so wie es sich für den Ingenieur auch 
gehört.

>
> Wer will kann ja in der ISR nur ein Flag für den Empfang eines Zeichens
> setzen und den String dann in der Main zusammenfügen.

Mit " Wollen" hat das nichts zu tun, sondern mit funktionierendem 
Code;-).

Mach fertig und zeigs uns, dafür haben wir Dich schließlich auf die Spur 
gebracht.

von Klaus D. (kolisson)


Lesenswert?

Isr schrieb:
> Mach fertig und zeigs uns, dafür haben wir Dich schließlich auf die Spur
> gebracht.

da ist doch mal ein gutes Wort zum Sonntag, wie es sich gehört.
Daumen hoch!

Gruss Klaus de Lisson

von Isr (Gast)


Lesenswert?

Amen.....

Möge das Schäflein uns dankbar sein.

von Andreas (Gast)


Lesenswert?

Isr schrieb:
> Kleiner Denkfehler;-):

Eigentlich dachte ich an was anderes mit Zeitkritisch:
In den Interrupts sollte man ja nur Flags setzen, da ein längerer 
Aufenthalt in der ISR andere Interrupts blockiert.

Auch wenn sich der Controller bei mir länger in der ISR Onrxd befindet 
macht das nix, da es keine anderen wichtigen Interrupts gibt.


> auf die Geschwindigkeit der eingehenden Zeichen hast Du keinen Einfluss,
> außer über die Baudrate.

Stimmt allerdings.

> Deine Mainroutine wird eh vom Interrupt zum Schweigen gebracht.
> Wenn nun aber die Zeichen so schnell eintrudeln, dass die ISR beim
> nächsten Zeichen noch gar nicht fertig ist, dann funktioniert das nicht
> mehr.
> Dreh die Baudrate hoch und irgendwann läuft Dein , nicht vorhandener
> (hardwareabhängig), Puffer über.
> Vielleicht geht das trotzdem noch bei max. Baudrate ( rechne das mal
> nach, schöne kleine Übung).

Ja kann gut passieren.
Wenn der Controller zu langsam ist um die eingehenden Zeichen zu 
verarbeiten, dann hilfts aber auch nix, wenn sich der Code zum Auswerten 
in der Main befindet. Es werden in der ISR zwar die Flags für ein neues 
Zeichen gesetzt aber die Auswertung ist zu langsam um diese zu 
verarbeiten.

von isr2 (Gast)


Lesenswert?

wie du meinst

von Andreas (Gast)


Angehängte Dateien:

Lesenswert?

Aber ich hab doch noch was.

Ich hoffe jetzt ist jeder Glücklich :-)

Gruß Andreas

von sokrates (Gast)


Lesenswert?

Andreas schrieb:
> Ja kann gut passieren.
> Wenn der Controller zu langsam ist um die eingehenden Zeichen zu
> verarbeiten, dann hilfts aber auch nix, wenn sich der Code zum Auswerten
> in der Main befindet. Es werden in der ISR zwar die Flags für ein neues
> Zeichen gesetzt aber die Auswertung ist zu langsam um diese zu
> verarbeiten.

Du hast das noch nicht so ganz verstanden:

Es hat niemand gesagt in der ISR NUR Flags zu setzen.
Die muss halt so knackig kurz sein, dass dein Ziel immer erreicht wird.
Du musst es so bauen, das deine eingehenden Zeichen nicht verloren gehen 
können, also auf alle Fälle in einem Puffer landen (Array/String)...

In der ISR kannst Du durchaus nach dem Motto alter string = alter string 
+ neues Zeichen vorgehen.

Damit hast du doch alles erreicht.
In der Hauptschleife kannst Du in Ruhe all das tun was getan werden soll 
du verlierst keine Zeichen.
Denk da nochmal gaanz in Ruhe und logisch drüber nach ;-)

von Andreas (Gast)


Lesenswert?

sokrates schrieb:
> Es hat niemand gesagt in der ISR NUR Flags zu setzen.

Na ja aber "möglichst nur" hieß es.

> Die muss halt so knackig kurz sein, dass dein Ziel immer erreicht wird.
> Du musst es so bauen, das deine eingehenden Zeichen nicht verloren gehen
> können, also auf alle Fälle in einem Puffer landen (Array/String)...

Meine Interruptroutine aus dem ersten Beispiel ist für mich kurz und 
knackig genug, damit bei 9600 Baud keine Zeichen verloren gehen. Mehr 
wollt ich eigentlich nicht. Amen.

Wers besser kann, der soll doch bitte einfach den Code posten.

Trotzdem Danke

von isr2 (Gast)


Lesenswert?

Andreas schrieb:
> Aber ich hab doch noch was.
>
> Ich hoffe jetzt ist jeder Glücklich :-)
>
> Gruß Andreas

ANDREAS..
.. es geht doch garnicht darum das wir glücklich sind.
... wir waren es doch zuvor schon
.... du warst der, der unglücklich war weil deine Software nicht funzte


. nun scheinst du glücklich zu sein und alles ist gut.

isr2

von bwler (Gast)


Lesenswert?

..denkt wie ein Kaufmann, nicht wie ein Techniker .........

von Amüsierter (Gast)


Lesenswert?

Was von dem, das C normalerweise von seinen Fans angekreidet wird, hat 
BASCOM hier eigentlich nicht gezeigt? Overlay vs. union; AT &H123, huch 
das ist ja ASM; dazu passt auch $hwstack, $swstack, $framesize, darum 
kümmert sich bei mir GCC und ld; simpler Array-Überflauf a la C führt 
zum Crash; Bibliothek von Funktionen, die man im Zweifel besser nicht 
nutzt;
Für mich ist das nicht einfacher als C und wenn's nicht reicht, ich sag 
nur:
1
Messwert = ( ( a & 0xfc ) / 2 ) * BASE_RATIO;
Wie schreibt man das nochmal in BASCOM?
Ja Timm Thaler, das ist in BASCOM nicht unüblich, sondern unmöglich.

von sepp (Gast)


Lesenswert?

Ja ja der einzige Vorteil von Bascom sind die vorhandenen Bibliotheken 
und der Zugriff auf einzelne Pins ohne Bitmanipulation.

Die Leistungsfähigkeit des Compilers lässt teilweise doch zu wünschen 
übrig. Fehlermeldungen sind oft nichtssagend.

von sokrates (Gast)


Lesenswert?

?

Wo ist denn hier ein Problem aufgetreten welches sprachabhängig ist?
Bleib mal bei dem Beispiel ohne in Allgemeingeschwafel zu verfallen.

Das ist doch ein schönes Beispiel welches zeigt, das die Probleme oft im 
fehlenden Verständnis genereller Dinge liegt.

von Amüsierter (Gast)


Lesenswert?

Eigentlich hatte ich an einigen Beispielen aufgezeigt, daß dieser 
COMPILER, ich hatte nichts zur Sprache geschrieben, einiges an Klippen 
liefert, die seine Anhänger normalerweise C zuschreiben. Aber das ist 
dann ja böses BASCOM Bashing, weil nicht sein kann, was nicht sein darf.

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.