ATtiny45 & ATtiny44 SPI communication using USI.
Hi, can anyone help me to make the USI(Universal Serial Interface) of ATtiny44 and ATtiny45 to work as SPI. I have tried using arduino IDE with addition 3rd party boards, it failed to compile so I wrote some code using AVR-libc. This is the code I am using for both Master and Slave:
#define F_CPU 1000000UL
#include <avr/io.h>
//#include <avr/iotn44.h>
#include <util/delay.h>
#define True 1
#define False 0
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define USI_MOSI PINB0
#define USI_MISO PINB1
#define USI_SCK PINB2
#define USI_SS PINB4
#define USI_DDR DDRB
#define USI_PORT PORTB
void USI_SPI_init(uint8_t);
void USI_SPI_transfer(uint8_t);
uint8_t USI_SPI_receiver(void);
void USI_SPI_init(uint8_t mode){
if(1 == mode){ // Master mode
// configure USI pins: MOSI, SCK, SS as outputs
USI_DDR |= (1<<USI_MOSI) | (1<<USI_SCK) | (1<<USI_SS);
// set SS high
USI_PORT |= (1<<USI_SS);
// Configure MISO as an input & enable pull-up resistor
USI_DDR &= ~(1<<USI_MISO);
//USI_PORT |= (1<<USI_MISO);
// Clear OVF interrupt flag
USISR |= (1<<USIOIF);
USICR |= (1<<USIWM0) | (1<<USICS1) | (1<<USICLK) | (1<<USITC);
}
else if(0 == mode){ // Slave mode
// Configure USI pins: MISO, SCK, SS as input & MOSI as output
USI_DDR &= ~(1<<USI_MISO) | (1<<USI_SCK) | (1<<USI_SS);
USI_DDR |= (1<<USI_MOSI);
USI_PORT |= (1<<USI_MISO) | (USI_SCK) | (USI_SS);
// Configure 3-wire Slave mode, enable OVF interrupt
USICR = (1<<USIWM0) | (1<<USIOIE) | (1<<USICS1);
}
else{
DDRB |= (1<<PINB0);
PORTB |= (1<<PINB0);
}
}
void USI_SPI_transfer(uint8_t dataIn){
// Set SS pin LOW
USI_PORT &= ~(1<<USI_SS);
// Load the data in USI data reg.
USIDR = dataIn;
do{
// Toggle the SCK pin
USICR |= (1<<USIWM0) | (1<<USICS1) | (1<<USICLK) | (1<<USITC);
}while(!(USISR & (1<<USIOIF)));
// Set back USI_SS pin HIGH
USI_PORT |= (1<<USI_SS);
}
uint8_t USI_SPI_receiver(void){
USISR |= (1<<USIOIF);
while(!(USISR & (1<<USIOIF)));
// Return USI buffer reg. content
return USIDR;
}
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(){
DDRB &= ~(1<<PINB3);
PORTB |= (1<<PINB3);
USI_SPI_init(1);
uint8_t count = 0;
while(True){
if (bit_is_clear(PINB, 3)){
count += 1;
if (count >= 400){
USI_SPI_transfer(1);
count = 0;
}
}
_delay_ms(100);
}
}
The main() part is for Master. I would like some advice on how to make it work.