NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » MIDI over USART - Help

March 07, 2010
by jban4us
jban4us's Avatar

Hi everyone!

I'm working on a project that requires communicating with other devices over MIDI. I'm modifying a library found here that was written for ATmega8. Mostly I have it working, but working on receiving messages I've run into a problem.

I've gotten receiving messages to work by polling, but I want it to work off of interrupts. The original library used an interrupt for receiving but I took it out and used polling to see if my midi circuit was correct.

Here is the initialization code:

void midiInit(uint16_t clockSpeed, bool out, bool in){
    // Set baud rate
    uint8_t MYUBRR = 29;//(uint8_t)(clockSpeed/16.0f/MIDI_BAUD);
    UBRR0H = (uint8_t)(MYUBRR   >> 8);
    UBRR0L = (uint8_t)(MYUBRR & 0xFF);
    // Enable transmitter
    if(out)
        UCSR0B |= (1<<TXEN0);
    if(in) {
        //Enable receiver
        //RX Complete Interrupt Enable  (user must provide routine)
        UCSR0B |= ((1<<RXEN0) | (1<<RXCIE0));
    }
    //Set frame format: Async, 8data, 1 stop bit, 1 start bit, no parity
    //needs to have URSEL set in order to write into this reg
    //UCSR0C = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
    UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); // we don't need the URSEL register
}

Main program file:

volatile uint16_t cnt;

//the midi input interrupt handler
ISR(USART_RXC_vect){
    uint8_t inByte;
    inByte = MIDI_IN_GET_BYTE;
//  if(inByte == 0xF8) // increment if a midi clock message
        cnt++;

}

int main(void) {
    // fire up the LCD
    lcd_init();
    lcd_home();

    //init the byte count
    cnt = 0;

    lcd_line_one();
    lcd_write_string(PSTR("Initializing"));

    //init midi
    midiInit(F_CPU, false, true);

    //enable interrupts
    sei();

    lcd_line_one();
    lcd_write_string(PSTR("Initialized  "));

    while(1);
}

The problem is that when I turn it on, it says "Initializing" initializes the USART and then says "Initialized". But if I plug in the midi cable, it starts to flash "Initializing" over and over, and continues to do so even after removing the cable. It appears that something is happening to cause it to restart repeatedly.

Any help would be appreciated, I've searched all over and it looks like I'm doing it right, but there is clearly a mistake somewhere!

Thanks!

March 07, 2010
by jban4us
jban4us's Avatar

Oops i forgot to mention that when i compile it gives a warning:

warning: 'USART_RXC_vect' appears to be a misspelled signal handler

Looking at the data sheet this appears to be the right interrupt vector though, so I am not sure if this is the cause of the problem.

March 07, 2010
by Rick_S
Rick_S's Avatar

I'll assume you are using an ATMega168 as supplied in the standard Nerdkit. If that is the case, your ISR is incorrect.

Instead of

ISR(USART_RXC_vect){
                    }

You should have

ISR(USART_RX_vect){
                    }

Now is you are using an ATmega16, ATmega32, ATmega323, or ATmega8 then it would be correct as you have it written.

If you hadn't found it already, the complete list of innterupts available for any given micro is available at the avr-libc: Documentation Site.

I'm not very proficient at C still so as to any other problems, I sorry if I can't be of much help.

BTW, what are you trying to build?? Sounds interesting. It would be neat to turn my Kawai electronic piano into a player piano with songs of my choice...

Good luck!

Rick

March 07, 2010
by jban4us
jban4us's Avatar

Thanks! I am using the ATMega168. I changed the ISR to the correct one, and now it's receiving via interrupt. Thanks for the link too, it should be helpful in the future. Looking at the ATMega168 data sheet I found:

0x0024    jmp    USART_RXC    ; USART, RX Complete Handler

under the "Interrupt vectors in ATmega168" section, so I thought that's what it was. Perhaps avr-libc just uses USART_RX_vect instead for some reason?

I'm building a control box for custom lighting effects for a DJ setup, to be controlled over MIDI via midi clock from Traktor and manually with an alesis micron.

Post a Reply

Please log in to post a reply.

Did you know that a thermometer can be made "faster" by using a bit of math? Learn more...