USART on ATmega328p not functioning [Solved]

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

Hi,

This issue has been driving me crazy for several days. I've not worked with Atmel devices much before (aside from some tinkering with existing stuff, they are new to me) so I'm expecting it to be a rather dumb/boneheaded issue that I've overlooked somewhere.

 

I'm trying to get the UART to work, it is currently in local loopback, and I've tried numerous code examples including that in the datasheet but to no avail. I'll point out I've tried this on 2 devices so I'm confident it's not a busted device. As expected all the code examples I've found are pretty similar, and I've not found any evidence that anyone else has had this issue.

 

I'm using Atmel Studio 6.2 with an Atmel-ICE attached. (I know the connections are working as I've had it flipping an LED as a proof of execution)

 

I've boiled the code down to just this which I believe is the minimum, and stepped through it in the debugger (as well as having a logic analyser attached which is not showing any activity.)

Anyway, I've noticed today that non of the registers in the IO View for the USART peripheral are changing.

 

Can someone give me pointer to what my issue is.

 

Thanks

 

#include <asf.h>
#include <avr/io.h>

static volatile uint8_t rx_byte = 0x55;
int USART_Test(void);

int main (void)
{

 board_init();
 sysclk_init();
 
 // Initialise Delay
 delay_init(F_CPU);

 USART_Test();
}


int USART_Test(void)
{
 // Initialise Delay
 delay_init(F_CPU);
 
 // Initialise USART
 #define CLK  1000000UL  /* aka FOSC -- using internal oscillator (8 MHz) - redefined here for debug purposes */
 #define DIVISOR  16
 #define BAUD_RATE 4800
 #define BRR   ((( CLK / DIVISOR ) / BAUD_RATE ) - 1)  /* UBBR = 103 @ 8MHz & 12 @ 1MHz */
 #define BYTE_SHIFT 8
 #define ENABLE  1
 #define STOP_BITS 0  // 0 =  1 stop bit
 #define CHAR_SIZE 3  // 3 = 8 bit characters
 UBRR0H = (unsigned char)(BRR >> BYTE_SHIFT);
 UBRR0L = (unsigned char)(BRR);
 
 UCSR0B = (ENABLE << RXEN0) | (ENABLE << TXEN0) | (ENABLE << TXCIE0) | (ENABLE << RXCIE0); // Tx on, Rx On, Tx Complete Interrupt on, Rx Interrupt on
 UCSR0C = (STOP_BITS << USBS0) | (CHAR_SIZE << UCSZ00);
 
 Enable_global_interrupt();
 
 while(1)
 {
  delay_ms(250);
  
  while ( !( UCSR0A & (ENABLE << UDRE0 )) ) ;
  UDR0 = rx_byte;
  
 }
 
 return 0;
}

// Rx Complete
ISR(USART_RX_vect)
{
 // USART Rx
 rx_byte = UDR0;
}

// Tx Complete
ISR(USART_TX_vect)
{
 // Do nothing - simply here to enable a breakpoint in the ISR
 static volatile uint8_t b = 0;
 b++;
}

Edit:

Fuse Values are:  E:0xFF  H:0xD9  L:0xA2

This topic has a solution.

Last Edited: Mon. Mar 30, 2015 - 06:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would first try some simplier code.

You can test the folowing with a PC terminal.

It echoes what you type on the keyboard.

 

// UART test
// Atmega88, 8 MHz 
#include <avr/io.h>

//------------------------------------------------------------
void uart_init( unsigned int baud )
{
      /* Set baud rate */
      baud = (F_CPU / (16UL * baud)) - 1;
      UBRR0H = (unsigned char)(baud>>8);
      UBRR0L = (unsigned char)baud;
      /* Enable receiver and transmitter */
      UCSR0B = (1<<RXEN0)|(1<<TXEN0);
}

//------------------------------------------------------------
void uart_putc( unsigned char data )
{
      /* Wait for empty transmit buffer */
      while ( !( UCSR0A & (1<<UDRE0)) )
      ;
      /* Put data into buffer, sends the data */
      UDR0 = data;
}

//------------------------------------------------------------
unsigned char uart_getc( void )
{
      /* Wait for data to be received */
      while ( !(UCSR0A & (1<<RXC0 )) )
      ;
      /* Get and return received data from buffer */
      return UDR0;
}

unsigned char byte;
//------------------------------------------------------------
int main()
{
   uart_init(4800);   // baud = 4800

   while(1)
   {
      byte = uart_getc();
      uart_putc(byte);
   }
}

 

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

Oatcake, Are you getting any output for your code???

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

Usual sequence is 1) flash ked on for 1 sec, off for 1 sec. If it takes 8 sec to flash, internal clock fuses are snafu. 2) init baud to some std baud rate, send UUUUU in a loop. See if you can see this on teraterm. 3) now you know getchar and inituart work. If getchar putchar doesnt work, my money is on getchar.

 

Imagecraft compiler user

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

I wasn't getting any output at all (aside from a flashing test LED which was giving me the timing I expected [within a couple dozen milliseconds which is accounted for by the other code])

 

I've tried the code posted by Visovian and that gave me some output on the scope (quick check of the registers stepping through the code and hey presto).

Quickly lashing it onto a Rasp Pi and I've finally got some output.

 

I'll work through my code in slower time to see if I can spot the problem, although first glance through and aside from the interrupt enabling, I'm not spotting much difference - it's just irritating as I thought I'd copied it almost verbatim from the datasheet with adjustments for debugging the problem.

 

If I work out the problem in the next day or so I'll post it here, it may help someone else with a similar issue.

 

Thanks all

 

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It was all down to the Power Reduction Register which is part of the default calls inserted into main() when using the ASF wizard.

 

By default, calling  

 sysclk_init();

all the peripheral clocks are turned off. The clock for those modules/peripherals you want to use then need to be turned on.

You can do this by either calling the function as below (there is also a function to disable the module aswell)

void sysclk_enable_module(enum power_red_id port, uint8_t id);

// Enable USART module
sysclk_enable_module(POWER_RED_REG0, PRUSART0_bm);

or by bit toggling (for USART0)

PRR = ~(1 << PRUSART0);

I then had an issue with the clock frequency (and it being prescaled in the code)

in src/config/conf_clock.h modify

#define CONFIG_SYSCLK_PSDIV         SYSCLK_PSDIV_8

to

#define CONFIG_SYSCLK_PSDIV         SYSCLK_PSDIV_1

which will disable the prescaler.

 

With these modifications, by original code works.