Forum: Mikrocontroller und Digitale Elektronik Midi Empfangen mittels Atmega 8 und Bascom


von Derek W. (dmun)


Lesenswert?

Hallo zusammen,

Ich habe ein kleines Problem mit dem Empfang von MIDI Daten über einen 
Atmega 8 mit Bascom
Gegeben: Atmega 8 und Midi-In auf PD0 über Opto nach MIDI-Standard. 
Übertragung 31250 Baud wie vorgeschrieben.

In Bascom so konfiguriert:
$regfile = "m168def.dat"
$hwstack = 32
$swstack = 10
$framesize = 40
$PROG &HFF , &HCF , &HDF , &HF9
'$crystal = 7372800
$crystal = 8000000
$baud = 31250

Nun sende ich von einer Midi-Schnittstelle (am PC) ein paar Bytes an den 
µC welcher mir den Inhalt der Bytes dann über 8 LEDs anzeigen soll:
Sende (Hx): 01 02 03 04 05 06

Aber es werden aber nur die 01 02 und 03 UND das letzte Byte angezeigt, 
ausgegeben.
Sende ich:
01 02 03 04 05 06 07 08 09 0A
dann wird ebenfalls wieder 01, 02 und 03 und das letzte Byte angezeigt. 
Alles dazwischen scheint nicht vorhanden zu sein.

Um ein Problem mit dem MIDI-Interface aus zu schliessen habe ich einen 
zweiten µC genommen welcher auch senden kann (gleicher µC, gleicher 
Quarz etc) und siehe da, wenn ich die einzelnen Bytes mittels printbin 
01, printbin 02 ... raus gebe habe ich den gleichen Effekt. Die ersten 
drei Bytes und das letzte werden angezeigt, was dazwischen liegt nicht. 
MIDI-Interface scheidet also aus.

Wenn ich jetzt aber beim Sender das Programm erweitere und nach jedem 
printbin ein waitms 1000 schreibe, also so:

printbin 01
waitms 1000
printbin 02
waitms 1000
....
dann bekomme ich alle Bytes übertragen und auch vollständig und korrekt 
angezeigt.

Nun habe ich auf Empfängerseite seite ebenfalls ein waitms 1000 mit rein 
genommen:
   If Ischarwaiting() = 1 Then
       bRx = WaitKey()
       waitms 1000
   end if

Aber ohne Erfolg, bringt nichts, gleiches fehlerhaftes Verhalten.

Hat jemand eine Idee was ursächlich sein könnte für das Problem ? 
Timing, Baud, Quarz, Fuse Bits (Divide by 8 is disabled, CLOCK Output 
disabled und 001111 Ext. Cyrstal Osc gesetzt) ?
Habe sowohl 7,372800 MHz als 8 MHz Quarze versucht mit dem identischen 
Ergebnis.
Was mir noch aufgefallen ist: wenn ich Config Serialin = Buffered , Size 
= 20 setze, dann geht auch nichts.

Und im Moment habe ich keine Idee wo ich noch weiter suchen oder 
schrauben kann...

Grüße, dmun

von Weingut P. (weinbauer)


Lesenswert?

die Unart buffered laufen lassen und ischarwaiting kann sich beißen ... 
hatt ich jedenfalls mal.

also weitms einfügen ist generell Müll. Der Controller macht dann 
einfach garnichts.

Also was die Behandlung der UART in Bscom angeht kann ich nur empfehlen 
die Highlevelbefehle von Bascom zu meiden.
Nen Sendepuffer und UTXC-Interrupt sowie URXC-Interrupt und 
Empfangspuffer sind nicht zu schwierig.

Dann packst Du Deinen Empfang in den URXC-Interrupt und die Anzeige in 
die Mainloop

: Bearbeitet durch User
von Jacko (Gast)


Lesenswert?

So ganz klar ist das Problem noch nicht beschrieben:

