Forum: Mikrocontroller und Digitale Elektronik MIDI Note mit assembler über UART ausgeben


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Walter (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Mitstreiter,

ich bin hier am verzweifeln und hoffe auf einen Hilfreichen Tipp.
Ich kann leider Nur Assembler und damit habe ich auch schon viel 
erreichen können.
Es geht mir um das Ausgeben einer MIDI-Note.

Ich habe schon einiges zu dem Thema gefunden und normalerweise sollte es 
recht einfach gehen. Dennoch gelingt es mir nicht, einen Ton aus dem 
01R/W zu bekommen.

Ich schließe meine Keyboard an den 01R/W an und betätige die Taste für 
ein A (440Hz) und die Empfangs Led am 01R/W blinkt auf und auch der Ton 
wird höhrbar.

So weit, so gut.

Nun schließe ich meine Schaltung an und auch bei mir blinkt die Empfangs 
Led aber es wird kein Ton hörbar. Cubasis empfängt auch keine Noten ...

Mit dem Oszi werden 3 gesendete Bytes erkennbar und ein Bit braucht 33µs
Am Keyboard sind es auch 33µs

Vieleicht hat ja einer von euch eine Idee...

Ich dachte mir, Mit dem ATMega 32 sollte es kein Problem sein.

**** 1. Bautrate ermitteln:
;Variabelen und Vorgabewerte

     .equ     TAKT = 8000000    ; Systemtakt 8.000 MHz
     .equ     BAUD  = 31250     ; Baudrate für MIDI

; Berechnungen
.equ UBRR_VAL   = ((TAKT+BAUD*8)/(BAUD*16)-1)    ; clever runden
.equ BAUD_REAL  = (TAKT/(16*(UBRR_VAL+1)))      ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille

.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille 
Fehler
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit 
zu hoch!"
.endif

**** 2. Bautrate in Register ablegen

; Baudrate einstellen

    ldi     akku, HIGH(UBRR_VAL)
    out     UBRRH, akku
    ldi     akku, LOW(UBRR_VAL)
    out     UBRRL, akku

**** 3. UART konfigurieren
    ; Frame-Format: 8 Bit

;    ldi     akku, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)
;    out     UCSRC, akku
; Abgeschaltet da in Midirec auch nicht gewesen

    sbi     UCSRB,TXEN                  ; TX aktivieren

**** 4. 3 Byte Vorbereiten:

lds   akku, 0b01101111  ; Note on CH1
sts    MIDI1, akku
lds   akku, 0b10000101  ; Note A4 (69 MIDI = 45 Hex)
sts    MIDI2, akku
lds   akku, 0b10000000  ; minimale Lautstärke (0) (Note off)
sts    MIDI3, akku

**** 5. 3 Byte senden

MIDIout:
  push  akku

MIDIout1:
sbis    UCSRA,UDRE               ; Warten bis UDR für das nächste
                                 ; Byte bereit ist
rjmp    MIDIout1
LDS  akku, MIDI1
out     UDR, akku
MIDIout2:
sbis    UCSRA,UDRE                ; Warten bis UDR für das nächste
                                  ; Byte bereit ist
rjmp    MIDIout2
LDS  akku, MIDI2
out     UDR, akku
MIDIout3:
sbis    UCSRA,UDRE                  ; Warten bis UDR für das nächste
                                        ; Byte bereit ist
rjmp    MIDIout3
LDS     akku, MIDI3
out     UDR, akku

pop  akku
ret

**** und zum Schluss
.DSEG
MIDI1:  .BYTE   1         ; MIDI - Befehl/Kanal
MIDI2:  .BYTE   1         ; MIDI - Controlernummer(Note)
MIDI3:  .BYTE   1         ; MIDI - Controlerwert (Lautstärke)

Ich hoffe Ihr könnt mir folgen,
Liebe Grüße und vielen Dank
Walter

von eProfi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ein Bit dauert 32 Mikrosekunden.
Du schickst im 2. Byte nicht 45, sondern 85.
Lautstärke 0 oder 80? Kommentar muss immer zum Code passen.
Manche Geräte schicken statt Note off ein Note on mit Lautstärke 0.

Passt die Polarität? Normal fließt kein Strom in der Schleife.

von Thomas E. (picalic)


Bewertung
3 lesenswert
nicht lesenswert
Walter schrieb:
> lds   akku, 0b01101111  ; Note on CH1
> sts    MIDI1, akku
> lds   akku, 0b10000101  ; Note A4 (69 MIDI = 45 Hex)
> sts    MIDI2, akku
> lds   akku, 0b10000000  ; minimale Lautstärke (0) (Note off)
> sts    MIDI3, akku

Warum gibst Du die Werte der Bytes binär an? Wenn Du es dann wenigstens 
selbst korrekt ausgerechnet hättest...

