Ich wollte mit einem ATMega8 eine oktave stummelpedale midifizieren. etzt hab ich mir gedacht, machst die uart mal von hand... Irgendwas funktioniert aber nicht, ich habe mir den Takt von 31,250kHz mittels timer hergestellt (und mit oszi nachgemessen) und ein progrämmchen geschrieben, welches ein startbit, 8 datenbits und ein stopbit auf einen pin schickt: ______________________________________________________________ unsigned char tick=0x00; unsigned char toggle=0x00; const unsigned char noteon=0x09; //90 const unsigned char keynum=0x24; //24 const unsigned char velocity=0xff; const unsigned char novelocity=0x00; // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // if (tick==0x00) // { tick++; // } // else // { // tick=0x00; // } TCNT0=0x30; } void midiout (unsigned char byte) { unsigned char busy=0x01; unsigned char bitcount=0x00; while (busy==0x01) { //write startbit if (bitcount==0x00 && tick==0x01) { PORTD=0xFF; tick=0x00; bitcount++; } //write stopbit else if(bitcount==0x09 && tick==0x01) { PORTD=0xFF; tick=0x00; bitcount++; } else if(bitcount==0x0a && tick==0x01) { PORTD=0x00; tick=0x00; bitcount++; busy--; } //write byte else if(tick==0x01) { PORTD=byte; byte>>=1; bitcount++; tick=0; } } PORTC.1^=1; } // Timer 1 overflow interrupt service routine interrupt [TIM1_OVF] void timer1_ovf_isr(void) { // Reinitialize Timer 1 value TCNT1H=0x70; TCNT1L=0x00; // Place your code here PORTC.2^=1; toggle++; } /* // Timer 2 overflow interrupt service routine interrupt [TIM2_OVF] void timer2_ovf_isr(void) { // Place your code here PORTD.2^=1; } */ // Declare your global variables here void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port B initialization // Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In // State0=P State1=P State2=P State3=P State4=T State5=T State6=P State7=P PORTB=0xCF; DDRB=0x00; // Func0=Out Func1=Out Func2=Out Func3=Out Func4=Out Func5=Out Func6=Out // State0=0 State1=0 State2=0 State3=0 State4=0 State5=0 State6=0 PORTC=0x00; DDRC=0x7F; // Port D initialization // Func0=Out Func1=Out Func2=Out Func3=In Func4=In Func5=In Func6=In Func7=In // State0=0 State1=0 State2=0 State3=T State4=T State5=T State6=T State7=T PORTD=0x00; DDRD=0x07; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 8000,000 kHz TCCR0=0x01; TCNT0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 8000,000 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge TCCR1A=0x00; TCCR1B=0x05; TCNT1H=0x70; TCNT1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; /* // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: 8000,000 kHz // Mode: Normal top=FFh // OC2 output: Disconnected TCCR2=0x01; ASSR=0x00; TCNT2=0x00; OCR2=0x00; */ // External Interrupt(s) initialization // INT0: Off // INT1: Off GICR=0x00; MCUCR=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x45; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off // Analog Comparator Output: Off ACSR=0x80; SFIOR=0x00; // Global enable interrupts #asm("sei") while (1) { midiout(noteon); midiout(keynum); midiout(velocity); /* if(toggle==0x01) { midiout(noteon); //10010000 midiout(keynum); //00100100 midiout(velocity); //11111111 toggle++; } else if (toggle==0x03) { midiout(noteon); //10010000 midiout(keynum); //00100100 midiout(novelocity); //00000000 toggle=0x00; } */ } } ____________________________________________________________ Irgendwo ist ein grober fehler drinne, das signal hab ich aufm oszi, wie es eigentlich sein soll. Wie muss ein midisignal aussehen, 1 bedeutet doch stromschleife unterbrochen, für eine taktperiode? wie ist das mit startbit, kommt da nochmal 0 dazwischen? das keyboard, das ich angeschlossen hab reagiert nicht, schaltet nur manchmal das rythmusgerät ein, ist aber definitiv ok, da es mit anderen quellen tut. Die Stromschleife passt von den Werten her exakt (nachgemessen)
Ist schon eine Weile her, seit dem ich mich das letzte mal mit Midi beschäftigte. Schließ doch mal statt eines Keyboards die Midi-Signale an Deine PC-Soundkarte an. Ich kann mich noch dunkel an ein Programm (Midimon?) erinnern, das die Bytes am Bildschirm anzeigte. Solche Projekte gibt es wie Sand am Meer, oft mit PIC-Prozessoren. Polarität des Midi-Signals weiß ich nicht auswendig, ich denke aber mal TTL high = V24 low = Midi no current (nur eine Vermutung, da sonst bei abgestecktem Midi immer Startbits gesehen würden). Freut mich immer, wenn jemand was mit Midi macht... Kennst Du den ZEL Midi-Compiler (www.zelsoft.com)? Super high-density-Programm für Puristen!
Danke erstmal für die Hilfe, aber die projekte, die ich bisher gesehen hab, sind alle in asm -kann ich nicht. Es tut ja an sich alles was ich will... signal hab ich ja aufm oszi. es ist irgendwie der fehler im systen... hi/lo verwechselt, byte verkehrtrum gesendet? steht doch nirgends...steht nur überall startbit datenbyte stoppbit. oder muss man da noch irgendwelche config messages bringen? aus dem keyboard seh ich immer nur die 3 bytes noteon/kanal, keynumber/ velocity...beim loslassen halt mit velocity=00
natürlich mußt du auch während der Ausgabe eines Bytes über den Soft UART dafür sorgen, daß keine weitere Interrupt Routine ausgeführt wird. Sonst kommt ja da das Bit-Timing durcheinander.
Versuche doch mal, genau die gleiche Bitfolge zu erzeugen, wie aus dem Keyboard beim Drücken einer Taste kommt. Dann muss es gehen. Habe ich von 20 Jahren schonmal gemacht: ein einfachster Sequenzer: ich zeichnete das Byte und die Zeit zum nächsten auf. Damit konnte ich gespielte Stücke wiederholt abspielen. Hast Du mal den Midimon ausprobiert? Hast Du eine Soundkarte mit Midi-In/Out?
Ich hab jetzt mal doch die USART des atmels benutzt -die bitfolge ist von der frequenz her auch so wie von meiner softuart... ich kann nur die vom keyboard schlecht angucken, weil ich kein speicheroszi hab. habs jetzt mal versucht mit der soundkarte als audio aufzuzeichen auch nicht ideal mit 44.1kHz sampling nur, mehr macht die irgendwie net. das problem ist eher dass ich nirgends gefunden hab, wie das signal aussehen soll. ich hab ein programm nahmens midispy, das hex anzeigt, was empfangen wird (nix). Ich begreif das midisignal nicht. HAb wo gelesen, dass logisch 1 strom aus und logisch null strom an sei. ist das startbit dann logisch 0? das signal vom keyboard, so gut ichs erkennen kann ist strom aus, wenn nix gesendet wird. irgendwie ist der fehler im system. signal fällt ja raus, nur das falsche, und ich weiss nicht was falsch ist.
MIDI Spezifikationen gibt´s unter http://www.midi.org unter http://www.google.de sind jede Menge Seiten mit Infos zu finden, wie die verschiedensten MIDI-Strings aufgebaut sind.
Zuerst musst Du mal klären, ob es an der HW oder der SW liegt, ich vermute mal, mit der HW stimmt was noch nicht. Kannst Du mal versuchen, das Signal im Empfänger nach dem ersten Optokoppler zu messen. Wenn Du Dein Oszi auf Single oder AUTO stellst und die Triggerung und den Slope richtig einstellst, kannst Du erreichen, dass der Strahl immer mit dem Startbit an der linken Seite der Schirms beginnt. Wenn die Umgebung dunkel ist, sieht man den Strahl immer noch ausreichend lange nachleuchten. Natürlich wäre ein Speicheroszi besser, hat ein Bekannter vielleicht eines zum Leihen? Dann kannst Du auch die Polarität und die Bit-Dauer (ca.31µs) messen. Vergleiche sie mit einem Midi-Signal (aus dem PC oder einem anderen Gerät oder mit einem Midi-Loop-Stecker sogar aus dem selben Gerät). Das sollte doch zu schaffen sein.
@ Bassti: Hast Du an Deiner Soundkarte keinen MIDI-Eingang? Falls doch, guckst Du "MIDI-OX" - kleines Programm, was Dir alles zeigt, was über MIDI ´rein kommt. In puncto Midi: Startbit (0V / 0mA), Datenbits LSB zuerst, MSB zuletzt, Stopp-Bit (5V / 5 mA). Falls Du ´nen Optokoppler benutzt, diesen über 3x 220 Ohm und ´ne Sicherheitsdiode antiparallel zu LED zwischen Port-AusgangsPin und VCC klemmen, so daß beim StopBit die LED aus ist. Am Ausgang des Optos einen PullUp und daran die MIDI-Schnittstelle der Soundkarte. Achtung, die Pegel und Anstiegs-/Abfallzeiten sind kritisch und können, falls falsch eingestellt oder verwaschen, zu Bitfehlern führen. Übrigens sind MIDI-Befehle nur sehr selten ein einziges Byte. Kanalmeldungen und Ereignismeldungen (Note/Anschlag) müssen immer mitübertragen werden, sonst reagiert der angeschlossene "Slave" nicht. Nutz doch für Testzwecke erstmal einen Hardware-Uart, bei dem Du von 4 oder 8MHz die Taktfreqens auf 31250Hz herunterteilst. Bei dem stimmen dann zwangsläufig zumindest Datenformat und Timing und Du kannst den Fehler eventuell woanders suchen.
also wie gesagt, hab ich zu hardwaredebugging mal die hardwareuart des atmels verwendet, mit 8MHz auf die 31,250kHz eingestellt. Passt von der frequenz her. Mir ist das mit dem startbit nicht klar was das soll... wenn nix kommt, dann ist doch sowieso 0 Strom?? Datenbits 1=Strom oder kein Strom? -also wirklich in der stromschleife... ich hab jetzt von optokopplern mal abgesehen kommt später, wenns mal soweit tut. versorgt potentialfrei, also keine probleme mit massen und so. ist das alles richtig so? code vom wizzard: _________________________________________________________________ #include <mega8.h> #define RXB8 1 #define TXB8 0 #define UPE 2 #define OVR 3 #define FE 4 #define UDRE 5 #define RXC 7 #define FRAMING_ERROR (1<<FE) #define PARITY_ERROR (1<<UPE) #define DATA_OVERRUN (1<<OVR) #define DATA_REGISTER_EMPTY (1<<UDRE) #define RX_COMPLETE (1<<RXC) // USART Transmitter buffer #define TX_BUFFER_SIZE 64 typedef unsigned char byte; char tx_buffer[TX_BUFFER_SIZE]; unsigned char tx_wr_index,tx_rd_index,tx_counter; const byte noteon=0x90; const byte keynum=0x24; const byte velocity=0x7F; const byte novelocity=0x00; byte toggle=0x00; // USART Transmitter interrupt service routine #pragma savereg- interrupt [USART_TXC] void uart_tx_isr(void) { #asm push r26 push r27 push r30 push r31 in r26,sreg push r26 #endasm if (tx_counter) { --tx_counter; UDR=tx_buffer[tx_rd_index]; if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0; }; #asm pop r26 out sreg,r26 pop r31 pop r30 pop r27 pop r26 #endasm } #pragma savereg+ #ifndef DEBUG_TERMINAL_IO // Write a character to the USART Transmitter buffer #define ALTERNATE_PUTCHAR #pragma used+ void putchar(char c) { while (tx_counter == TX_BUFFER_SIZE); if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0)) { tx_buffer[tx_wr_index]=c; if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0; #asm("cli") ++tx_counter; PORTC.2^=1; //schaun #asm("sei") } else UDR=c; } #pragma used- #endif // Standard Input/Output functions #include <stdio.h> // Timer 1 overflow interrupt service routine interrupt [TIM1_OVF] void timer1_ovf_isr(void) { // Place your code here toggle++; TCNT1H=0x70; TCNT1L=0x00; } // Declare your global variables here void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port B initialization // Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In // State0=P State1=P State2=P State3=P State4=T State5=T State6=P State7=P PORTB=0xCF; DDRB=0x00; // Port C initialization // Func0=Out Func1=Out Func2=Out Func3=Out Func4=Out Func5=Out Func6=Out // State0=0 State1=0 State2=0 State3=0 State4=0 State5=0 State6=0 PORTC=0x00; DDRC=0x7F; // Port D initialization // Func0=In Func1=In Func2=In Func3=In Func4=Out Func5=In Func6=In Func7=In // State0=T State1=T State2=T State3=T State4=0 State5=T State6=T State7=T PORTD=0x00; DDRD=0x10; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped TCCR0=0x00; TCNT0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 7,813 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge TCCR1A=0x00; TCCR1B=0x05; TCNT1H=0x70; TCNT1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected TCCR2=0x00; ASSR=0x00; TCNT2=0x00; OCR2=0x00; // External Interrupt(s) initialization // INT0: Off // INT1: Off GICR=0x00; MCUCR=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x04; // USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity // USART Receiver: Off // USART Transmitter: On // USART Mode: Asynchronous // USART Baud rate: 31250 UCSRA=0x00; UCSRB=0x48; UCSRC=0x86; UBRRL=0x0F; UBRRH=0x00; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off // Analog Comparator Output: Off ACSR=0x80; SFIOR=0x00; // Global enable interrupts #asm("sei") while (1) { putchar(novelocity); // Place your code here // if(toggle==0x01) /* { putchar(noteon); //10010000 putchar(keynum); //00100100 putchar(velocity); //11111111 toggle++; } else if (toggle==0x03) { putchar(noteon); //10010000 putchar(keynum); //00100100 putchar(novelocity); //00000000 toggle=0x00; } */ }; } _____________________________________________ hab jetzt einfach nen dauersignalstrom drinne, um die frequenz mal anzuschauen... ansonsten immer abwechlungsweise die drei / sechs messages Noteonereignis/Kanalnummer Keynummer und velocity, mal volle pulle, mal 0. -was anderes tut das keyboard auch nicht schicken. das Signal hab ich dann von dem pin genommen und doppelt invertiert. bzw. die last der 2. emitterstufe ist dann die midistromschleife. kann man aufm oszi auch anschaun. ich bin echt am verzweifeln. sind die einsen beim datenbyte strom oder nicht strom?
Also könntest Du bitte mal das tun, was wir dir anraten, sonst wird das nichts. Ich bin mir nicht ganz sicher: Ruhe = 0 mA Startbit = 5 mA (TravelRec behauptet das Gegenteil) Dlow = 5mA Dhigh = 0 mA Stopbit = 0mA (TravelRec behauptet das Gegenteil) Ist die Bitdauer richtig (MESSEN!) sind die Kanten scharf (MESSEN!) Ist das Signal genauso wie das Keyboard es sendet? HAST DU EINEN MIDI-EINGANG AM PC???
Ruhe = 0 mA -richtig. Startbit = 5 mA -richtig. Dlow = 5mA -richtig. Dhigh = 0 mA -richtig. Stopbit = 0mA -richtig. Ist die Bitdauer richtig (MESSEN!) -bei der hardwareusart ja, hab versucht bei der softwareusart mal die dauern zu variieren um vielleicht irgendwann mal die richtige zu treffen, denn die vom keyboard gesendeten stimmen auch nicht. sind die Kanten scharf (MESSEN!) -ja, sind sie.(imo wirklich scharf genug, scharf ist relativ) Ist das Signal genauso wie das Keyboard es sendet? nein, denn mit der hardwareusart krieg ich das mit den start/stoppbits nicht hin -dient das stopbit als platzhalter? ansonsten ja sinnlos, weil dann strom eh 0.. mit der softuart hab ich dann mal versucht das signal genausolang zu machen, wie das vom keyboard mit meinem speicheroszi (oszi + digicam) es will nicht tun. HAST DU EINEN MIDI-EINGANG AM PC??? -ja, und der empfängt genausowenig wie das keyboard
Freudentränen laufen mir über die backen... geht doch, GEHT DOCH!! Das tool, das ich verwendet hab war einfach n sch.... mit der hardwareuart tuts jetzt, einfach das falsche gesendet. das geniesse ich jetzt erstmal, bevor ich mich wieder entmutigen lass. ich melde mich dann wieder von der front, wenn ich was neues hab. Dickes DANKE erstmal für eure Hilfe! Hoffentlich kann ich das auch zurückgeben.
Na super! Ja, habe da oben ein bissi Quark geschrieben - kommt von der dauernden Invertiererei mit den Optos - irgendwann hat man dann ´nen Knoten im Hirn. Wichtig ist, es geht, bei mir tut´s ja auch alles geh´n trotz des Hirnknotens ;-). Zum Klarstellen nochmals: Das U(S)ART ist gegenüber Masse logisch HIGH, solange nix passiert, geht auf logisch 0 für das Startbit, toggelt je nach Daten zwischen 0 und 1 rum, wobei das kleinstwertige Bit zuerst gesendet wird und geht mit dem Stopp-Bit wieder auf logisch 1. Parity gibt´s dann auch noch, aber eben nicht bei MIDI - schön, daß wir uns alle einig sind :-).
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.