Hallo liebes Forum,
Ich bin neu hier. bin seit ein paar wochen / wenigen monaten am atmega programmieren. ich hatte schon ein paar fragen in ein anderes forum geschrieben, wurde dort aber nicht sonderlich freundlich begrüßt, weshalb ich es mal hier versuche...
ich bastele an einem kleinen projekt. hauptziel ist dabei midi zu verstehen. der Atmega8 soll also mit Uart midi auslesen und dann entsprechende LEDs anschalten.
ich leg mal los, mit dem schon erledigten:
ich habe mir ein kleines board mit optokopler aufgebaut. das gewandelte signal schicke ich dann direkt an mein stk500 an den RX pin für das UART. Getacktet wird mein Atmega8 mit einem 4 Mhz Quarz direkt auf dem eingebauten sockel des stk500. also quasi mit Quarzoszillator. midi läuft ja mit 31250 baud. laut verschiedener rechner im internet, sollte ein 4 Mhz takt genau geeinget sein. also ohne relative fehler. den UBRR-Wert, den ich dazu errechnet habe ist 7 (kommt weiter unten zum einsatz).
gefused habe ich den atmega 8 mit 0xD9 (high) und 0xE0 (low). ich habe auch den quarz an einem oszi überprüft. der scheint korrekt zu schwingen. das müsste alles soweit passen denke ich. jumper habe ich auch entsprechend gesetzt. assembliert wird alles mit gcc-avr.
unten stehendes programm ist nur zum testen der übertragung gedacht. das erste übertragene byte (in dem das midi-event und der kanal stehen) soll am port B ausgegeben werden und ich habe diesen port dann mit den LEDs vom stk500 verbunden. so sehe ich, ob und was als erstes übertragenes byte (Statusbyte bei normalen midi-messages) ankam.
...und, naja... es gibt schwankungen. fast alle messages werden korrekt übertragen. nur die (sehr wichtigen) note-on messages haben oft bit-kipper. tatsächlich funktioniert es etwa in 50 prozent der fälle (ich bekomme dann 1001 xxxx angezeigt). wenns nicht funktioniert dann erhalte ich meistens 1000 xxxx (was ja einer note-off message entspräche. obwohl ich die taste noch nicht mal unbedingt losgelassen habe). ich teste die ganze sache mit nem kleinen midi-keyboard, an dem ich tasten drücke und vergleiche mit den ausgegebenen werten an den LEDs. hab jetzt echt viel gedrückt. kann keine systematik der fehler erkennen. es scheinen vermehrt die unteren midi-kanäle (0 - ca. 5) betroffen zu sein. aber auch bei den oberen funktioniert es nicht zuverlässig. kann sich jemand nen reim drauf machen? das würde mir echt viel helfen. ich bin mit meinem latein am ende... vielleicht habe ich auch nen echt banalen fehler beim programmieren gemacht...
jetzt mal zum code: hier ist mein folständiges programm:
ich danke jeden, der bis hier durchgehalten hat...
Ich bin neu hier. bin seit ein paar wochen / wenigen monaten am atmega programmieren. ich hatte schon ein paar fragen in ein anderes forum geschrieben, wurde dort aber nicht sonderlich freundlich begrüßt, weshalb ich es mal hier versuche...
ich bastele an einem kleinen projekt. hauptziel ist dabei midi zu verstehen. der Atmega8 soll also mit Uart midi auslesen und dann entsprechende LEDs anschalten.
ich leg mal los, mit dem schon erledigten:
ich habe mir ein kleines board mit optokopler aufgebaut. das gewandelte signal schicke ich dann direkt an mein stk500 an den RX pin für das UART. Getacktet wird mein Atmega8 mit einem 4 Mhz Quarz direkt auf dem eingebauten sockel des stk500. also quasi mit Quarzoszillator. midi läuft ja mit 31250 baud. laut verschiedener rechner im internet, sollte ein 4 Mhz takt genau geeinget sein. also ohne relative fehler. den UBRR-Wert, den ich dazu errechnet habe ist 7 (kommt weiter unten zum einsatz).
gefused habe ich den atmega 8 mit 0xD9 (high) und 0xE0 (low). ich habe auch den quarz an einem oszi überprüft. der scheint korrekt zu schwingen. das müsste alles soweit passen denke ich. jumper habe ich auch entsprechend gesetzt. assembliert wird alles mit gcc-avr.
unten stehendes programm ist nur zum testen der übertragung gedacht. das erste übertragene byte (in dem das midi-event und der kanal stehen) soll am port B ausgegeben werden und ich habe diesen port dann mit den LEDs vom stk500 verbunden. so sehe ich, ob und was als erstes übertragenes byte (Statusbyte bei normalen midi-messages) ankam.
...und, naja... es gibt schwankungen. fast alle messages werden korrekt übertragen. nur die (sehr wichtigen) note-on messages haben oft bit-kipper. tatsächlich funktioniert es etwa in 50 prozent der fälle (ich bekomme dann 1001 xxxx angezeigt). wenns nicht funktioniert dann erhalte ich meistens 1000 xxxx (was ja einer note-off message entspräche. obwohl ich die taste noch nicht mal unbedingt losgelassen habe). ich teste die ganze sache mit nem kleinen midi-keyboard, an dem ich tasten drücke und vergleiche mit den ausgegebenen werten an den LEDs. hab jetzt echt viel gedrückt. kann keine systematik der fehler erkennen. es scheinen vermehrt die unteren midi-kanäle (0 - ca. 5) betroffen zu sein. aber auch bei den oberen funktioniert es nicht zuverlässig. kann sich jemand nen reim drauf machen? das würde mir echt viel helfen. ich bin mit meinem latein am ende... vielleicht habe ich auch nen echt banalen fehler beim programmieren gemacht...
jetzt mal zum code: hier ist mein folständiges programm:
Code:
#define __SFR_OFFSET 0
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#define temp0 r17
#define temp1 r18
.section .text
.global main
main:
//*********************Stackpointer initialisierung*********************\\
ldi temp1, hi8(RAMEND-0x20)
out SPL, temp1
ldi temp1, lo8(RAMEND-0x20)
out SPH, temp1
//*********************Port B konfigurieren*********************\\
ldi temp1, 0xFF
out DDRB, temp1
ldi temp1, 0x00
//*********************Uart konfigurieren*********************\\
ldi temp0, 0x80 // laut diesem thread muss man erst UBRRH so setzten, bevor man UCSRC beschreiben kann:
// http://www.avr-praxis.de/forum/showthread.php?178-Erste-Erfahrungen-mit-der-seriellen-Daten%FCbertragung
out UBRRH, temp0
ldi temp0, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)
out UCSRC, temp0
sbi UCSRB, RXCIE
sbi UCSRB, RXEN
ldi temp1, 0b00000000
out UBRRH, temp1
ldi temp1, 0b00000111
out UBRRL, temp1
sei //Interrupts allgemein aktivieren
ldi temp0, 0b00000001 //Eine LED leuchtet, wenn startbereit (bzw. leuchtet nicht. die leds sind beim stk500 ja negiert)
out PORTB, temp0
//*********************loop*********************\\
loop:
rjmp loop
//*********************Uart interrupt*********************\\
.global USART_RXC_vect
USART_RXC_vect:
cli //schaltet die interrupts gleich wieder aus. so wird (hoffentlich) nur das erste übertragene byte angezeigt
in temp0, UDR
ror temp0
ror temp0 // ich muss hier zweimal rotieren, da an den beiden höchsten bits vom port B ja der externe oszi dran
//hängt. deswegen verschiebe ich das ganze um zwei bits nach rechts, so sehe ich zumindest die obersten 6
//bits vom übertragenen byte. die untersten 2 sind jetzt auch erstmal nicht so wichtig. da steht ja nur der midi-kanal
//drin
out PORTB, temp0 //hier wird das byte am port B ausgegeben
ret
ich danke jeden, der bis hier durchgehalten hat...