📄 lcd.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 + -