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

📄 lcd_12232f.c.bak

📁 自己开发的uclinux下RT12232F液晶的驱动程序
💻 BAK
字号:
/* Copyright (c) 2007,9,18  北京华龙通有限公司事业二部一室
*
* 文件名称:lcd12232F.c
* 摘 要:使用Avalon总线的4×4键盘底层驱动。
*
* 当前版本:v1.1.0
* 日期:2008年2月18日
*/
#include <linux/kernel.h>	
#include <linux/module.h>	
#include <linux/fs.h>
#include <asm/uaccess.h>	
#include <linux/delay.h>

#include "lcd_12232F.h"

#define SUCCESS 0


static int Device_Open = 0;

static char Message[BUF_LEN];
static char *Message_Ptr;

/*****************************************
 *    定义用户程序访问外设接口函数
 ****************************************/
 
/*
 * Function 1:device_open
 */
static int device_open(struct inode *inode, struct file *file)
{ 
  if (Device_Open)
    return -EBUSY;
  
  Device_Open++;
  Message_Ptr = Message;
  try_module_get(THIS_MODULE);
  return SUCCESS;
}

/*
 * Function 2:device_release
 */
static int device_release(struct inode *inode, struct file *file)
{  
  Device_Open--;
  
  module_put(THIS_MODULE);
  return SUCCESS;
}

/*
 * Function 3:device_read
 */
static ssize_t device_read(struct file *file,char __user * buffer,size_t length,loff_t * offset)
{
  int bytes_read = 0;     
  if (*Message_Ptr == 0)      
    return 0;  
  while (length && *Message_Ptr) {
    put_user(*(Message_Ptr++), buffer++);
    length--;
    bytes_read++;
  }  
  return bytes_read;
}

/*
 * Function 4:device_write
 */
static ssize_t device_write(struct file *file,const char __user * buffer, size_t length, loff_t * offset)
{
  int ii;
  unsigned char c;
  //0x80=10000000;代表设定DDRAM第一行地址到地址计数器AC,
  WriteNios(ADR_LCD_COMMAND,ADR_LCD_LINE1_OFFSET);
  udelay(50);
  //length为用户缓冲区的长度,BUF_LEN=16  
  for (ii = 0; ii < length && ii < BUF_LEN; ii++)
    {
      get_user(c, buffer + ii);
      //将从用户空间得到的字符c写到LCD的Data Register中
      WriteNios(ADR_LCD_DATA, (unsigned long) c);
      udelay(50);
    } 
  if (length < BUF_LEN)        //当用户缓冲区长度小于或等于16bytes
    {      	
	    //将第一行其它写成空,0x20的ASCII值为空
	    for (ii = length; ii < BUF_LEN; ii++)
		   {
		    WriteNios(ADR_LCD_DATA,0x20);
		    udelay(50);
		   }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
	    //将第二行其它全部写成空,0x20的ASCII值为空
	    WriteNios(ADR_LCD_COMMAND,ADR_LCD_LINE2_OFFSET);
	    udelay(50);
	   for (ii = BUF_LEN; ii < BUF_LEN+BUF_LEN; ii++)
		  {
		  WriteNios(ADR_LCD_DATA,0x20);
		  udelay(50);
		  }      
    }
   else                     //当用户缓冲区长度大于16bytes
    {
     //此时,用户数据已经将第一行写满,准备接着写第二行
     WriteNios(ADR_LCD_COMMAND,ADR_LCD_LINE2_OFFSET);
     udelay(50);
     for (ii = BUF_LEN; ii < length && ii < BUF_LEN+BUF_LEN; ii++)
		 {
		  get_user(c, buffer + ii);
		  WriteNios(ADR_LCD_DATA,(unsigned long) c);
		  udelay(50);
		 }		  
		 if (length < BUF_LEN + BUF_LEN)  //如果用户缓冲区数据长度小于或等于32bytes
		 {
		  //将第二行未写满的DDRAM写成空
		  for (ii = length; ii < BUF_LEN + BUF_LEN; ii++)
			{
			  WriteNios(ADR_LCD_DATA, 0x20);
			  udelay(50);
			}
		 }
    }
  //返回从用户段写入内核段数据的长度
  return length;
}