Also, das Statusbyte für "Note On Ch1" ist 0x90 (= 0b10010000) - Deins 
scheint (warum auch immer) invertiert zu sein.

0x45 ist 0b01000101 - Deins ist 0x85 (=>Statusbyte "Note off on Ch 6")

Dein Velocity-Wert 0 würde (wenn er richtig codiert wäre - tatsächlich 
sendest Du 0x80 = Statusbyte Note Off on Ch1) als
 "Note Off" interpretiert - da müsstest Du Dich auch nicht wundern, wenn 
Du nix hörst. Probier's mal mit mittlerem Velocity-Wert, also 0x40.

Bei der obigen Sequenz also:
> lds   akku, 0x90  ; Note on CH1
> sts    MIDI1, akku
> lds   akku, 0x45  ; Note A4 (69 MIDI = 45 Hex)
> sts    MIDI2, akku
> lds   akku, 0x40  ; mittlere Lautstärke 64
> sts    MIDI3, akku

: Bearbeitet durch User
von S. Landolt (Gast)


Bewertung
1 lesenswert
nicht lesenswert
> lds   akku, 0x90  ; Note on CH1
> sts    MIDI1, akku
> lds   akku, 0x45  ; Note A4 (69 MIDI = 45 Hex)
> sts    MIDI2, akku
> lds   akku, 0x40  ; mittlere Lautstärke 64
> sts    MIDI3, akku

Da muss doch jeweils ldi stehen statt lds, oder?

von Walter (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Hallo, zusammen,

das ist ja der Hammer! Wer wird mir schon helfen? Und dann so schnell! 
Ganz herzliches Dankeschön! Super Kommentare und es läuft.

Aber für alle die das Gleiche erleben, hier noch mal konkret:

Ich war so verzweifelt und suchte nach jedem Halm. In einem der Beiträge 
war erwähnt, dass die Bits invertiert werden müssen – ein Versuch 
zeigte, dass es deshalb trotzdem nicht klappte. Ich vergas die 
Invertierten Bits zurück zu schreiben!

Also Rüffel zu Recht und sorry!

; **** Note on:
    ldi   akku, 0b10010000  ; Note on und CH1 (000)
    sts    MIDI1, akku
    ldi   akku, 0b00100100  ; Note C1 (36 MIDI = 25 Hex)
    sts    MIDI2, akku
    ldi   akku, 0b01111111  ; maximale Lautstärke (127) (Note on)
    sts    MIDI3, akku

    call  MIDIout

; **** Note off:
    ldi   akku, 0b10010000  ; Note on und CH1 (000)
    sts    MIDI1, akku
    ldi   akku, 0b00100100  ; Note C1 (36 MIDI = 25 Hex)
    sts    MIDI2, akku
    ldi   akku, 0b00000000  ; minimale Lautstärke (0) (Note off)
    sts    MIDI3, akku


Mein Fehler bestand tatsächlich in dem LDS ... ganz klar, den akku läd 
man mit einer Zahl mit "ldi" und schon spielt die Musik! - Naja - die 
Note ;-)

Übrigens angeregt durch den Beitrag "MIDI-Controller selber bauen" von 
Götz Müller-Dürholt

https://www.youtube.com/watch?v=a6pex3DwNjs

baue ich ein Gerät zum wiedergeben von Wierderständen in Form von 
Midinoten.

Also nochmals Danke für die absoulut korrekte und sehr ziehführende 
Hilfe!

Viele Grüße
Walter

von Thomas E. (picalic)


Bewertung
1 lesenswert
nicht lesenswert
Ok, das mit dem LDS vs. LDI wäre mir vielleicht auch aufgefallen, wenn 
ich mehr mit AVRs zu tun hätte... ;)

Deinen Hang zu Zahlenwerten im Binärsystem kann ich immer noch nicht 
nachvollziehen. Das macht es hier doch nur unleserlich und 
fehleranfällig.
Beim MIDI Statusbyte bietet sich hexadezimale Schreibweise an (erstes 
Digit = Funktion, z.B. 9 = Note On, zweites Digit: MIDI-Kanal 0..F -> 
K.1..16), Notennummer und Velocitywert könnte man auch dezimal angeben - 
was soll hier die Binärdarstellung?

: Bearbeitet durch User
von Walter (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Thomas,

ja, Du hast recht, die Hex darstellung ist sehr schön. Ich war nur auf 
der Fehlersuche und wollte die seriellen Bits mit dem Bild vom Oszi 
vergleichen und da kann ich mir besser vorstellen wie das Signal 
aussehen muss :-)

von Jürgen S. (engineer) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Sendest Du regelmäßig den MIDI-Takt?

von Bla (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wie kann man leider nur assembler können? C ist viel einfacher und 
schnell gelernt, wenn man eh weiß was sich unter dem Blech abspielt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.