Forum: Mikrocontroller und Digitale Elektronik MIDI Daten senden?


von Sebastian (Gast)


Lesenswert?

Hallo,

ich möchte ganz einfach ein paar MIDI-Daten an ein Keyboard senden. 
Leider komme ic nicht zum Ziel. Vielleicht bin ich auch schon ein wenig 
betriebsblind -- so dass der Fehler ganz nah liegen könnte.

Ich habe Wahlweise einen ATmega8 bzw. einen ATmega8535 mit je 6MHz.
Compiler: AVR-Studio mit GCC/WinAVR

Mein Quellcode:


#include <avr/io.h>
#include <inttypes.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

#define F_CPU       6000000UL
#define BAUD        31250UL
#define UBRR_BAUD   ((F_CPU/(16UL*BAUD))-1)


// USART initialisieren
void uart_init(void)
{
    // Baudrate einstellen (Normaler Modus)
    UBRRH = (uint8_t) (UBRR_BAUD>>8);
    UBRRL = (uint8_t) (UBRR_BAUD);

    // Aktivieren vom transmitter
    UCSRB = (1<<TXEN);

    // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}

int main(void)
{
    uint8_t buffer;

    // USART initialisieren
    uart_init();

    while (1)
    {
        // Warten bis der Sendepuffer frei ist
        while ( !( UCSRA & (1<<UDRE)) );
        // Daten in den Puffer schreiben und damit senden
        buffer = 0x91;
        UDR = buffer ;
        _delay_ms(10);

        // Warten bis der Sendepuffer frei ist
        while ( !( UCSRA & (1<<UDRE)) );
        // Daten in den Puffer schreiben und damit senden
        buffer = 0x3C;
        UDR = buffer ;
        _delay_ms(10);

        // Warten bis der Sendepuffer frei ist
        while ( !( UCSRA & (1<<UDRE)) );
        // Daten in den Puffer schreiben und damit senden
        buffer = 0x7F;
        UDR = buffer ;
        _delay_ms(10);
    }
}



PD1(TXD) --> Pin 4 der MIDI Buchse
+5V      --> Pin 4 der MIDI Buchse

jeweils über 220R

Auf dem Oszilloskop kann man die einzelnen gesetzten Bits auszähen. Es 
sieht auf dem ersten und zweiten Blick nicht verkehrt aus.

Im Moment lese ich die gesendeten Daten mit einem MIDI-USB-Übertrager 
aus. Leider erhalte ich nur Müll, obwohl die EmpfangsLED leuchtet.

Kann mir jemand sagen, was ich falsch gemacht habe??

Vielen Dank und viele Grüße

von Sebastian (Gast)


Lesenswert?

Entschuldigung, ein kleiner Fehler. Es muss natürlich so sein:

PD1(TXD) --> Pin 5 der MIDI Buchse
+5V         --> Pin 4 der MIDI Buchse

von C. H. (_ch_)


Lesenswert?

Hallo,

die Fuses für externen Quarz sind gesetzt?

Gruß
Christian

von Sebastian (Gast)


Lesenswert?

Japp - zusätzlich durch Oszi verifiziert.
--> Es ergibt sich eine Bitbreite von ca. 32µs.

Gruß Sebastian

von Mano Wee (Gast)


Lesenswert?

Wieso wartest Du eigentlich immer 10ms ? Du könntest doch in der Zeit 
schon längst wieder senden.

von C. H. (_ch_)


Lesenswert?

Sende doch mal nur ein einzelnes Byte und schaue was der 
MIDI-Usb-Übertrager macht.
So spontan kann ich auch keinen Fehler im Code finden.

Gruß
Christian

von Sebastian (Gast)


Lesenswert?

Hallo, ich habe immer 10ms dazwischen gesetzt, damit man auf dem Oszi 
die Bits besser auszählen kann. Auch wenn ich nur 1 Byte sende wird nur 
Müll erkannt.

Der USB-Umsetzer ist soweit ich das beurteilen kann in Ordnung, da das 
Einspeisen von anderen MIDI-Quellen problemlos funktioniert.

Gruss
Sebastian

von cyberlink (Gast)


Lesenswert?

Hallo, ich würde gerne mit Bascom Midi-Befehle senden.
soweit ich das kapiert habe, hat midi eine baudrate von 3125 Baud. 
stimmt das?

mein code:
------------------------------------------------------------------------ 
-----
$regfile = "m8def.dat"
$crystal = "8000000"
Baud = 3125

Do
  print chr(144) ; chr(60) ; chr(64) 'Taste C drücken (Kanal 0)
  print chr(128) ; chr(60) ; chr(64) 'Taste C loslassen (Kanal 0)
  wait 1
Loop
End
------------------------------------------------------------------------ 
-----
quelle der midi-codes: 
http://web.archive.org/web/20071005165328/www.borg.com/~jglatt/tech/midispec/noteon.htm

funktioniert der so?

mfg cyberlink

von Mano Wee (Gast)


Lesenswert?

@ cyberlink

>Hallo, ich würde gerne mit Bascom Midi-Befehle senden.
>soweit ich das kapiert habe, hat midi eine baudrate von 3125 Baud.
>stimmt das?

Nicht ganz. Sie beträgt 31,25 kBauds, so wie es oben steht.

von Stefan (Gast)


Lesenswert?

>hat midi eine baudrate von 3125 Baud.
Wo hast du diese Info her ?

Und überlege Dir mal wie lange die Taste C in Deiner Schleife in etwa 
gedrückt bleibt.

von Sebastian (Gast)


Lesenswert?

Hallo, erstaunlicher Weise funktioniert die Lösung mit BASCOM (Baud = 
31250).


Daraus schlussfolgere ich, dass meine Peripherie und Pinbelegung richtig 
sind.

Dann kann ja nur noch mein Quellcode falsch sein...

Gruß
Sebastian

von Mano Wee (Gast)


Lesenswert?

@ Sebastian

Die Fragen kann ich mir wahrscheinlich sparen: ohne die beiden ersten 
_delay_ms(10) hast Du es sicher auch schon probiert, oder?

von Sebastian (Gast)


Lesenswert?

Japp, ohne gehts auch nit.
Die Zeiten dienen nur zum besseren anschauen auf dem Oszi.

Gruß

von Dussel (Gast)


Lesenswert?

Das ist ein komisches Problem. Mir fällt auf, dass das BASCOM Beispiel 
den Kanal 0 benutzt, während du im C Beispiel Kanal 1 hast. Kann es 
sein, dass das Keyboard auf Monophonie eingestellt ist? Meine andere 
Idee ist, dass vielleicht der Ton einen langsamen Attack hat und du 
deshalb nichts hörst, weil der Ton in Sekundenbruchteilen wieder neu 
startet.

von cyberlink (Gast)


Lesenswert?

Hallo,
da jetzt mein quellcode fertig ist (mini-synthesizer mit tastern) würde 
ich mich jetzt mal an den Anschluss meines Keyboards machen. Also dass 
der AVR MIDI-Daten sendet und das Keyboard sie über den MIDI-IN Port 
empfängt. Auf wikipedia hab ich folgende Anschlussbelegung gefunden:
http://de.wikipedia.org/wiki/Bild:StandardMIDIInterface.gif

Diese ist aber offensichtlich für den Gameport, der sicher wieder einen 
anderen Signalpegel hat. Midi hat ja einen Signalpegel von 5 Volt (0) 
oder 0 Volt (1). Das ist genau der UART Pegel des AVR, nur negativ.

Wie bekommt man so etwas am einfachsten (kleiner Bauteileaufwand, 
Bastelkistenteile) hin? Vielleicht mit zwei Optokopplern?
Das IC in der Wikipediaschaltung (falls das mit dem AVR funktionieren 
würde) müsste ich nämlich erst bestellen.

Ich hoffe, ihr könnt mir helfen

mfg
cyberlink

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

AVR TXD über 220 Ohm an die MIDI-Buchse (Ausgang) und den anderen Pol 
der MIDI-Buchse über 220 Ohm an Vcc. Vom externen Keyboard an die 
MIDI-Buchse (Eingang) über 220 Ohm an die Anode der LED eines 
Optokopplers (CNY17/1 reicht) und deren Kathode zum anderen Pol der 
Buchse, dessen Emitter an Masse, Kollektor an AVR RXD und einen PullUp 
von 470 Ohm an Vcc. Das war´s.

von Dussel (Gast)


Lesenswert?


von Thomas K. (thomas47058)


Lesenswert?

Hallo zusammen,

ist schon ein altes Thema. Ich mach deshalb keinen neuen Thread auf, in 
der Hoffnung, dass das trotzdem jemand liest.

Ich bin gerade dabei einen MIDI Controller zu basteln. Noch befindet 
sich alles im Aufbau. Ich würd gerne aus Testzwecken einzelne MIDI 
Messages an den PC senden.

Der Aufbau ist folgender:
uC: atmega8
taktgeber quarz: 12 MHz
Fuses gesetzt (low: FF, high: C9)
MIDI Schnittstelle gebaut und verkabelt nach Plan (Pin4 der Buchse über 
220 ohm an TXD, Pin2 an GND, Pin5 über 220 an Vcc 5V)
programmiert mit Codevision

Mit MidiOX prüfe ich, was am PC ankommt. Leider tut sich rein gar 
nichts. Ich weiß nicht, ob es am Code liegt, oder am uC... ich bin 
ratlos.

Hier der Code in abgespeckter Form. Könnt ihr irgendwo einen Fehler 
entdecken? Hab ich vergessen notwendige Details zu erwähnen? Ich wäre 
für eure Hilfe sehr sehr dankbar.
1
Chip type           : ATmega8
2
Program type        : Application
3
Clock frequency     : 12,000000 MHz
4
Memory model        : Small
5
External RAM size   : 0
6
Data Stack size     : 256
7
*****************************************************/
8
9
#include <mega8.h>
10
#include <delay.h>
11
12
// Standard Input/Output functions
13
#include <stdio.h>
14
15
16
unsigned char buffer;
17
18
void putchar_midi_on()
19
{
20
    
21
        while ( !( UCSRA & (1<<5)) );
22
        buffer = 0x91;
23
        UDR = buffer ;
24
25
        while ( !( UCSRA & (1<<5)) );
26
        buffer = 0x50;
27
        UDR = buffer ;
28
29
        while ( !( UCSRA & (1<<5)) );
30
        buffer = 0x64;
31
        UDR = buffer ;
32
33
}
34
35
void putchar_midi_off()
36
{
37
        while ( !( UCSRA & (1<<5)) );
38
        buffer = 0x81;
39
        UDR = buffer ;
40
41
        while ( !( UCSRA & (1<<5)) );
42
        buffer = 0x50;
43
        UDR = buffer ;
44
45
        while ( !( UCSRA & (1<<5)) );
46
        buffer = 0x64;
47
        UDR = buffer ;
48
}
49
50
51
void main(void)
52
{
53
54
[...]
55
56
// Port D initialization 
57
PORTD=0xFF;
58
DDRD=0xFF;
59
60
[...]
61
62
// USART initialization
63
// Communication Parameters: 8 Data, 1 Stop, No Parity
64
// USART Receiver: Off
65
// USART Transmitter: On
66
// USART Mode: Asynchronous
67
// USART Baud Rate: 31250
68
UCSRA=0x00;
69
UCSRB=0x08;
70
UCSRC=0x86;
71
UBRRH=0x00;
72
UBRRL=0x17;
73
74
[...]
75
76
while (1)
77
      {
78
      
79
      if(!(PINC&0b00000001)) //Button an pinc0
80
      {
81
       putchar_midi_on();
82
       
83
       PORTD&=~(0b00000100); //Kontroll LED an
84
       delay_ms(100);
85
       PORTD|=0b00000100; //Kontroll LED aus
86
      //LEDs dienen nur temporär zum Überprüfen, ob die Fkt aufgerufen wird
87
      }
88
      
89
      if(!(PINB&0b00000100)) //Button an pinb2
90
      {        
91
       putchar_midi_off();
92
       
93
       PORTD&=~(0b00000100);
94
       delay_ms(100);
95
       PORTD|=0b00000100; 
96
      
97
      };
98
}
99
}

von Thomas K. (thomas47058)


Lesenswert?

weiß keiner eine lösung? hier nochmals die bitte drüber zu sehen.

besten dank!

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Als erstes würde ich am MIDI-Ausgang Deines Controllers eine LED 
anschließen und gucken, ob sie blinkt. Dann wäre noch interessant, wie 
Du Deinen MIDI-Ausgang mit dem PC verdrahtet hast.

von Phil J. (sunflower_seed)


Lesenswert?

http://www.embedds.com/diy-midi-interface-for-usb/

Guck mal hier, ich habe die Orginale Internetseite nicht mehr gefunden.
Aber vielleicht hilft dir der Code zu dem projekt weiter
http://www.avrfreaks.net/index.php?module=Freaks%20Files&func=viewFile&id=2515&showinfo=1

von Thomas K. (thomas47058)


Lesenswert?

Hallo und vielen Dank für die Antworten.

@travelrec, dass daten fließen, habe ich mit nem multimeter gemessen. 
ich weiß, das ist nicht die genaueste Methode, aber es hat gereich um 
festzustellen, dass was passiert am Ausgang. An die MIDI (DIN) Buchse 
habe ich ein einfaches MIDI Kabel angeschlossen, welches dann zur 
seriellen Schnittstelle meiner Soundkarte führt, als Adapter sozusagen. 
Soundkarte ist die Terratec EWX 24/96. Die haben damals einen "Gameport" 
mitgeliefert als "Midi In". Mein MIDI Keyboard tut's auch einwandfrei, 
daran liegts also nicht.

@phil, vielen Dank für den Beispiel Code. Nachdem ich drüber gesehen 
habe, hab ich, abgesehen vom Umfang, keinen Unterschied zu meinem Code 
entdeckt... leider. Hm... ich frag mich, ob ich das mit der 
Bitübertragung richtig eingestellt habe. 8 Daten Bits, 1 Stop Bit, kein 
Parity Bit ist doch korrekt, oder? Was ist mit dem Startbit? Und wieso 
steht im Beispielcode etwas von Stop Bit Generation?:
1
void SUART_putchar( u8 val )    // send byte
2
{
3
  while( stx_count );      // until last byte finished
4
  stx_data = ~val;  // invert data for Stop bit generation
5
  stx_count = 10;      // 10 bits: Start + data + Stop
6
}

Das verwirrt mich. Was hat es damit auf sich? Hab auch in Büchern nix 
dazu gefunden.

Vielleicht liegt es daran, dass etwas fehlt bei der Übertragung, oder 
etwas falsch interpretiert wird...

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Moment mal: benutzt Du nun eine Hardware- oder Software-UART? Bei der 
Hardware-UART mußt Du nur Baudratenregister und Steuerregister passend 
setzen und nacheinander die richtigen Bytes in das UDR-Register 
schreiben. Die Baudrate muß natürlich stimmen. Den Rest mit Start und 
Stop-Bit macht die Hardware.

von Mark M. (mom-jovi)


Lesenswert?

Thomas P. schrieb:
> 8 Daten Bits, 1 Stop Bit, kein Parity Bit ist doch korrekt, oder? Was
> ist mit dem Startbit?

Ich weiß, es ist ein altes Thema. Aber ich beschäftige mich gerade auch 
damit. Erwartet MIDI tatsächlich ein Stop Bit?
Nach dem hier: 
http://de.wikipedia.org/wiki/Musical_Instrument_Digital_Interface#Funktionsweise_des_MIDI-Protokolls
werden doch nur bloße Bytes gesendet, oder? Die Unterscheidung 
Status-/Datenbyte erfolgt mit dem ersten Bit eines Bytes.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Mark M. schrieb:
> Nach dem hier:
> http://de.wikipedia.org/wiki/Musical_Instrument_Di...
> werden doch nur bloße Bytes gesendet, oder?

Das hat damit nichts zu tun. Es geht um die grundlegende serielle 
Übertragung, Start- und Stopbit gehören zu deren Framing, das um jedes 
übertragene Byte gepackt wird.

Darum muss man sich als Programmierer nicht kümmern, das erledigt die 
UART-Hardware ganz von selbst.

von Mark M. (mom-jovi)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Mark M. schrieb:
>> Nach dem hier:
>> http://de.wikipedia.org/wiki/Musical_Instrument_Di...
>> werden doch nur bloße Bytes gesendet, oder?
>
> Das hat damit nichts zu tun. Es geht um die grundlegende serielle
> Übertragung, Start- und Stopbit gehören zu deren Framing, das um /jedes/
> übertragene Byte gepackt wird.
>
> Darum muss man sich als Programmierer nicht kümmern, das erledigt die
> UART-Hardware ganz von selbst.

Aber hier geht es doch darum, MIDI-Bytes an einen MIDI-Eingang zu 
senden. Und ich habe gedacht, dass MIDI eben kein Framing hat/braucht. 
Oder versteht es UART mit Start- und Stop-Bits? Steht das irgendwo?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Mark M. schrieb:
> Und ich habe gedacht, dass MIDI eben kein Framing hat/braucht.

Doch, tut es. Das ist eine ganz stinknormale UART-Übertragung, so, wie 
es asynchrone serielle Schnittstellen tun. Es "versteht" nicht nur 
Start- und Stopbits, es benötigt sie zwingend.

Wäre die serielle Schnittstelle des PCs in der Lage, die korrekte 
Baudrate zu erzeugen, müsste man nur von RS232-Pegeln auf die 
MIDI-Stromschnittstelle umsetzen und könnte direkt mit MIDI-Hardware 
kommunizieren.

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.