/* 
 *  Function 5:device_ioctl
 */
static int device_ioctl(struct inode *inode,struct file *file, unsigned int ioctl_num,unsigned long ioctl_param)
{
  int i;
  char *temp;
  char ch;
  
  switch (ioctl_num) 
  {
    case IOCTL_WRITE:                       // 将temp指针指向用户空间的message数据,将这条信息设置为需要传递给LCD设备的信息          
         temp = (char *)ioctl_param;        // 得到用户进程传递给ioctl函数的地址内的数据取出          
         get_user(ch, temp);                   
         for (i = 0; ch && i < BUF_LEN + BUF_LEN; i++, temp++)
           {
        	   get_user(ch, temp);
           }                               //解析这条message的长度,得到i值
         if (i<BUF_LEN)
           {
	           i=i-1;
           }
         device_write(file, (char *)ioctl_param, i, 0);     
         break;   
    case IOCTL_READ:                      //从LCD设备中读取内容到ioclt_param 地址所在的空间
    	   i = device_read(file, (char *)ioctl_param, 99, 0);
         put_user('\0', (char *)ioctl_param + i);     
         break; 
    case IOCTL_LCD_ON:   	     
    case IOCTL_LCD_OFF:
    	   WriteNios(ADR_LCD_COMMAND,LCD_CMD_ONOFF);   
         mdelay(1);   	     
         break;
    case IOCTL_LCD_CLEAR: 
     	   WriteNios(ADR_LCD_COMMAND,LCD_CMD_CLEAR);   
         mdelay(2); 
         break;
    case IOCTL_LCD_RESET :
     	   WriteNios(ADR_LCD_COMMAND,LCD_COM_RESET);
         mdelay(5);
         break;
    case IOCTL_LCD_HOME:
     	   WriteNios(ADR_LCD_COMMAND,LCD_CMD_HOME);
     	   mdelay(1);
     	   break;
    case IOCTL_LCD_CURSOR_LEFT:
     	   WriteNios(ADR_LCD_COMMAND,LCD_CMD_MODES);
     	   mdelay(1); 
     	   break;
    case IOCTL_LCD_CURSOR_RIGHT:
     	   WriteNios(ADR_LCD_COMMAND,LCD_CMD_MODES | LCD_CMD_ONOFF_SHIFT);
     	   mdelay(1); 
     	   break;
    case IOCTL_LCD_CURSOR_ON:
     	   WriteNios(ADR_LCD_COMMAND,LCD_CMD_ONOFF | LCD_CMD_ONOFF_CURSOR);
     	   mdelay(1); 
     	   break;     	   
    case IOCTL_LCD_DISP_SHOW_ON:
     	   WriteNios(ADR_LCD_COMMAND,LCD_CMD_ONOFF | LCD_CMD_ONOFF_DISP);
     	   mdelay(1); 
     	   break;      	   
    case IOCTL_LCD_CURSOR_GET:
     	   break;      	   
    case IOCTL_LCD_CURSOR_SET: 
     	   break;
    case IOCTL_LCD_GET_CURSOR_POS:
     	   break;      	   
    case IOCTL_LCD_SET_CURSOR_POS: 
     	   break;
    case IOCTL_LCD_CURSOR_BLINK:
     	   WriteNios(ADR_LCD_COMMAND,LCD_CMD_ONOFF | LCD_CMD_ONOFF_BLINK);
     	   mdelay(1);      	
     	   break;      	   
    case IOCTL_LCD_ROW1_BLINK: 
     	   break;
    case IOCTL_LCD_DISP_LEFT:
     	   break;      	   
    case IOCTL_LCD_DISP_RIGHT: 
     	   break;     	      	   
    case IOCTL_LCD_DISP_ON: 
     	   break;
    case IOCTL_LCD_DISP_OFF:
     	   break;      	   
    case IOCTL_LCD_LINE1:
         WriteNios(ADR_LCD_COMMAND,ADR_LCD_LINE1_OFFSET);
         udelay(50);    	 
     	   break;
    case IOCTL_LCD_LINE2:
         WriteNios(ADR_LCD_COMMAND,ADR_LCD_LINE2_OFFSET);
         udelay(50);     	 
     	   break;
    case IOCTL_LED_NORMAL:
         WriteNios(0x02010850,LED_STATE_NORMAL);
         udelay(50);    	 
     	   break;     	         	         	   
    case IOCTL_LCD_BACKGROUND_LED_OFF:
         WriteNios(0x02010850,0x02);
         udelay(50);    	 
     	   break;
    case IOCTL_LCD_WARNING_LED_ON:
         WriteNios(0x02010850,0x01);
         udelay(50);     	 
     	   break;     	        	        	
  }
  
  return SUCCESS;
}


