⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcd.c

📁 160*160字符图形液晶Linux2.6.24内核驱动程序
💻 C
字号:
//#include <linux/config.h>#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/crc32.h>#include <linux/device.h>#include <linux/spinlock.h>#include <linux/workqueue.h>#include <linux/miscdevice.h>#include <linux/list.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/time.h>#include <asm/hardware.h>#include <asm/system.h>#include <linux/fs.h>#include <linux/types.h>#include <asm/uaccess.h>#include <linux/spinlock.h>#include <linux/irq.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/arch/gpio.h>#include "pic.h"#define	MEM_LCD_ADDR	0x50000000/* Memory mapping definitions */#define MAP_SIZE 1024#define MAP_MASK (MAP_SIZE - 1)#define	DIS_DELAY 	1#define	LCD_TEST			0x01#define	LCD_LOAD_PIC		0x02#define LCD_BACKLIGHT_ON	0x03#define	LCD_CONTRAST_SET	0x04#define	LCD_DISP_TIME		0x05#define	LCD_DISP_STATUS	0x06#define   LCD_CONTRAST_INC	0x07#define   LCD_CONTRAST_DEC	0x08#define   LCD_DISP_AREA		0x09#define	MAX_BUFF_LEN	3200typedef struct lcd_data {	unsigned int len;	unsigned int data;	unsigned int y1;	unsigned int y2;	unsigned char buf[MAX_BUFF_LEN+1];}lcd_data;static struct lcd_data local_data;void * LCD_MAPPED_BASE = NULL;void Display_Picture(unsigned char *pic);void Display_Time(unsigned char *pic);void Display_Status(unsigned char *pic);void Display_Gray(void);void Display_Grid(unsigned char dat1,unsigned char dat2,unsigned char dat3,unsigned char dat4);void Initial_LCD(void);inline void Write_Instruction(unsigned char cmd);inline void Write_Data(unsigned char dat);void LcdTest(void);inline void Write_Data(unsigned char dat) {	*(unsigned char *)(LCD_MAPPED_BASE+1) = dat;}inline void Write_Instruction(unsigned char cmd){	*(unsigned char *)(LCD_MAPPED_BASE) = cmd;}void Initial_LCD(void){	Write_Instruction(0x30);//Ext in	Write_Instruction(0x94);//Sleep out	Write_Instruction(0xd1);//Internal OSC on		Write_Instruction(0x20);//Frame 1 gray PWM set	Write_Data(0x08);//两次写入参数,Set Gray level 0 at odd frames	mdelay(DIS_DELAY);	Write_Instruction(0x20);//Set Gray level 1 at odd frames	Write_Data(0x0b);	Write_Instruction(0x81); //Contrast adjusting	Write_Data(0x0f); //0x36	Write_Data(0x05); //0x04	Write_Instruction(0xca);//Display conctrl	Write_Data(0x00);//参数用于指定是否将时钟分频,0x04将时钟分频	Write_Data(0x27);//(行数/4)-1即为所得参数值,specifies the duty of the module on block basis.	Write_Data(0x00);//	Write_Instruction(0xa6);//Normal display	Write_Instruction(0xbb);//COM scan direction	Write_Data(0x02);//参考文档ST7529,第39页	Write_Instruction(0xbc);	Write_Data(0x00);//P42	Write_Data(0x00);	Write_Data(0x02);	Write_Instruction(0x75);//指定MPU存取显示RAM的行范围	Write_Data(0x00);//起始行	Write_Data(0x9f);//结束行,159(MAX)	Write_Instruction(0x15);//指定MPU存取显示RAM的列范围	Write_Data(0x00);//起始列	Write_Data(0x35);//结束列,53(MAX=84/0x54)	Write_Instruction(0x31);//Ext out,另一指令集	Write_Instruction(0x32);//模拟电路设置	Write_Data(0x05);//晶振频率调整,19.3	Write_Data(0x01);//Booster Efficiency set,调压器功效设置,默认6K	Write_Data(0x01);//驱动LCD电压偏差率	Write_Instruction(0x22);//Weight set	Write_Data(0x04);//	Write_Data(0x1f);//	Write_Data(0x02);//	Write_Instruction(0x20);//Frame 1 gray PWM set	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Instruction(0x21);//Frame 2 gray PWM set	Write_Data(0x00);	Write_Data(0x00);	Write_Data(0x04);	Write_Data(0x04);	Write_Data(0x08);	Write_Data(0x08);	Write_Data(0x0c);	Write_Data(0x0c);	Write_Data(0x10);	Write_Data(0x10);	Write_Data(0x14);	Write_Data(0x14);	Write_Data(0x18);	Write_Data(0x18);	Write_Data(0x1f);	Write_Data(0x1f);	Write_Instruction(0x34);//抖动电路关闭	Write_Instruction(0x30);//Ext in	Write_Instruction(0xaf);//打开显示,ae,显示关闭}void Display_Grid(unsigned char dat1,unsigned char dat2,unsigned char dat3,unsigned char dat4){    register unsigned char i,j,k,l;    Write_Instruction(0x15);    Write_Data(0x00);    Write_Data(0x35);    Write_Instruction(0x75);    Write_Data(0x00);    Write_Data(0x9f);    Write_Instruction(0x5c);    for(k=0;k<0x14;k++)    {          for(i=0;i<0x04;i++)          {            for(j=0;j<0x14;j++)			{			    for(l=0;l<0x4;l++)                    Write_Data(dat1);			    for(l=0;l<0x4;l++)                    Write_Data(dat2);            }            Write_Data(dat2);            Write_Data(dat2);          }          for(i=0;i<0x04;i++)          {            for(j=0;j<0x14;j++)			{			    for(l=0;l<0x4;l++)                    Write_Data(dat3);			    for(l=0;l<0x4;l++)                    Write_Data(dat4);            }            Write_Data(dat4);            Write_Data(dat4);          }    }	Write_Instruction(0x25);//cml  NOP空指令,离开写模式	return;}void Display_Gray(void){    register unsigned char i,j,k;    Write_Instruction(0x15);    Write_Data(0x00);    Write_Data(0x35);    Write_Instruction(0x75);    Write_Data(0x00);    Write_Data(0x9f);    Write_Instruction(0x5c);    for(k=0;k<0x04;k++)    {        for(i=0;i<0x0a;i++)        {            for(j=0;j<0xa2;j++)                Write_Data(0x00);        }        for(i=0;i<0x0a;i++)        {	        for(j=0;j<0xa2;j++)                Write_Data(0x4f);        }        for(i=0;i<0x0a;i++)        {        	for(j=0;j<0xa2;j++)                Write_Data(0xaf);        }        for(i=0;i<0x0a;i++)        {	        for(j=0;j<0xa2;j++)                Write_Data(0xff);        }    }	Write_Instruction(0x25);//cml  NOP空指令,离开写模式	return;}void Display_Picture(unsigned char *pic){    unsigned char i,j,k,tmp,temp;    unsigned int test=0;    Write_Instruction(0x15);//cml  Column Address Set    Write_Data(0x00);    Write_Data(0x35);//0x35=53    Write_Instruction(0x75);//cml  Line Address Set    Write_Data(0x00);    Write_Data(0x9f);//0x9F=159    Write_Instruction(0x5c);    for(k=0;k<0xa0;k++)//cml  0xA0=160    {        for(i=0;i<0x14;i++)//cml  0x14=20        {		test = k*20+i;		if(test <= MAX_BUFF_LEN) temp=pic[test];		else printk("ERROR: LCD BUFFER OVERFLOW(%d)!!!\n", test);		for(j=0x00;j<0x08;j++)		{			tmp=temp&0x80;			if(tmp==0x80)		            	Write_Data(0x00);			else				Write_Data(0xf8);			temp=temp<<1;		}        }	Write_Data(0xf8);	Write_Data(0xf8);    }	Write_Instruction(0x25);//cml  NOP空指令,离开写模式	return;}//cml  刷新显示指定区域void Display_Area(unsigned int y1, unsigned int y2, unsigned char *pic){    unsigned char i,j,k,tmp=0,temp=0;    unsigned int test=0;    //y1 = y1/16 * 16;    //y2 = (y2/16+1)*16;    if(y2 > 159)y2 = 159;//cml  防止显示缓冲区溢出        Write_Instruction(0x15);//cml  Column Address Set    Write_Data(0x00);    Write_Data(0x35);//0x35=53,与列的对应关系53*3=159    Write_Instruction(0x75);//cml  Line Address Set    Write_Data(y1);    Write_Data(y2);//0x9F=159    Write_Instruction(0x5c);    for(k=y1;k<=y2;k++)//cml  0xA0=160    {        for(i=0;i<0x14;i++)//cml  0x14=20        {		test = k*20+i;		if(test <= MAX_BUFF_LEN) temp=pic[test];		else printk("ERROR: LCD BUFFER OVERFLOW(%d)!!!\n", test);		for(j=0x00;j<0x08;j++)		{			tmp=temp&0x80;			if(tmp==0x80)		            	Write_Data(0x00);			else				Write_Data(0xf8);			temp=temp<<1;		}        }	Write_Data(0xf8);	Write_Data(0xf8);    }	Write_Instruction(0x25);//cml  NOP空指令,离开写模式	return;}void Display_Time(unsigned char *pic){    unsigned char i,j,k,tmp,temp;    unsigned int test=0;    Write_Instruction(0x15);    Write_Data(0x00);    Write_Data(0x35);    Write_Instruction(0x75);    Write_Data(0x00);    Write_Data(0x10);    Write_Instruction(0x5c);    for(k=0;k<0x10;k++)    {        for(i=0;i<0x14;i++)        {		test = k*20+i;		if(test <= MAX_BUFF_LEN) temp=pic[test];		else printk("ERROR: LCD BUFFER OVERFLOW(%d)!!!\n", test);		for(j=0x00;j<0x08;j++)		{			tmp=temp&0x80;			if(tmp==0x80)		            	Write_Data(0x00);			else				Write_Data(0xf8);			temp=temp<<1;		}        }	Write_Data(0xf8);	Write_Data(0xf8);    }	Write_Instruction(0x25);//cml  NOP空指令,离开写模式	return;}void Display_Status(unsigned char *pic){    unsigned char i,j,k,tmp,temp;    unsigned int test=0;    Write_Instruction(0x15);    Write_Data(0x00);    Write_Data(0x35);    Write_Instruction(0x75);    Write_Data(0x90);    Write_Data(0x9F);    Write_Instruction(0x5c);    for(k=0x90;k<0xA0;k++)    {        for(i=0;i<0x14;i++)        {		test = k*20+i;		if(test <= MAX_BUFF_LEN) temp=pic[test];		else printk("ERROR: LCD BUFFER OVERFLOW(%d)!!!\n", test);		for(j=0x00;j<0x08;j++)		{			tmp=temp&0x80;			if(tmp==0x80)		            	Write_Data(0x00);			else				Write_Data(0xf8);			temp=temp<<1;		}        }	Write_Data(0xf8);	Write_Data(0xf8);    }	Write_Instruction(0x25);//cml  NOP空指令,离开写模式	return;}void LcdTest(void){	int i = 0;	for(i = 0; i < 5; i ++)	{	        Display_Grid(0xff,0xff,0xff,0xff);        	mdelay(DIS_DELAY*1000);		Display_Picture(pic1);        	mdelay(DIS_DELAY*1000);		Display_Picture(pic2);        	mdelay(DIS_DELAY*1000);        	Display_Gray();        	mdelay(DIS_DELAY*1000);        	Display_Grid(0xff,0xff,0x00,0x00);        	mdelay(DIS_DELAY*1000);        	Display_Grid(0x00,0x00,0xff,0xff);        	mdelay(DIS_DELAY*1000);        	Display_Grid(0x00,0xff,0x00,0xff);        	mdelay(DIS_DELAY*1000);        	Display_Grid(0xff,0x00,0xff,0x00);        	mdelay(DIS_DELAY*1000);        	Display_Grid(0xff,0x00,0x00,0xff);        	mdelay(DIS_DELAY*1000);        	Display_Grid(0x00,0xff,0xff,0x00);        	mdelay(DIS_DELAY*1000);    	}}void lcd_backlight(int on){	if(on) 	at91_set_gpio_output(AT91_PIN_PC6, 1);	else	at91_set_gpio_output(AT91_PIN_PC6, 0);}void lcd_contrast(int data){	Write_Instruction(0x81); //Contrast adjusting	Write_Data((data>>8)&0xFF); //0x36	Write_Data(data&0xFF); //0x04		Write_Instruction(0x25);//cml  NOP空指令,离开写模式}void lcd_contrast_inc(void){	Write_Instruction(0xD6);	printk("driver contrast inc!\n");}void lcd_contrast_dec(void){	Write_Instruction(0xD7);	printk("driver contrast dec!\n");}static int lcd_ioctl(struct inode *inode, struct file *file,                     unsigned int cmd, unsigned long arg){	if (copy_from_user(&local_data, (struct lcd_data *)arg, sizeof(local_data)))		return -EFAULT;	switch (cmd) {		case LCD_TEST:			LcdTest();			return 0;		break;		case LCD_LOAD_PIC:			Display_Picture(local_data.buf);			return 0;		break;		case LCD_BACKLIGHT_ON:			lcd_backlight(local_data.data);		break;		case LCD_CONTRAST_SET:			lcd_contrast(local_data.data);		break;				case LCD_DISP_TIME:			Display_Time(local_data.buf);		break;		case LCD_DISP_STATUS:			Display_Status(local_data.buf);		break;		case LCD_CONTRAST_INC:			lcd_contrast_inc();		break;		case LCD_CONTRAST_DEC:			lcd_contrast_dec();		break;		case LCD_DISP_AREA:			Display_Area(local_data.y1, local_data.y2, local_data.buf);			break;		default:			return -EINVAL;		break;	}     		  return -EINVAL;}static int lcd_open(struct inode *inode, struct file *file){	return 0;}static int lcd_release(struct inode *inode, struct file *file){	return 0;}static struct file_operations lcd_fops = {	.open		= lcd_open,	.release	= lcd_release,	.ioctl  	= lcd_ioctl,};static struct miscdevice lcd_dev = {	.minor  = 199,	.name   = "LCD",	.fops   = &lcd_fops,};static int __init lcd_init(void){		/*	 * addr * Map the attribute space.  This is overkill, but clean.	 * clean */	LCD_MAPPED_BASE = ioremap(MEM_LCD_ADDR, MAP_SIZE);	if (!LCD_MAPPED_BASE)		return -ENOMEM;	misc_register(&lcd_dev);	Initial_LCD();	return 0;}static void __exit lcd_exit(void){}MODULE_AUTHOR("Yanjun Luo <yanjun.luo@gmail.com");MODULE_DESCRIPTION("lcd driver");MODULE_LICENSE("GPL");module_init(lcd_init);module_exit(lcd_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -