?? lcd_d.c
字號:
#include<linux/kernel.h>
#include<linux/module.h>
#include<asm/uaccess.h>
#include<linux/init.h>
#include<asm/8xx_immap.h>
#include<linux/delay.h>
#include<linux/ioport.h>
#include<asm/io.h>
#include<linux/fs.h>#ifndef KERNEL_VERSION#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))#endif
volatile immap_t *immap;
//LCD相關寄存器定義
#define LCD_BASE 0x80000000
#define LCD_CONTROL 0x80000017
#define LCD_DATA_BASE 0x8000001d
//LED相關寄存器定義
#define LED_CONTROL 0x8000001b
#define LED_OFF 0xff
#define LED_ON 0x00
//LCD操作定義
#define LCD_ENH_INS 0x02
#define LCD_ENL_INS 0x00
#define LCD_ENH_DATA 0x03
#define LCD_ENL_DATA 0x01
#define LCD_ON 0x70
#define LCD_OFF 0x10
#define LCD_FUNCSET 0x3c
#define LCD_INPUT_MODESET 0x60
#define LCD_CLEAR 0x80
#define LCD_MODESET 0x1c
#define LCD_ROW2 0x03
#define MAJOR_NUM 200
#define GOODOPEN 1
// 設備名,將出現在 /proc/dev
#define DEVNAME "lcd_driver"// 設備正被打開嗎? 用于防止對同一設備的同時訪問 static int Device_Open = 0;
static int device_open(struct inode *,struct file*);
static int device_release(struct inode *,struct file*);
static ssize_t device_write(struct file *,const char *,size_t ,loff_t *);
struct file_operations lcd_ops=
{
write: device_write,
open: device_open,
release: device_release,
};//僅定義相關的的結構,其它操作用不到//格式轉換
static unsigned char
char_change (unsigned char org_char)
{ unsigned char swap_char = '\0';
swap_char |= ((org_char & 0x80) >> 7) | ((org_char & 0x40) >> 5)
| ((org_char & 0x20) >> 3) | ((org_char & 0x10) >> 1)
| ((org_char & 0x08) << 1) | ((org_char & 0x04) << 3)
| ((org_char & 0x02) << 5) | ((org_char & 0x01) << 7);
return swap_char;
}
//寫數據時序
static void lcd_data_write(char data)
{
writeb(char_change(data),LCD_DATA_BASE);
udelay(15);
writeb(LCD_ENL_DATA,LCD_CONTROL);//set EN=1,RS=1
udelay(1);
writeb(LCD_ENH_DATA,LCD_CONTROL);//set EN=0,RS=1
udelay(1);
writeb(LCD_ENL_DATA,LCD_CONTROL);//set EN=1,RS=1
udelay(40);
}//寫命令時序
static void lcd_cmd_write(char cmd)
{
writeb(cmd,LCD_DATA_BASE);
udelay(15);
writeb(LCD_ENL_INS,LCD_CONTROL);//set EN =1,RS=0
udelay(1);
writeb(LCD_ENH_INS,LCD_CONTROL);//set EN=0 ,RS=0
udelay(1);
writeb(LCD_ENL_INS,LCD_CONTROL);//set EN=1,RS=0
udelay(40);
}//LCD 初始化操作
static int __init lcd_init(void)
{ int err;
immap=(immap_t *)(mfspr(IMMR)&0xFFFF0000);//取得IMMR 內容
immap->im_memctl.memc_br7=0x80000401;//配置CS7相關寄存器
immap->im_memctl.memc_or7=0xffff0FF4;
err=register_chrdev(MAJOR_NUM,DEVNAME,&lcd_ops);//注冊設備
if(err!=0)
printk("<1> unable to get major 200 for LCD device\n");
if(check_region(LCD_BASE,0x1ff))//檢測IO端口
{
printk("IO is used already\n");return -1;
}else
{request_region(LCD_BASE,0x1ff,DEVNAME);//申請占用此端口//初始化 udelay(10);
lcd_cmd_write(LCD_MODESET);/* set 8-bit mode*/
udelay(4);
lcd_cmd_write(LCD_MODESET); /*set 8-bit mode */
udelay(1);
lcd_cmd_write(LCD_MODESET);/* set 8-bit mode*/
lcd_cmd_write(LCD_OFF);
lcd_cmd_write(LCD_ON);
lcd_cmd_write(LCD_INPUT_MODESET);
lcd_cmd_write(LCD_CLEAR);return 1;}
}
static int device_open(struct inode *rinode,struct file *rfile)
{/* 我們不想同時和兩個進程通話 */if (Device_Open)return -1;Device_Open++;
MOD_INC_USE_COUNT;//rmmod 操作時用
lcd_cmd_write(LCD_CLEAR);
lcd_cmd_write(LCD_INPUT_MODESET);
return 0;
}
static int device_release(struct inode *rinode,struct file *rfile)
{
MOD_DEC_USE_COUNT;
//歸還端口
release_region(LCD_BASE,0x1ff);
return 0;
}
static ssize_t device_write(struct file *rfile,const char *buffer,size_t length,loff_t *offset)
{ int i;
unsigned char c;
// lcd_init();
//寫時序
lcd_cmd_write(LCD_FUNCSET);
lcd_cmd_write(LCD_OFF);
lcd_cmd_write(LCD_ON);
lcd_cmd_write(LCD_INPUT_MODESET);
lcd_cmd_write(LCD_CLEAR);
for(i=0;i<length;i++)
{
if(i==8) lcd_cmd_write(LCD_ROW2);
get_user(c,buffer+i);
lcd_data_write(c);
}
return 0;
}
static void __exit lcd_cleanup(void)
{
int err;
lcd_cmd_write(LCD_CLEAR);
err=unregister_chrdev(MAJOR_NUM,DEVNAME);
if(err!=0)
printk("<1> Uninstall the %s failed!",DEVNAME);
release_region(LCD_BASE,0x1ff);
}module_init(lcd_init);module_exit(lcd_cleanup);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -