2

I'm trying to send a character 'a' with termite to my AVR via a USB-to-serial cable. This has worked before, but after a while atmel studio didn't show the controller as a device, I had to update atmel studio to a later version to recognize the controller. I probably changed the code somewhere along the way to try so I'm not sure if the code is correct anymore.

It's a really simple program for receiving the first char that arrives:

#include <avr/io.h>
#include "initialize.h"
#include "constantComfort.h"

char receivedchar;

void USART_receive_char(void){
    /* wait for data to be received */
    while( !(UCSR0A & (1<<RXC0)) );

    receivedchar = UDR0;
}

int main(void)
{
    init(0.5); //0.5 for interruptcycle in seconds
    USART_receive_char();
    writeLong(receivedchar,1);
}

The write-long can write 'a' as the ascii-code 97 if I insert it directly, but when I try to receive 'a' or other chars it just shows 0.

The initialization of the AVR looks like this, and I am pretty sure I have set the termite-program accordingly. 9600 BAUD, 8 data-bits, 1 stop-bit, no parity.

//USART (for Serial connection to computer)
    #define F_CPU       1000000
    #define BAUDRATE    9600                            // 9600 bits/sec
    #define BAUD        ((F_CPU)/(BAUDRATE*16UL)-1)     // from formula

    /* enable USART0 module */
    PRR = (0<<PRUSART0);

    /* set baud rate to  defined baudrate*/
    UBRR0H = (BAUD>>8);
    UBRR0L = (BAUD);

    /* enable receiver and transmitter */
    UCSR0B |= (1<<RXEN0)|(1<<TXEN0);

    /* set frame format: 8 data bits, 1 stop bit (always 1 start bit)*/
    UCSR0C |= (0<<USBS0)|(3<<UCSZ00);

I am rather sure that this is all the code that affects this problem. I have gone through the manual for register names so I believe the initialization is correct.

Anyone have an idea what to do with this problem?

dekuShrub
  • 466
  • 4
  • 20
  • 1
    if you have an oscilloscope you can check the lines for the signal. maybe this is a problem of the hardware connectivity... – ralf htp Mar 01 '16 at 13:28
  • Yeah I can probably try that at the lab. Would be nice if it wasn't a hardware problem though. – dekuShrub Mar 01 '16 at 13:46
  • 1
    Is this your actual code? Your compiler should complain since you call `USART_receive_char(receivedchar);` while in the function definition it doesn't take an argument – Ctx Mar 01 '16 at 14:00
  • 3
    `PRR = (0< – Ctx Mar 01 '16 at 14:01
  • @Ctx It didn't complain about the argument. Didn't help to change it though (will edit in a second). Setting `PRUSART0` to 1 shuts down the USART. It is probably 0 by default, I set it to 0 to be sure. – dekuShrub Mar 01 '16 at 14:36
  • to try if the USART receives anything can you read the **Receive Complete Flag** ------------- The USART Receiver has one flag that indicates the Receiver state. The Receive Complete (RXCn) Flag indicates if there are unread data present in the receive buffer. This flag is one when unread data exist in the receive buffer, and zero when the receive buffer is empty (i.e., does not contain any unread data) (datasheet) ------------- you read the receiver error flags ? – ralf htp Mar 01 '16 at 16:16
  • Your post has a bug: "with termite to my AVR". See [termite](https://en.wikipedia.org/wiki/Termite) ;-) – chux - Reinstate Monica Mar 01 '16 at 19:01
  • @chux Are you sure a termite is a bug? ;-) – JimmyB Mar 02 '16 at 14:32
  • @Hanno Binder Well the [supposed first bug](https://en.wikipedia.org/wiki/Software_bug#Etymology) was a moth - your call. ;-) – chux - Reinstate Monica Mar 02 '16 at 14:37

2 Answers2

2

the code seems to be correct except

 PRR = (0 << PRUSART0); // i think this does not work

instead try this

 PRR &= ~(1 << PRUSART0); 

then to enable the USART receive interrupt try this

 #include <avr/interrupt.h>
 #include <inttypes.h>

 sei(); //global interrupt enable
 UCSR0B |= (1 << RXCIEn); //USART receive interrupt enable (datasheet page 195)

 ISR(USART_RXCn) (datasheet page 57)
 {
 //LED_on switch ON or OFF one of your leds if the receive interrupt is triggered by incoming data from termite
 }

for the BAUD rate try this (datasheet page 176)

 UBRRH0 = (unsigned char)(BAUD>>8);
 UBRRL0 = (unsigned char)BAUD; // the type-casting to unsigned char
ralf htp
  • 9,149
  • 4
  • 22
  • 34
  • `PRR = (0 << PRUSART);` does work. But I should probably write `PRR |= (0 << PRUSART0);` to not overwrite other bits. Also I'm using busy-waiting in main thread, so interrupt is not of any use. Good ideas though! And I will need interrupt later, so thanks :) – dekuShrub Mar 02 '16 at 21:31
  • 1
    no, not `PRR |= (0 << PRUSART0);`. The `|`-operator is a logical OR and `PRR |= (0< – ralf htp Mar 02 '16 at 21:46
  • Yes, that's true... My bad! – dekuShrub Mar 02 '16 at 22:01
1

atmega169p has 8 MHz clock-frequency

I had read that in "low power consumption" mode the avr will have a clock-frequency of 1 MHz and somehow thought it was the default.

By default atmega169p has 8 MHz clock frequency without prescaling, so the baud calculation is wrong and I assume the avr didn't read fast enough because of this, thereby receiving '0'.

Correct code snippet:

    //USART (for Serial connection to computer)
    #define F_CPU       8000000 //>>>>>>>>>>  THIS ONE!  <<<<<<<<<<<<
    #define BAUDRATE    9600                            
    #define BAUD        ((F_CPU)/(BAUDRATE*16UL)-1)     

Changing to 8 MHz like in this code snippet solved my problem.

Thanks for the help with other potential problems in my code!

dekuShrub
  • 466
  • 4
  • 20