Forum: Mikrocontroller und Digitale Elektronik MIDI-Frage


von Mathias (Gast)


Lesenswert?

Hallo!

Blöde Frage, aber ich möchte mit einem midicontroller einen ATmega16
ansteuern und dabei wird durch die 128 midiprogramme geschalten, aber
wie sieht ein MIDI-Signal in dem Fall aus, find keine passende
Literatur dazu und brings selber auch nicht hin

danke im voraus!!

grüße
mathias

von Ingo Henze (Gast)


Lesenswert?

Hardwareseitig bietet sich die Verwendung eines UARTs an, der dann mit
31250 bps, 1 Startbit, 8 Datenbits, 1 Stopbit initilisiert werden muß.
Standardkonform ist für den MIDI-Eingang unbedingt ein Optokoppler
vorzusehen, die von der MIDI-Organistion empfohlene Beschaltung findest
Du hier:
http://www.midi.org/about-midi/electrical.shtml

Softwareseitig willst Du, wenn ich das richtig verstanden habe,
Programmwechsel-Befehle verarbeiten.
Dafür ist im MIDI-Standard der 2Byte-Befehl "Program Change"
vorgesehen (hex):
 Cn pp
wobei n die Nummer des des MIDI-Kanals ist (0 - F, also 0 bis 16) und
pp das gewünschte Programm (0 - 7F, also 0 bis 127)

Bsp.:
 C0 28
Schaltet für Kanal 0 das Instrument 41 ein (z.B. Violine)

Weitere Infos auch bei MIDI-Org:
http://www.midi.org/about-midi/table1.shtml

Gruß
Ingo

von Ingo Henze (Gast)


Lesenswert?

Oops,
MIDI-Kanalnummer natürlich nur von 0 bis 15 :-)

von Mathias (Gast)


Lesenswert?

Hallo!

Danke vielmals! Opto usw. habe ich alles, das mit dem UART ist auch
klar, habe nur nicht gewusst, wie das Signal aussieht! Aber danke,
jetzt weiß ich auf alle Fälle mehr!!

Grüße
Mathias

von Mathias (Gast)


Lesenswert?

Hallo!!

Hab das jetzt so probiert, aber irgendwie funktioniert das so nicht,
kannst du oder jemand mir genauer beschreiben wie das geht? als
optokoppler verwende ich einen PC900, wie kann ich MIDI-Programmwechsel
auf dem µC empfangen bzw. verwerten?? Ich empfange zwar Daten mit dem µC
jedoch kommt da immer was falsches daher bzw. bewirken alle Taster das
selbe...

Grüße
Mathias

von Rahul (Gast)


Lesenswert?

Poste doch bitte den Programmcode! Höchstwahrscheinlich liegt dort der
Fehler.

von Ingo Henze (Gast)


Lesenswert?

Naja, auch ohne Programmcode möchte ich schon man ganz allgemein
versuchen zu helfen.

Zunächst wäre natürlich wichtig zu wissen, was der MIDI-Controller denn
tatsächlich für Daten sendet. Das es der MIDI-Befehl "Program Change"
ist, habe ich nur vermutet, weil da steht "...durch die 128
midiprogramme geschalten...".
Falls Du MS-Windows hast, und irgendwie die Möglichkeit ein MIDI-Gerät
an den PC anzuschließen, könntest Du Dir die gesendeten Daten erstmal
mit einem Programm auf dem PC anschauen (z.B. MidiOx,
http://www.midiox.com)

Außerdem gibt es noch zwei "Gemeinheiten" zu beachten.

Zum einen Senden manche Geräte System-Realtime-Messages, meist das
sogenannte "Active Sensing" (Hex FE). Es stellt die einzige
Möglichkeit dar, festzustellen, ob überhaupt eine MIDI-Vebindung zu
einem Gerät besteht.
Diese wird alle paar Millisekunden gesendet und kann zu jedem
beliebigen Zeitpunkt aufreten, also auch zwichen dem Befehlsbyte und
dem Datenbyte (für mein obiges Beispiel könnte das bedeuten: C0 FE
28).
Das heißt, man kann sich nicht darauf verlassen, das nach dem
Statusbyte auch direkt das Datenbyte folgt.

Zum anderen gibt es den sogenannten "Running Status".
Hier wird zur Einsparung von Übertragungskapazität angenommen, das nach
einem Statusbyte (also z.B. C0) beliebig viele Daten gesendet werden
können, ohne das Satusbyte jedesmal wiederholen zu müssen.
Für das Beispiel bedeutet das, der MIDI-Controller sendet nur einmal
das Statusbyte C0, und dann nur noch Datenbytes (0 bis 7F).
Was für den Musikbereich in diesem Fall sicher nicht sinnvol ist (
ständig ein anderes Instrument einschalten, aber nie eine Note spielen
:-), kann bei Steuerungsaufgaben durchaus sinnvoll sein.

Gruß
Ingo

von Ingo Henze (Gast)


Angehängte Dateien:

Lesenswert?

So,
ich hab mal aus dem "AVR-Tutorial - 6. Das UART" das
interruptgetriebene Empfangsbeispiel genommen und leicht angepaßt (im
Anhang)
Oben muß natürlich
  .equ CLOCK = 4000000
an die entsprechenden Gegebenheiten angepaßt werden.

Außer dem Löschen der von mir hinzugenommen beiden Register R17 und R18
 (Status und Daten) stecken die Erweiterungen alle in der
Interruptroutine.
Ich hoffe, daß man mit Hilfe der Kommentare versteht, was da gemacht
wird :-)

