Forum: Mikrocontroller und Digitale Elektronik Problem bei Steuerung über MIDI und ATtiny2313


von povla (Gast)


Angehängte Dateien:

Lesenswert?

Liebe Mikrokontroller-Gemeinde,

bei meinem eigentlich einfach scheinenden Projekt hänge ich fest.
Es geht um folgendes: eine Steuerung von 6 Diaprojektoren über einen 
ATtiny2313. Das Signal soll ein Musikstück im MIDI-Format sein, was über 
einen PC an die Platine weitergegeben wird.
Jeder Projektor erhält eine Note, wird diese Note gespielt, soll er zum 
nächsten Dia weiterschalten.
Die Platine funktioniert an sich ohne Probleme, den Schaltplan hab ich 
euch drangehängt.
Schwierig wird's beim Code. Ich denke dort ist irgendetwas mit der USART 
- Einstellung nicht in Ordnung. Ich selbst mach das hier zum ersten Mal, 
und bin da leider nicht so versiert - vielleicht kennt sich jemand von 
euch besser aus.
Die Platine kann schalten, leider reagiert sie aber nicht auf 
MIDI-Signale.....

Hier der Code
1
/********************************************************
2
 *   midiled für ATTiny2313                *
3
 *   über Port b0 led mit midinote schalten        *
4
 ********************************************************/
5
6
#include <avr/io.h>                    // Standard Bibliothek
7
#include <util/delay.h>                  // Verzögerung
8
#include "midi.h"                    // Midi Informationen
9
10
#define MCU AVR_ATtiny2313                // Microcintrollertyp
11
#define F_CPU 8000000                  // 8Mhz Quarz
12
#define UART_BAUD_RATE 31250              // 31250 Baudrate
13
14
#define UART_BAUD_SELECT (F_CPU/(UART_BAUD_RATE*16l)-1)  // Berechnung des Inhalts des UBBR-Registers
15
16
typedef unsigned char  BYTE;              // Datentypdefinitionen
17
typedef unsigned short  WORD;              // braucht man nicht unbedingt
18
19
20
21
int main (void)                      // Anfang Hauptprogramm
22
{
23
24
25
    UBRRH = UART_BAUD_SELECT;              // Baudrate einstellen
26
27
  UCSRB = (1<<RXEN)|(1<<TXEN);
28
29
    DDRB = 0xff;                    // Port B als Ausgang konfigurieren
30
31
    while(1) {
32
33
    if (UCSRA & (1<<RXC)) {                 // Bit RXC im UCSRA gesetzt ?
34
        switch (UDR) {                      // Datenregister auslesen
35
            case 'noteon':                // Note an abfragen
36
37
               
38
                break;
39
            case 'a':                  // Note a abfragen
40
         PORTB |= (1<<PINB0);           // Pinb0 von PortB auf high setzen
41
        PORTD |= (1<<PIND6);          // Pinb6 von PortD auf high setzen  
42
      _delay_ms(180);                  // .18 sek warten
43
                PORTB &=~ (1<<PINB0);          // Pinb0 low setzen
44
                PORTD &=~ (1<<PIND6);          // Pinb6 von PortD auf low setzen
45
        break;
46
            default:                  // Bei allen anderen Zeichen nichts machen
47
                break;
48
    }
49
50
    }
51
  }
52
}

Und hier die Midi-Initialisierung:
1
              // midi.h
2
              // midi definitionen
3
4
#define noteon   0x90    // note an  #define noteoff 0b10000000      // note aus
5
#define oc1    0x0C    // octave +1
6
7
              // notentabelle für octave 0
8
9
#define c    0x0C    // n12 (c0)
10
#define db    0x0D    // n13 (d#0)
11
#define d    0x0E    // n14 (d0)
12
#define e    0x0F    // n15 (e0)
13
#define eb    0x10    // n16 (e#0)
14
#define f    0x11    // n17 (f0)
15
#define fb    0x12    // n18 (f#0)
16
#define g    0x13    // n19 (g0)
17
#define gb    0x14    // n20 (g#0)
18
#define a    0x15    // n21 (a0)
19
#define b    0x16    // n22 (b0)
20
#define bb    0x17    // n23 (b#0)

