Atmega328P-PU strange uart behaviour

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

Hi everybody,

 

I need a simple electronics black box that reads a decimal number from the uart, and creates a pwm wave on a pin with the desired frequency. So I decided to use an old Arduino uno R3 board, and started playng with it,. However, I'm stuck at reading uart.

I'd like to insert a byte in a buffer on every uart rx interrupt. When reading from the buffer first the reading function has to check whether there is a character avaiable. If it is then returns it, otherwise puts the microcontroller in sleep mode, waiting for next interrupt, then checks again.

 

But actually uart seems to not worki some times, so I wrote this simple test code:

#ifndef __AVR_ATmega328P__
#    define __AVR_ATmega328P__  // microcontroller
#endif
#define F_CPU 16000000      // frequency of the cpu

#include <avr/interrupt.h> // ISR macro
#include <avr/io.h> // Input/output
#include <avr/power.h> // powersave funtions
#include <avr/sleep.h> // To send cpu to sleep
#include <avr/cpufunc.h> // memory barriers

// Some utils
#define __IDLE_SLEEP() { set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode(); }
#define __NO_USART_INTERRUPTS() UCSR0B &= ~(1 << RXCIE0) /* Disables uart interrupt */
#define __USART_INTERRUPTS()    UCSR0B |= (1 << RXCIE0) /* Re-enables uart interupt */

#define BAUD 19200
#include <util/setbaud.h> // Automatically calculates baud

ISR(USART_RX_vect) // Received something
{
    uint8_t temp;
    temp = (uint8_t)UDR0; // reads the buffer and
    _MemoryBarrier(); // forces order of execution
    UDR0 = (uint8_t)temp; // Immediately replies
}

int main(void)
{
    cli(); // Clears inpterrupt

    // Powersave (reduces power consumption)
    power_all_disable(); // Disables every peripheral (such as ADC)
    power_usart0_enable(); // Only needed usart

    DDRD = 0; // Resets
    DDRD |= (1 << PORTD1); // Sets output
    DDRD &= ~(1 << PORTD0); // Sets input

    // ===============================================================
    // ============== This works, but I don't know why ===============
    DDRD |= (1 << PORTD4); // Misteriousely makes things work
    PORTD &= ~(1 << PORTD);
    // ===============================================================

    // Set baud rate; lower byte and top nibble
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;

    UCSR0C = UCSR0B = UCSR0A = 0;
    UCSR0B |= (1 << TXEN0);	// Enable TX
    UCSR0B |= (1 << RXEN0);	// Enable RX

    UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00); // 8 bit, no parity, 1 bit stop
    UCSR0C |= (1 << UMSEL00); // Enables syncronous mode
    UCSR0A |= (1 << U2X0); // Enables double speed
    UCSR0B |= (1 << RXEN0) | (1 << RXCIE0); // Enables interrupt for rx

    sei(); // Re-enables interrupts

    while (1) { // Waits for data in circular buffer
        __IDLE_SLEEP();
        asm volatile ("nop");
    }
    __builtin_unreachable();
}

Line 42 (the one highlighted) whas randomly added after some edits, and it turns out that it makes things works (i.e Arduino replies correctly to the PC each time it sends something on the uart), and if I comment it the Arduino does not reply. Does anyone of you knows why? What does PORTD4 has to do with uart? On the datasheet I can't find any reference.

When I attach a led between PORTD4 and GND it lights, even if I did't write a 1 on that port (only by setting it output), ad disabling the uart, for example via the power_usart0_disable() function, makes the pin work normally.

I also changed the Arduino board, because it might an hardware problem only of that one, but same result.

I did't connect anithimg to the Arduino, so it can't be a circuit design problem.

 

Thank you!

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

What does this do??

PORTD &= ~(1 << PORTD);
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which is probably a pretty strong argument for not using:

    DDRD |= (1 << PORTD1); // Sets output
    DDRD &= ~(1 << PORTD0); // Sets input

If you omit the digit (the only thing that is actually important here!) then you come up with a line like that. The above is surely just more readable as:

    DDRD |= (1 << 1); // Sets output
    DDRD &= ~(1 << 0); // Sets input

anyway isn't it?

 

(a 1 is a 1 is a 1 .... why dress it up as "PORTD1"?)

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

Kartman wrote:

What does this do??

PORTD &= ~(1 << PORTD);

 

Oh, you're right, it actually should be

PORTD &= ~(1 << PORTD4);

Or

PORTD &= ~(1 << 4);

It should make sure Arduino outputs a 0, however attaching a led it lights anyway, it isn't the problem.