Using USI as a UART in the ATtiny 25/45/85

Last post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am looking for some UART C code for the ATTiny85 written for AVR-GCC.

I could use AVR307(Half duplex UART using the USI Interface) but this is written for the IAR compiler.

Can anyone help with this or an alternative that uses timer-0?

thanks

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

I've just been through the exercise of converting the AVR307 code to run on a Tiny2313, using avr-gcc.

Re-working the code for avr-gcc was pretty straightforward, the main difference iirc was the naming conventions used for the ISRs and the register variable. Why don't you give it a go?

And yes, it works well. Be aware that it really is half duplex, since rx and tx share the same register. Watch out for your transmissions being interrupted by incoming rx data!

Colin

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

This is the kind of thing that I was looking for:

http://www.mikrocontroller.net/attachment/18859/USI_UART.c

from AVR307 change USI_UART_config.h to USI_UART.h

Inside USI_UART.h add lines:

#include
#include

In USI_UART.c I had to remove the '+9' from this line:
#define TIMER0_SEED (256 - ( (SYSTEM_CLOCK / BAUDRATE) / TIMER_PRESCALER ))+9

To get the transmit timing correct.

Also this declaration of USI_UART_TxData causes it to get overwritten during interrupts:

Change:
register unsigned char USI_UART_TxData asm("r15");

to:
static volatile unsigned char USI_UART_TxData;

For a loopback test, put this into the main loop:

while(USI_UART_Data_In_Receive_Buffer())
USI_UART_Transmit_Byte(USI_UART_Receive_Byte());

and in the initialise routine add this:

USI_UART_Initialise_Transmitter();

I hope this helps someone using the attiny25/45/85

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

It's better to reset prescaler after
TCCR0B = (0<<CS02)|(0<<CS01)|(1<<CS00); // start Timer0
by
GTCCR |= (1<<PSR0);

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

Thanks alot Techy, think that helped me alot, but i dont got a attiny25/45/85 at hand atm, so im trying with a ATtiny, but it seems to be some problem with the interrupt pinchange:

    GIMSK |=  (1<<PCIE);                                    // Enable pin change interrupt for PORTB
    PCMSK |=  (1<<PCINT0);									// Enable pin change interrupt for PB0

Which isn't possible for ATtiny2313... Can someone give me a hint maybe? :)

*edit*
And by the way.. Is there a special way the Tx and Rx(DI and DO ofc) needs to be connected to the chip?

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

Stevanx wrote:

    GIMSK |=  (1<<PCIE);                                    // Enable pin change interrupt for PORTB
    PCMSK |=  (1<<PCINT0);									// Enable pin change interrupt for PB0

Which isn't possible for ATtiny2313... Can someone give me a hint maybe? :)

For the 2313, use

PCMSK = (1<<PB5);

since the DI pin is on PB5 on this chip

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

why not use the uart that is inside the tiny2313 ??? saves a lot of code.

1)Datasheet and application notes checked?
2)tutorial forum
3)Newbie start here

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

meslomp, i needed two UART :-) But i've been using the Transmit only uart, which did the trick for me.

But thanks anyways Colin :)

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

I wondered why the whole thing didn't work with me. The reason: Dependent on the value of (SYSTEM_CLOCK / TIMER_PRESCALER) there are only certain baudrates permitted. Other baudrates result in garbage.

Here the baudrates for certain SYSTEM_CLOCK / TIMER_PRESCALER values:

// Baudrate at 1 MHz: 9600
// Baudrate at 2 MHz: 9600
// Baudrate at 4 MHz: 19200
// Baudrate at 8 MHz: 38400

Cheers, Volker

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

Hello, I have just reinstalled the AVR-GCC toolchain in a new Debian system. I have a couple of tiny85s, and tried to compile AVR307, per techy60's instructions from Nov.19, 2008. I modified the Makefile from one of the examples included in AVR-GCC as follows:

PRG = attinyuart
OBJ = main.o USI_UART.o
MCU_TARGET = attiny85
OPTIMIZE = -Os

DEFS =
LIBS =

# You should not have to change anything below here.

CC = avr-gcc

CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
LDFLAGS = -Wl,-Map,$(PRG).map

OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump

When I ran "make", I got the following output:

Rasputin:/usr/local/avr/avr_src/tiny85# make
avr-gcc -g -Wall -Os -mmcu=attiny85 -c -o main.o main.c
main.c:26: warning: return type of 'main' is not 'int'
main.c: In function 'main':
main.c:36: warning: implicit declaration of function '__enable_interrupt'
main.c:52: warning: implicit declaration of function '__sleep'
avr-gcc -g -Wall -Os -mmcu=attiny85 -c -o USI_UART.o USI_UART.c
USI_UART.c: In function '__vector_2':
USI_UART.c:168: warning: large integer implicitly truncated to unsigned type
avr-gcc -g -Wall -Os -mmcu=attiny85 -Wl,-Map,attinyuart.map -o attinyuart.elf main.o USI_UART.o
main.o: In function `main':
/usr/local/avr/avr_src/tiny85/main.c:36: undefined reference to `__enable_interrupt'
/usr/local/avr/avr_src/tiny85/main.c:52: undefined reference to `__sleep'
make: *** [attinyuart.elf] Error 1
Rasputin:/usr/local/avr/avr_src/tiny85#

Is this a porting issue from IAR to GCC? or is there something I missed following techy60's instructions, or setting up the makefile?
it has been a while since I last did any AVR coding and it's probably a dumb mistake but any help would be really appreciated!

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

Those sound an awful lot like IAR specific functions. Sounds like you have some porting work to be done to convert from IAR to GCC

 

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

clawson wrote:
Those sound an awful lot like IAR specific functions. Sounds like you have some porting work to be done to convert from IAR to GCC
Thanx, clawson. I reviewed interrupt.h, and sleep.h and replaced the "offending" function calls with their GCC-AVR alternatives. The program compiled without problems. Now for the "Smoke Test"........

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

Wrote a naive implementation that's probably a good starting point. Check it at my blog http://electronic-excursions.blogspot.com. It's a good place to start and pretty easy code to decipher. TX is done too and will be posted soon.

Thanks.