MIDI Daten senden?

Gast #1021057
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
Gast #1021278
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
Gast #1021384
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
Gast #1021404
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.
Gast #1021440
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
Gast #1022185
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.
Gast #1023796
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
(Firma: TravelRec.) Persönliche Seite #1023872
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.
#1288231
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
}
#1289224
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...
#2467920
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.
Persönliche Seite #2467996
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.
#2468002
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?
Persönliche Seite #2468013
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren