#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define GPIO_PB_8 24
#define GPIO_PH_4 116
#define GPIO_PH_5 117
#define GPIO_PE_11 75
#define GPIO_PE_12 76
#define SCLK GPIO_PH_4
#define MOSI GPIO_PH_5
#define CS GPIO_PE_11
#define Reset GPIO_PE_12
#define LCDPWM GPIO_PB_8
#define OUTP 1 //表示GPIO接口方向为输出
#define INP 0 //表示GPIO接口方向为输入
#define set_gpio_value gpio_set_value
#define get_gpio_value gpio_get_value
//默认为1则一直关比背光灯,默认为0一直打开背光灯
#define LCDdefault 0
//先释放一下几个gpio口为了方便以后的占用
static void spi_free_gpio(void)
{
gpio_free(MOSI);
gpio_free(SCLK);
gpio_free(CS);
gpio_free(Reset);
gpio_free(LCDPWM);
}
//申请GPIO口资源
static int spi_request_gpio(void)
{
if (gpio_request(MOSI, "spi_mosi") < 0)
{
printk("fail to request mosi\n");
return -1;
}
if (gpio_request(SCLK, "spi_sclk\n") < 0)
{
printk("fail to request sclk\n");
return -1;
}
if (gpio_request(CS, "spi_cs") < 0)
{
printk("fail to request cs\n");
return -1;
}
if (gpio_request(Reset, "spi_reset") < 0)
{
printk("fail to request reset\n");
return -1;
}
if (gpio_request(LCDPWM, "spi_lcdpwm") < 0)
{
printk("fail to request lcdpwm\n");
return -1;
}
return 0;
}
/* SPI端口初始化 用于每次传递参数 */
static void spi_init(void)
{
gpio_set_value(SCLK, 0);
gpio_set_value(MOSI, 0);
}
/*
从设备使能
enable:为1时,使能信号有效,SS低电平
为0时,使能信号无效,SS高电平
*/
//因为不确定cs为高低才是使能,所以先保持原样
void ss_enable(int enable)
{
if (enable)
set_gpio_value(CS, 0); //SS低电平,从设备使能有效
else
set_gpio_value(CS, 1); //SS高电平,从设备使能无效
}
/* SPI字节写 */
void spi_write_cmd(unsigned char b)
{
//变量初始化
int i;
/* SPI端口初始化 */
spi_init();
// udelay(5);
ss_enable(1); //从设备使能有效,通信开始
// udelay(5);
for (i = 8; i >= 0; i--)
{
if (i == 8)
{
set_gpio_value(SCLK, 0);
// udelay(5); //延时
set_gpio_value(MOSI, 0); //如果是写命令则首位先写0
// udelay(5); //延时
set_gpio_value(SCLK, 1); // CPHA=1,在时钟的第一个跳变沿采样
// udelay(5);
}
else
{
set_gpio_value(SCLK, 0);
// udelay(5); //延时
set_gpio_value(MOSI, b & 1 << i); //从高位7到低位0进行串行写入
// udelay(5); //延时
set_gpio_value(SCLK, 1); // CPHA=1,在时钟的第一个跳变沿采样
// udelay(5); //延时
} //延时
}
set_gpio_value(SCLK, 0);
// udelay(5);
//结束单次通信
ss_enable(0);
}
void spi_write_data(unsigned char b)
{
//变量初始化
int i;
/* SPI端口初始化 */
spi_init();
// udelay(5);
ss_enable(1); //从设备使能有效,通信开始
// udelay(5); //延时
for (i = 8; i >= 0; i--)
{
if (i == 8)
{
set_gpio_value(SCLK, 0);
// udelay(5); //延时
set_gpio_value(MOSI, 1); //如果是写数据则首位先写1
// udelay(5); //延时
set_gpio_value(SCLK, 1); // CPHA=1,在时钟的第一个跳变沿采样
// udelay(5);
}
else
{
set_gpio_value(SCLK, 0);
// udelay(5); //延时
set_gpio_value(MOSI, b & 1 << i); //从高位7到低位0进行串行写入
// udelay(5); //延时
set_gpio_value(SCLK, 1); // CPHA=1,在时钟的第一个跳变沿采样
// udelay(5); //延时
}
}
set_gpio_value(SCLK, 0);
// udelay(5);
//结束单次通信
ss_enable(0);
}
//屏幕初始化函数
static void spi_lcd_init(void)
{
//spi模拟通信初始化
gpio_direction_output(CS, 1);
gpio_direction_output(SCLK, 1);
gpio_direction_output(MOSI, 0);
//屏幕初始化
gpio_direction_output(LCDPWM, 1);
gpio_direction_output(Reset, 1);
gpio_set_value(LCDPWM, LCDdefault);
gpio_set_value(Reset, 1);
mdelay(10);
gpio_set_value(Reset, 0);
mdelay(100);
gpio_set_value(Reset, 1);
mdelay(500);
spi_write_cmd(0xb2);
spi_write_data(0x0C);
spi_write_data(0x0C);
spi_write_data(0x00);
spi_write_data(0x33);
spi_write_data(0x33);
spi_write_cmd(0xb7);
spi_write_data(0x35);
//-------ST7789S Power setting-------//
spi_write_cmd(0xbb);
spi_write_data(0x20);
spi_write_cmd(0xc0);
spi_write_data(0x2c);
spi_write_cmd(0xc2);
spi_write_data(0x01);
spi_write_cmd(0xc3);
spi_write_data(0x12); //0x15
spi_write_cmd(0xc4);
spi_write_data(0x20);
spi_write_cmd(0xc6);
spi_write_data(0x0f);
spi_write_cmd(0xd0);
spi_write_data(0xa4);
spi_write_data(0xa1);
//-------ST7789S gamma setting------//
spi_write_cmd(0xe0);
spi_write_data(0xd0);
spi_write_data(0x00);
spi_write_data(0x05);
spi_write_data(0x0e);
spi_write_data(0x15);
spi_write_data(0x0d);
spi_write_data(0x37);
spi_write_data(0x43);
spi_write_data(0x47);
spi_write_data(0x09);
spi_write_data(0x15);
spi_write_data(0x12);
spi_write_data(0x16);
spi_write_data(0x19);
spi_write_cmd(0xe1);
spi_write_data(0xd0);
spi_write_data(0x00);
spi_write_data(0x05);
spi_write_data(0x0d);
spi_write_data(0x0c);
spi_write_data(0x06);
spi_write_data(0x2d);
spi_write_data(0x44);
spi_write_data(0x40);
spi_write_data(0x0e);
spi_write_data(0x1c);
spi_write_data(0x18);
spi_write_data(0x16);
spi_write_data(0x19);
spi_write_cmd(0x2a);
spi_write_data(0x00);
spi_write_data(0x00);
spi_write_data(0x01);
spi_write_data(0x3f);
spi_write_cmd(0x2b);
spi_write_data(0x00);
spi_write_data(0x00);
spi_write_data(0x00);
spi_write_data(0xef);
spi_write_cmd(0x3a);
spi_write_data(0x66);
spi_write_cmd(0xB0);
spi_write_data(0x11);
spi_write_data(0xf0);
spi_write_cmd(0xB1);
spi_write_data(0x46);
spi_write_data(0x05);
spi_write_data(0x14);
spi_write_cmd(0x36);
spi_write_data(0xa0); //行列切换
spi_write_cmd(0x11);
mdelay(150);
spi_write_cmd(0x29); // display on
mdelay(50);
printk("finished invitialized.....\n");
}
//入口主函数
static int __init ya15c_spi_init(void)
{
//spi端口先释放,防止之前有人使用
spi_free_gpio();
//占用函数要用的几个IO口
if (spi_request_gpio())
{
printk("ya15c spi initializer failure...\n");
return -1;
}
//屏幕初始化
printk("start to set color! ...\n");
// setcolor();
spi_lcd_init();
return 0;
}
static void __exit ya15c_spi_exit(void)
{
printk("ya15c exit!\n");
}
module_init(ya15c_spi_init);
module_exit(ya15c_spi_exit);
MODULE_LICENSE("GPL");
代码例程也不复杂,注释也已经很清楚,唯一的问题就是初始化代码可能会不好理解,可以结合手册理解。