jenswilly.dk


SPI and USI

The Max 7219 chip communicates using SPI. The last time I used it I had apparently written my own bit-banging SPI routine in the Arduino IDE. Which works just fine (the SPI protocol being so simple) but it seems clunky. And since the ATTiny2313 has a built-in USI (Universal Serial Interface) capable of doing SPI I thought I might as well use that.

After a bit of Googling and reading of the datasheet, this is what I came up with:

#define PIN_LOAD PB4

// Utitlity method to shift 8 bits out the USI pins in 3-wire (SPI) mode
static unsigned char spiByte(unsigned char val) 
{ 
    USIDR = val;            // Set data byte to send
    USISR = (1<<USIOIF);    // Clear Counter Overflow Interrupt Flag (by writing 1 to the USIOIF bit)
    do
    { 
        USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);    // 3-wire mode; shift reg. clock source: external pos. edge; 4-bit counter source: USITC; Toggle USICK pin 0->1 or 1->0 (shift register will only clock on 0->1)
    } while ((USISR & (1<<USIOIF)) == 0);                        // Check for OIF set which will happen after 16 cycles. I.e. 8 bits since the clock toggles twice per bit.
    return USIDR;            // Return data value
}

void sendToMax7219( char reg, char value )
{
    PORTB &= ~(1 << PIN_LOAD);    // LOAD low
    spiByte( reg );
    spiByte( value );
    PORTB |= (1<<PIN_LOAD;    // LOAD high
}

Leave a Reply