The short answer is, all of the AVR's I've looked at only support 8-bit (hardware) SPI
The longer answer is, theres other ways to do it.
I've gotten a test pattern working on using an Atmega32 by bit-banging the ports.
Another thing you can do is use 8-bit SPI for 8 of the bits and bit bang the 9th bit. That works too. Below is a snippet from my test program that demonstrates the technique. It's currently non-interrupt driven, so using the hardware SPI isnt much faster than bit-banging all 9-bits. But with a little clever coding, you could probably set it up to be interrupt driven. When the interrupt is triggered for the end of one byte, you would bit bang the first bit, then put the last 8 bytes in the buffer to be written out and return. It would be a little tricky to code, but I think it could be made to work.
Bear with me on the wacky macros... I try to avoid manual bit-twiddling, and gcc optimizes this rather well.
Code: Select all
#define LCD_PORT PORTB
#define LCD_RST 0
#define LCD_CS 1
#define LCD_SDATA 5
#define LCD_SCLK 7
#define sbi(port,bit) (port |= (1<<bit)) //set bit in port
#define cbi(port,bit) (port &= ~(1<<bit)) //clear bit in port
#define SET_LCD_CS(value) ( (!(value)) ? cbi(LCD_PORT, LCD_CS) : sbi(LCD_PORT, LCD_CS) )
#define SET_LCD_RST(value) ( (!(value)) ? cbi(LCD_PORT, LCD_RST) : sbi(LCD_PORT, LCD_RST) )
#define SET_LCD_SCLK(value) ( (!(value)) ? cbi(LCD_PORT, LCD_SCLK) : sbi(LCD_PORT, LCD_SCLK) )
#define SET_LCD_SDATA(value) ( (!(value)) ? cbi(LCD_PORT, LCD_SDATA) : sbi(LCD_PORT, LCD_SDATA) )
void lcdSendCommand(uint8_t v)
{
// bit bang the first bit...
SET_LCD_SDATA(0);
SET_LCD_SCLK(1);
SET_LCD_SCLK(0);
// turn on hardware SPI
SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);
// send the 8 bits using hardware spi
SPDR = v;
while (! ((SPSR) & (1<<SPIF)))
;
// turn off hardware SPI
SPCR = 0;
}
void lcdSendData(uint8_t v)
{
// bit bang the first bit...
SET_LCD_SDATA(1);
SET_LCD_SCLK(1);
SET_LCD_SCLK(0);
// turn on hardware SPI
SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);
// send the 8 bits using hardware spi
SPDR = v;
while (! ((SPSR) & (1<<SPIF)))
;
// turn off hardware SPI
SPCR = 0;
}