/* Module Declarations */
struct file_operations Fops = {
  .read = device_read,
  .write = device_write,
  .ioctl = device_ioctl,
  .open = device_open,
  .release = device_release,	/* a.k.a. close */
};

/* 
 * Initialize the module - Register the character device 
 */
int init_module()
{
  int ret_val;  //int i;  //unsigned long *p;
  ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
  if (ret_val < 0) {
    printk(KERN_ALERT "%s failed with %d\n",
	   "Sorry, registering the character device ", ret_val);
    return ret_val;
     }
  printk(KERN_INFO "Device %s registered\n", DEVICE_FILE_NAME);
  mdelay(20);     
  WriteNios(ADR_LCD_COMMAND,LCD_COM_RESET);
  mdelay(5);
  WriteNios(ADR_LCD_COMMAND,LCD_COM_RESET);
  udelay(200);
  WriteNios(ADR_LCD_COMMAND,LCD_COM_RESET);
  udelay(200);                                    //在此之前,不能检查BF标志
  WriteNios(ADR_LCD_COMMAND,LCD_NUMROWS | LCD_INTERFACE | LCD_CMD_FUNC);    //00111000
  udelay(50);
  WriteNios(ADR_LCD_COMMAND,LCD_CMD_ONOFF);   //显示状态开
  udelay(50);
  WriteNios(ADR_LCD_COMMAND,LCD_CMD_CLEAR);   //清屏
  mdelay(2);
  //WriteNios(ADR_LCD_COMMAND,LCD_CMD_ONOFF | LCD_CMD_ONOFF_DISP | LCD_CMD_ONOFF_CURSOR | LCD_CMD_ONOFF_BLINK);  WriteNios(ADR_LCD_COMMAND,LCD_CMD_ONOFF | LCD_CMD_ONOFF_DISP);
  udelay(50);
  //初始化液晶显示   /*for(i=0;i<16;i++)    {     p=0x02010850+i;    *p=0x00;    mdelay(200);      }*/  WriteNios(0x02010850,0xff);  mdelay(200);
  WriteNios(ADR_LCD_DATA,0xb1);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xb1);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xbe);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xa9);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xbb);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xaa);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xc1);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xfa);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xcd);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xa8);
  udelay(50);
  WriteNios(ADR_LCD_COMMAND,ADR_LCD_LINE2_OFFSET);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xbb);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xb6);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xd3);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xad);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xc4);
  udelay(50);
  WriteNios(ADR_LCD_DATA,0xfa);
  udelay(50);
  return 0;
}

/* 
 * Cleanup - unregister the appropriate file from /proc 
 */
void cleanup_module()
{
  int ret;
  
  /* 
   * Unregister the device 
   */
  ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
  
  /* 
   * If there's an error, report it 
   */
  if (ret < 0)
    printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
}

int WriteNios(unsigned long addr, unsigned long value)
{
  int ret = 0;
  unsigned long data;
  unsigned long *p = (unsigned long *)addr;
  data = (unsigned long)(value);
  ret = put_user(data, p);
  return ret;
}

int ReadNios(unsigned long addr, unsigned long * pValue)
{
  int ret = 0;
  unsigned long *p = (unsigned long *)addr;
  if (get_user(*pValue, p))
    return -EFAULT;
  return ret;
}

module_init(init_module);
module_exit(cleanup_module);


#define author "HLT of TCB: Department 2"
#define description "A driver for LCD12232F device of the satellite project."
MODULE_AUTHOR(author);
MODULE_DESCRIPTION(description);
MODULE_SUPPORTED_DEVICE(DEVICE_NAME);
MODULE_LICENSE("GPL");





⌨️ 快捷键说明

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