Falls jemand mir jemand von euch da weiterhelfen kann, wäre das wirklich 
super.
Vielen Dank schon mal fürs durchlesen
Paula

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> case 'noteon':         // Note an abfragen
Wozu die Hochkommas?

> (1<<TXEN)
Warum schaltest du den Sender ein?

> #define a    0x15    // n21 (a0)
Du definierst damit das kleine Ascii-a um. Willst du das?

Sieh dir mal die Warnungen des Compilers genau an. Da kommen sicher 
welche. :-/

von der mechatroniker (Gast)


Lesenswert?

> Du definierst damit das kleine Ascii-a um. Willst du das?

Tut er doch gar nicht.

a ist nun 0x15
'a' bleibt 'a'

von der mechatroniker (Gast)


Lesenswert?

> 'a' bleibt 'a'

Ergänzung: deswegen stören auch die Hochkommas bei case 'noteon'.

von bronko (Gast)


Lesenswert?

Hi.
Hab deinen Code jetzt nicht im Detail angeschaut, aber hier meine 
MidiInit - die ist getestet und für gut befunden ;)

void uart_as_midi_in(void)
{
        /*Baudratenfaktor berechnen und setzen*/
  u32 baudrate = 31250;
  u16 bauddiv = ((F_CPU+(baudrate*8L))/(baudrate*16L)-1);
  outb(UBRRL, bauddiv);
  #ifdef UBRRH
  outb(UBRRH, bauddiv>>8);
  #endif
  UCSRB |= (1<<RXEN);    //Empfang einschalten
}

Gruß

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

der mechatroniker schrieb:
> 'a' bleibt 'a'
Richtig, ein ASCII-a bleibt ein ASCII-a.
Soweit reicht das define zum Glück nicht  ;-)
Ich habe das mal ausprobiert:
1
#define a 0x15
2
#define b 'b'
3
4
int main(int argc, char* argv[])
5
{
6
   printf("%c %c   %c %c   \n", a, 'a', b, 'b');
7
}
Ausgabe:   § a   b b


Bleiben also die Hochkommas...

von Michael W. (retikulum)


Lesenswert?

UBRRL muss 0 sein? UBRRH muss 0 sein und UBRRL muss 15 sein.

Michael

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

>>>>> UBRRH = UART_BAUD_SELECT;              // Baudrate einstellen
> UBRRL muss 0 sein? UBRRH muss 0 sein und UBRRL muss 15 sein.
Auf jeden Fall sollten beide was abbekommen... ;-)
Ich würde das so probieren:
UBBRH = UART_BAUD_SELECT >> 8;
UBBRL = UART_BAUD_SELECT & 0xff;

von Karl H. (kbuchegg)


Lesenswert?

Lothar Miller schrieb:
> der mechatroniker schrieb:
>> 'a' bleibt 'a'
> Richtig, ein ASCII-a bleibt ein ASCII-a.
> Soweit reicht das define zum Glück nicht  ;-)

Trotzdem würde ich das als nicht so wahnsinnig glückliche Idee 
bezeichnen.
So einbuchstabige Variablennamen kommen in Funktionen schon mal vor, 
ohne dass man sich darüber Gedanken macht, welche Makros da jetzt noch 
ein Wörtchen mitzureden haben. Gerade bei Makros ist die Erfahrung 
eigentlich die: Den Namen lieber so wählen, dass es nur unter sehr 
aussergewöhnlichen Umständen zu Verwechslungen kommen kann.

Was spricht gegen
1
#define NOTE_ON 0x90
2
#define NOTE_a  0x15

dann hat man in der Verwendung
1
       switch (UDR) {                      // Datenregister auslesen
2
            case NOTE_ON:                // Note an abfragen
3
                break;
4
5
            case NOTE_a:                  // 
6
  ...

und das wäre IMHO eigentlich sehr gut im Code lesbar. Und nur darauf 
kommts an. Das Makro kann kompliziert sein wie Sau, in der Verwendung 
des Makros im Code muss sich der Sinn des Makros (die Aussage) auch 
einem Blinden mit Krückstock in 5 Meter Entfernung erschliessen. Und da 
steht jetzt ja eigentlich schon fast im Klartext: wenn der Inhalt von 
UDR (also das empfangene Zeichen) der Note a entspricht, dann ....

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.