Atmega1284P UART not working, help needed!

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Guys!

 

I am working on a MIDI interface with an Atmega1284P using U(S)ART 0. I have tried to, not enable TXEN0 and toggle the output, works fine, but when I enable the USART0 I can't get it to react (measuring with an oscilloscope) at PD1)). I just seem to stay on +5V.

 

The initialization is this: 

 

 

 

#define F_CPU 20000000UL

#define MIDI_BAUDRATEVAL 31250

 

void midiInit(){
    
    //set up USART
    
    UCSR0B =  (1<<TXEN0);
    UCSR0C = (1<<UCSZ00) | (1<<UCSZ01); //8 bit, 1 stop, no parity
    // Set the baud rate
    unsigned int baudrate;
    baudrate = (((F_CPU / (MIDI_BAUDRATEVAL * 16UL))) - 1);
    MIDI_UBRRL = (unsigned char) baudrate;
    MIDI_UBRRH = (unsigned char) (baudrate >> 8);
}

 

 

This is the execution:

 

int main(){
...

sendMidiData(0xE0); //controller midi ch0
            sendMidiData(0xE5); //random controller number
            sendMidiData(0xE7);  //random value
            displayValue(test);
....
}

Of this:

void sendMidiData(uint8_t midiVal){
    
    while((UCSR0A & (1<<UDRE0)) == 0);
    UDR0 = midiVal;
    test++;
} 

 

The 'test' value displays fine on my display, and raises by 3 every time I execute the 'sendMidiData()'.  

 

Hope someone can help! 

 

All the best!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The 1284 is known to have issues with high end crystals. Apart from anything else you must make sure the "full swing" option is selected. A search for something like "1284p crystal problem" may prove fruitful.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Swap these two around...

 

    MIDI_UBRRL = (unsigned char) baudrate;
    MIDI_UBRRH = (unsigned char) (baudrate >> 8);

...to give...

 

    MIDI_UBRRH = (unsigned char) (baudrate >> 8);
    MIDI_UBRRL = (unsigned char) baudrate;

See the datasheet for why.

 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Clawson I believe the full swing option is selected. This is the fuse setting: 

FUSES      = -U lfuse:w:0xE7:m -U hfuse:w:0xD1:m -U efuse:w:0xfD:m

I will google the 1284p crystal problem thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:

Swap these two around...

 

    MIDI_UBRRL = (unsigned char) baudrate;
    MIDI_UBRRH = (unsigned char) (baudrate >> 8);

...to give...

 

    MIDI_UBRRH = (unsigned char) (baudrate >> 8);
    MIDI_UBRRL = (unsigned char) baudrate;

See the datasheet for why.

 

 

Thanks! Have switched them. No result though..

Last Edited: Tue. Feb 17, 2015 - 04:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

oleoleo2 wrote:

Hi Clawson I believe the full swing option is selected. This is the fuse setting: 

FUSES      = -U lfuse:w:0xE7:m -U hfuse:w:0xD1:m -U efuse:w:0xfD:m

I will google the 1284p crystal problem thanks!

 

Well. It Seems like the "full-swing crystal problem people" have some different problems, as far as I have read. I have a display (tripple multiplexed 7-segment) and some diodes attached with a mux. And the entire system really seems to run rock-steady. It doesn't lock up either when trying to use the UART. But I can't sense anything with an oscilloscope on the output when activating the UART (or a MIDI monitor). 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've just tried your code on a real 1284P sitting here in a customers unit and I get data out of UART0.

 

One thought...what are your MIDI_UBRRL and MIDI_UBRRH defined as?

 

Now to put the customers unit back to doing what is should!

 

 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What I was suggesting was that your AVR may not be running at the speed you think it is. The usual test is to sit in a loop sending 'U' at 8-N-1. That produces an easy to observe 101010101010101.... bit stream. You then use a frequency meter, logic analyser or oscilloscope to measure the TXD bit width. For 31250 baud the bit width should be 1/31250 = 32us. Is this what you observe or is it a "little off" or is it "hugely off"?

 

EDIT: forgot to say that the 1284P also has CKOUT fuse and CLKO pin. So another approach is simply to set that fuse and see if you have an exact 20MHz on the pin.

Last Edited: Tue. Feb 17, 2015 - 04:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:

I've just tried your code on a real 1284P sitting here in a customers unit and I get data out of UART0.

 

One thought...what are your MIDI_UBRRL and MIDI_UBRRH defined as?

 

Now to put the customers unit back to doing what is should!

 

 

This:

#define    MIDI_UBRRH    UBRR0H
#define MIDI_UBRRL    UBRR0L

 

Hmm...that's a little bit scary that you actually get something out from the UART0.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

 Is this what you observe or is it a "little off" or is it "hugely off"?

 

 

 

 

Well pretty much off :) I observe +5V at the PD1 and nothing else. Have anybody heard of a broken UART before? Just wondering..

I will make some frequency analysis when I get home later tonight, but I just though I should be able to measure SOME activity on the PD1 even if the frequency is wrong?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is my code which is sending data out on PD1 (pin15 on a DIP package).

 

