单片机控制诺基亚2600彩屏(五)
0赞
发表于 5/24/2011 8:41:37 PM
阅读(1888)
Step 5AVR - Outputting 9-bit SPI with Inline Assembly
To implement the 9-bit protocol using an AVR, I found a nice ASM function in the SparkFun example code. I modified the code some to clean it up and adapt it for the Phillips controller. This ASM code is more efficient than using regular C and allows faster LCD writes.
It uses ATMega168 pins 11, 12, 13, and 14.
11 - Data
12 - Clock
13 - Chip Select
14 - Reset (not covered by this function)
void soft_spi_send_byte(char cmd, char data)
{
// enable chip_sel
asm("cbi %0, 7" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send the command flag bit
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 0" : : "a" (cmd));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send Bit 7 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 7" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send Bit 6 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 6" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 5 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 5" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 4 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 4" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 3 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 3" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 2 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 2" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 1 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 1" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 0 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 0" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// disable chip_sel
asm("sbi %0, 7" : : "I" (_SFR_IO_ADDR(PORTD)));
}
The following defines are used to make sending data and commands easier:
#define color_lcd_send_cmd(cmd) soft_spi_send_byte(0, cmd)
#define color_lcd_send_data(data) soft_spi_send_byte(1, data)
It uses ATMega168 pins 11, 12, 13, and 14.
11 - Data
12 - Clock
13 - Chip Select
14 - Reset (not covered by this function)
void soft_spi_send_byte(char cmd, char data)
{
// enable chip_sel
asm("cbi %0, 7" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send the command flag bit
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 0" : : "a" (cmd));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send Bit 7 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 7" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send Bit 6 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 6" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 5 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 5" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 4 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 4" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 3 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 3" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 2 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 2" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 1 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 1" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// Send bit 0 of data
asm("cbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("cbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbrc %0, 0" : : "a" (data));
asm("sbi %0, 5" : : "I" (_SFR_IO_ADDR(PORTD)));
asm("sbi %0, 6" : : "I" (_SFR_IO_ADDR(PORTD)));
// disable chip_sel
asm("sbi %0, 7" : : "I" (_SFR_IO_ADDR(PORTD)));
}
The following defines are used to make sending data and commands easier:
#define color_lcd_send_cmd(cmd) soft_spi_send_byte(0, cmd)
#define color_lcd_send_data(data) soft_spi_send_byte(1, data)