Vielleicht kurz in Worten:
Zunächst wird zwischen Daten- und Statusbyte unterschieden (alles
größer/gleich 0x80 ist ein Statusbyte).
Falls es Daten sind, wird geprüft, ob der aktuelle Status auch dem
gewünschten entspricht, wenn das so ist, wird das Datenbyte gespeichert
und "verarbeitet".
Im Falle eines Statusbytes werden alle System-Realtime-Messages
(größer/gleich 0xF8) verworfen, ansonsten wird er Status neu gesetzt.

Syntaktisch ist das für den AVR-Assembler (Studio) so richtig, ich habe
es allerdings inhaltlich nicht am "lebende Objekt" getestet.

Gruß
Ingo

von Mathias (Gast)


Lesenswert?

Hoi!

Danke erstmal!

Hab Windows und hab mir gleich Midiox heruntergeladen, um mir die Daten
von meinem Midi-Controller anzuschauen. Er sendet wirklich FEs vom
Active Sensing, außerdem schickt er vor und nach jedem Midibefehl einen
Sysex Buffer mit 6 Byte, der Midibefehl selber sieht dann so aus, wie du
es mir erklärt hast also zB C0 2C oder so.

Also mein Midicontroller schaltet eben nur durch die Midiprogramme(am
PC wären das die verschiedenen Instrumente), eine Note spielt er
natürlich nicht, normalerweise verwende ich ihn um bei meinem
Gitarrenverstärker und Effektgeräten durch die Kanäle zu schalten(also
die 128 Midiprogramme) und jetzt versuche ich bei meinem
Selbstbau-Verstärker das selbe, indem ich eine Schaltung mit µC
aufbaue, die sich durch mein Midipedal steuern lässt und bei meinem
Verstärker die Kanäle umschaltet. Zweiteres ist kein Problem, nur die
Midifunktionalität bekomm ich nicht hin.
Außerdem muss ich erwähnen, dass ich auf diesem Gebiet ein absoluter
Anfänger bin, deshalb verstehe ich noch so einiges nicht!

Die Teile des Programmcodes, die für das Midi zuständig wären sind
folgende(bin Anfänger, deswegen fehlt da sicher einiges ;):

.equ CLOCK = 11000000
.equ BAUD = 31250
.equ UBRRVAL = CLOCK/(BAUD*16)-1


        ldi r16, LOW(UBRRVAL)
        out UBRRL, r16
        ldi r16, HIGH(UBRRVAL)
        out UBRRH, r16

  ldi r16, (1<<URSEL)|(3<<UCSZ0)
        out UCSRC, r16

  sbi UCSRB, RXEN
  in temp, UDR
...

Ich hab mal die paar Schnipsel zusammenkopiert, die ich
zusammengebracht habe, aber mehr schaffe ich nicht ;)

Grüße und Danke
Mathias

von Mathias (Gast)


Lesenswert?

Hallo!

Wow, danke, dein Beispiel trifft den Nagel wirklich auf den Kopf!!!
Danke!! Werde mich jetzt noch weiter damit befassen und bei Fragen
einfach wieder hier melden!!

Danke vielmals
Grüße
Mathias

von Ingo Henze (Gast)


Lesenswert?

Ich denke mal, das Du die Sysex-Daten auch ignorieren kannst.
So wie sich das jetzt darstellt, brauchst Du wiklich nur auf "Program
Change" zu reagieren, so wie das mein kleines midi_rx.asm -Programm
weiter oben macht (hoffe ich mal, wie gesagt, ist nicht getestet :).

Die Frage ist, was der Mikrocontroller noch so erledigen soll.
Eventuell ist dann auch eine UART-Routine mit FIFO (Ringpuffer)
angesagt, und die eigentliche Verarbeitung in die Main-Loop
umzulagern.

Gruß
Ingo

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.