Sendet der PC die 8 Byte hintereinanderweg? Dann folgen
die Bytes einander mit 0,32 ms Abstand. - So schnell kann man
nicht gucken! - Aber wie siehst du die ersten 3 Byte?

Mit Sendepause von 1000 ms hat man natürlich eine Sekunde
Zeit jedes Byte zu sehen.

Wofür soll denn die Pause beim Empfänger dienen?

von Derek W. (dmun)


Lesenswert?

Hallo,

ja, de Bytes werden hinter einander gesendet und für die LEDs dann eine 
Zeit X ein und dann wieder ausgeschaltet. Somit kann man sehen was 
gesendet wird bzw. der Inhalt der Bytes.
Beispiel:

      If Ischarwaiting() = 1 Then
       bRx = WaitKey()
       Out1 = bRx.0
       Out2 = bRx.1
       Out3 = bRx.2
       Out4 = bRx.3
       Out5 = bRx.4
       Out6 = bRx.5
       Out7 = bRx.6
       Out8 = bRx.7
       waitms 500
       Out1 = 0
       Out2 = 0
       Out3 = 0
       Out4 = 0
       Out5 = 0
       Out6 = 0
       Out7 = 0
       Out8 = 0
       waitms 500
      end if

Es ist ganz egal ob es in Summe 8 Byte oder 4 Byte oder 12 Byte sind. 
das Muster ist immer identisch: die ersten drei Bytes und das Letzte 
Byte werden angezeigt und das ist im Moment nicht nachvollziehbar bzw. 
unlogisch.

Grüße dmun

von Clemens L. (c_l)


Lesenswert?

Probier das ganze mal komplett ohne Warten, mit einer LED pro Wert:
1
If Ischarwaiting() = 1 Then
2
    bRx = WaitKey()
3
    Select Case bRx
4
      Case 1:  Out1 = 1
5
      Case 2:  Out2 = 1
6
      Case 3:  Out3 = 1
7
      Case 4:  Out4 = 1
8
      Case 5:  Out5 = 1
9
      Case 6:  Out6 = 1
10
      Case 7:  Out7 = 1
11
      Case 8:  Out8 = 1
12
    End Select
13
End If

von Alex D. (allu)


Lesenswert?

Derek W. schrieb:
> If Ischarwaiting() = 1 Then
>        bRx = WaitKey()
>        waitms 1000
> end if

Wieso "WaitKey()", mit "If Ischarwaiting() = 1 Then" wird abgefragt ob 
ein Zeichen vom UART abgeholt werden kann.

Derek W. schrieb:
> ja, de Bytes werden hinter einander gesendet

Alle Waits müssen raus, ansonsten kann der UART sowas nicht empfangen. 
Die empfangenen Bytes in einem Array speichern, z.B. mit 16 Stellen.

Jacko schrieb:
> Sendet der PC die 8 Byte hintereinanderweg? Dann folgen
> die Bytes einander mit 0,32 ms Abstand.


$hwstack = 64
Dim Empfang(16) as Byte

Config Com1 = 31250 , Synchrone = 0 , Parity = None , Stopbits = 1 , 
Databits = 8 , Clockpol = 0
index = 1

Do
  If Ischarwaiting() = 1 Then    ' Zeichen lesen
               Empfang(index) = Inkey()       ' Byte aus dem Uart holen
               incr index
               if index = 17 then index = 1
  End If

Ein Wait von 100µsec wäre hier noch als Zählschritt für einen 
Anzeigetimer zulässig. Jetzt nacheinander die neuen Bytes aus dem Array 
holen und zum Beispiel für x mal 100µsec anzeigen.

loop

Besser wäre die Verwendung des CTC-Timers für die Anzeigezeiten.

Gruß  Alex

von Derek W. (dmun)


Lesenswert?

So, jetzt aber.
Habe jetzt das Programm nach dem $baud... um folgende zwei Zeilen 
ergänzt

$baud = 31250
Config Serialin = Buffered , Size = 10
Enable Interrupts

