I was messing with the same stuff and found no pre-fab code around.
it’s not much, but it should be enough to work with:
/*
simple USI implementation for WINAVR with interrupts
for ATTiny2313, basid on Atmel Application Note 319
Eric Toering - 25-3-2008
*/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
unsigned char output;
void blink ( void) {
PORTB |= 0x01; // turn LED on
_delay_ms(100); // wait 100 mS
PORTB &= FE; // and off again
_delay_ms(100);
}
int main(void){
PORTB = 0x00; // reset PORTB
DDRB |= 0x01; // make PB0 output (for LED)
TCCR0A = 0; // Timer0 settings
TCCR0B = 0b00000001; // Turn on Timer0 with no prescaling: every 1/(Fosc/256) Sec overflow
// So with 12 Mhz: 12000000/256 * 2 is 23437 bits/S
TIMSK = 0b00000000; // Timer interrupts
USIDR = 0x00; // clear USI register
DDRB |= (1<<PB6) | (1<<PB7); // Outputs.
DDRB &= ~(1<<PB5); // Inputs.
PORTB |= (1<<PB5); // Pull-ups.
USICR = (1<<USIOIE) | (1<<USIWM0) | // enable usi three wire master mode, overflow interrupt
(1<<USICS1) | (0<<USICS0) | // setup on rising edge, using clock strobe
(1<<USICLK);
sei(); // turn on interrupts
while(1){
if( (USISR & 0x0F) != 0 ) { // test if no transmission is blocking
blink(); // otherwire blink led
}
USIDR = 0x55; // <---- this is the data that is sent
TCNT0 = 0x00; // reset Timer0
TIMSK |= (1<<TOIE0); // turn on Timer0 interrupt
_delay_ms(45); // wait 45 mS and do it all again
}
}
ISR(TIMER0_OVF_vect){
USICR |= (1<<USITC); // Toggle clock output pin
}
ISR(USI_OVERFLOW_vect){
TIMSK &= ~(1<<TOIE0); // turn off Timer0 interrupt
USISR = (1<<USIOIF); // clear USI transmission flag
output = USIDR; // <----- this is the data that is received
}