(note, I use codevision as a compiler so my includes look a bit different)

 

#include <io.h>
#include <stdio.h>
#include <stdint.h>

#define F_CPU 11059200UL
#define MIDI_BAUDRATEVAL 31250


void sendMidiData(uint8_t midiVal){
    while((UCSR0A & (1<<UDRE0)) == 0);
    UDR0 = midiVal;
}

void midiInit(){

    unsigned int baudrate;
    //set up USART

    UCSR0B =  (1<<TXEN0);
    UCSR0C = (1<<UCSZ00) | (1<<UCSZ01); //8 bit, 1 stop, no parity
    // Set the baud rate

    baudrate = (((F_CPU / (MIDI_BAUDRATEVAL * 16UL))) - 1);

    UBRR0H = (unsigned char) (baudrate >> 8);
    UBRR0L = (unsigned char) baudrate;

}

void main(void)
{
	midiInit();

	while (1)
	{
		sendMidiData(0xE0); //controller midi ch0
		sendMidiData(0xE5); //random controller number
        sendMidiData(0xE7);  //random value
	}
}

 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And if I adjust the baudrate #define to 19200 then I can see correct data on the pin as decoded by my scope's inbuilt serial analyser.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try changing this: 

while((UCSR0A & (1<<UDRE0)) == 0);

 

to

while((UCSR0A & (1<<UDRE0)) == 1);

 

and see what happens.    The flag UDRE0 is set (1) when register is empty and ready for next char.

 

Jim

 

 

Edit, sorry, ignore, your spinning on flag not set!!   Duh!

 

 

 

Keys to wealth:

Invest for cash flow, not capital gains!

Wealth is attracted, not chased! 

Income is proportional to how many you serve!

 

Last Edited: Tue. Feb 17, 2015 - 06:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:
Swap these two around...

.

.

.

See the datasheet for why.

Actually it doesn't matter.  Although it is a 16-bit register, UBRRn doesn't have a temporary register for the high byte in UBRRnH (like the 16-bit timer registers).

 

The only restriction:

The USART Baud Rate Register (UBRRn) and the down-counter connected to it function as a programmable prescaler or baud rate generator. The down-counter, running at system clock (fosc), is loaded with the UBRRn value each time the counter has counted down to zero or when the UBRRLn Register is written. A clock is generated each time the counter reaches zero.

The worst case is that the first clock period runs at the previous UBRRn value.  Since there at 8 or 16 clock periods per bit time, it's unlikely that even the first bit of the first frame would be adversely affected.

 

In any event, why write to UBRRnL and UBRRnH separately?  The toolchain provides 16-bit access via UBRRn.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Tue. Feb 17, 2015 - 11:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But 31250 is the baudrate. 20,000,000/31250 is 640 decimal. 640/16 is 40. 0x28 hex. Try that in the baud lo reg?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@oleoleo2

 

Since it's clear that something odd is going on here I suggest you strip it back and start again.

 

1) Knock up a bit of code that toggles the pin at 1Hz.

2) Take the minimal code that is needed to send data out of the USART; for example my code (with adjustments for gcc) above.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey Thanks a lot for all the good inputs all of you! There have been some progress. I am sending 0xAA in a while(1) loop to the UART. I can actually measure this with the oscilloscope! So I guess there are two issues left here: One: my oscilloscope is to slow, and Two: something might be wrong with the timing as the MIDI monitor does not get the bytes. I will investigate and return!  

 

Last Edited: Wed. Feb 18, 2015 - 10:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have we established that your MPU is actually running at 20MHz?

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:

Have we established that your MPU is actually running at 20MHz?

 

I just made a measurement with these settings; 

void timerInit(void){
	
	//Timer0 -
	TCCR0B = (1<<CS00) | (1<<CS02); //prescaling 1024 //prev was (1<<CS00) | (1<<CS01) = 64
	TCNT0 = 0;
	TIMSK0 = (1<<TOIE0); //timer 0 overflow interrupt enable
		
}
ISR(TIMER0_OVF_vect){
		
	if (bit_is_set(PORTD,PD1)){
		CLEARBIT(PORTD,PD1);
	} else {
		SETBIT(PORTD,PD1);
	}
	timeCounter++;
	
	
	//updateDisplay();                               //remember to comment this in again!!!!!!!!!!!!!!!
}

So if the conditions are right: Clk = 20*10^6, Division = 1024, Timer0 = 8-bit. I toggle the bit on every overflow so the result should be divided with 2 in the end.

(20*10^6/1024*256)/2 = 38.147Hz (sorry for the messy math, but I think it makes the way of thinking clearer, not to reduce).

 

The oscilloscope says 38.14 to 38.15Hz. So it seems pretty clear on the spot. I can read the data via a Logic Analyzer (Salae). I'm going to check the hardware connections. I could maybe have "mirrored" some pins in the MIDI connector or something..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I got it up and running! Thanks for your great support :)

 

I made and "open cable expander" and measured the communication from an existing MIDI controller with a logic analyzer. After that, copied that data. Apparently my MIDI monitor software was not displaying invalid MIDI data (even though it said it would :)