und nun tut es wie es soll. Verstehe nicht wirklich wieso in diesem Fall 
noch Enable Interrupts gesetzt werden muss, aber so ist es.

@Alex: die Waits sind nur drin gewesen um die Anzeige sichtbar zu machen 
und WaitKey oder InKey ist meiner Meinung nach dem IsCharWaiting() egal, 
würde es fehlen, dann würde die Sache anders aussehen.

Aber jetzt geht alles wie es soll und ich kann das eigentliche Programm 
umsetzen.

Danke und Grüße dmun

von Jacko (Gast)


Lesenswert?

So ganz verstehe ich noch nicht, wie du alle 3 ersten Bytes
sehen kannst. AVR-BASIC ist nicht so mein Metier, wahrscheinlich
hat man da öfter solche Überraschungen...
Es liegt vielleicht am Buffering, dass nicht so richtig klappt,
wenn mehr als 3 Byte kommen. Letztendlich wird das letzte Byte
angezeigt. OK.

Andererseits - willst du MIDI machen?, oder MIDI-Bytes
angucken?

Wer MIDI für Musik nutzen will, kann DELAY und WAIT überhaupt nicht
brauchen: Die Instrumente müssen SOFORT auf die Befehle reagieren,
sonst spielt ein Instrument ein paar Sekunden später, als das andere...

Wer MIDI parallel zum Musikablauf sichtbar machen will, muss mehr,
als 8 LEDs nehmen!
Selbst ein Bildschirm mit 25 Zeilen / 80 Zeichen ist in 0,64 s
vollgeschrieben, wenn die Musik richtig abgeht...

Aber ERKENNEN kann man in 0,64 s auch NICHT viel...

von Kurt B. (kurt-b)


Lesenswert?

Derek W. schrieb:

> Was mir noch aufgefallen ist: wenn ich Config Serialin = Buffered , Size
> = 20 setze, dann geht auch nichts.


Enable INTERRUPT setzt den Pufferbetrieb in Gang


 Kurt

: Bearbeitet durch User
von Stromverdichter (Gast)


Lesenswert?

Derek W. schrieb:
> Um ein Problem mit dem MIDI-Interface aus zu schliessen habe ich einen
> zweiten µC genommen welcher auch senden kann (gleicher µC, gleicher
> Quarz etc) und siehe da, wenn ich die einzelnen Bytes mittels printbin
> 01, printbin 02 ... raus gebe habe ich den gleichen Effekt. Die ersten
> drei Bytes und das letzte werden angezeigt, was dazwischen liegt nicht.
> MIDI-Interface scheidet also aus.

Hallo Derek,
bei solchen Gelegenheiten bin ich froh, dass ich über ein Oszilloskop 
oder einen Logic-Aanlyzer verfügen kann. Das würde dir bei deiner 
Fehleranalyse sehr helfen. Du könntest auch die genauen zeitlichen 
Verläufe überwachen. Ich hatte damals nicht bedacht, dass meine 
Midi-Signale invertiert ausgegeben wurden. Der LA hatte meinen Fehler 
dann offenbart.

von Jacko (Gast)


Lesenswert?

Wenn das erste und letzte Byte richtig angezeigt werden, ist
Invertierung wohl nicht das Problem.

Logic Analyzer und Scope würden auch nur zeigen, dass da kein
passendes Konzept für MIDI-Übertragung vorliegt. Und LESEN muss
man, was Logic Analyzer und Scope liefern, auch können...


Also:  Derek White (dmun) - was willst du eigentlich machen?

von Derek W. (dmun)


Lesenswert?

Guten Morgen,

alles gut, Leute. Die LEDs dienten nur zur Anzeige der übertragenen 
Bytes um zu sehen was kommt und was nicht.
Hat mit dem eigentlichen Programm nichts zu tun, welches auch 
zwischenzeitlich fast fertig ist und jetzt genau das macht, was erwartet 
wird.

Grüße dmun

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.