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

📄 lcd12864.c

📁 LCD 128x64 驱动程序 嵌入式linux
💻 C
字号:
/*
**	linux/drivers/at91/LCD/lcd12864.c
**		
**
**	Copyright (C) 2006 Hyesco Technology Co.,Ltd
**
**	Author: casiawu <wujh@hyesco.com>
**
**	History:
**
**	2006.3   casiawu  <wujh@hyesco.com>
**               Original version
*/


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/fcntl.h>
#include <linux/string.h>

#include <asm/bitops.h>
#include <asm/arch/AT91RM9200_SYS.h>

#define LCD_MODULE_NAME "AT91_LCD"

#define U8 unsigned char 
#define U16 unsigned short
#define U32 unsigned long

//GPIO configurations 
#define   LCD_DI        0x2                  /* PB1   1: Data ; 0:Instruction   */
#define   LCD_RW        0x4                  /* PB2   1: Read ; 0:Write         */
#define   LCD_E         0x8                  /* PB3   1-0: enable               */
#define   LCD_CS1       0x1<<27              /* PA27  1:  enable; 0: disable    */
#define   LCD_CS2       0x1<<28              /* PA28  1:  enable; 0: disable    */
#define   LCD_CS3       0x1<<29              /* PA29  1:  enable; 0: disable    */
#define   LCD_DATA      0xFF0                /* PB4-11                          */
    

/*****   ks0108 Registers    ********/
#define   DISPLAY_ON    0x3F
#define   DISPLAY_OFF   0x3E

#define   START_LINE    0xC0
#define   PAGE_ADDR     0xB8
#define   COL_ADDR      0x40
#define   BUSY          0x80

/******   LCD control cmd   *********/
#define   LCD_CLEAR      0x5A00
//#define   BACKLIGHT_OFF  0x5A01
//#define   BACKLIGHT_ON   0x5A02
#define   XPAGE_GET      0x5A03
#define   XPAGE_SET      0x5A04
#define   YCOL_GET       0x5A05
#define   YCOL_SET       0x5A06


/* Global variables: cursor coordinate*/
U8 u8CursorX, u8CursorY;

int lcd_open(struct inode * inode, struct file * filp);
int lcd_release(struct inode * inode, struct file * filp);
ssize_t lcd_read(struct file * filp, char * buf, size_t count, loff_t * l);
ssize_t lcd_write(struct file *filp, const char *buf, size_t count,loff_t *f_pos);
int lcd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);


struct file_operations lcd_fops = {
 		owner:		THIS_MODULE,
		open:    	lcd_open,
		release:  lcd_release,
  	read:     lcd_read,		
  	write:    lcd_write,
  	ioctl:    lcd_ioctl,
};
	

int lcd_open(struct inode * inode, struct file * filp)
{
		MOD_INC_USE_COUNT;
		return 0;
}

int lcd_release(struct inode * inode,struct file * filp)
{
		MOD_DEC_USE_COUNT;
		return 0;
}	

/*------------------      delay      ------------------------*/
void delay(unsigned int t)
{
    unsigned int i,j;
    for(i=0;i<t;i++)
    for(j=0;j<10;j++);
}

/*------------------ Write cmd to LCD ------------------------*/
void write_com(U8 cmdcode)
{
    
    AT91_SYS->PIOB_OER  |= 0xFF0;     	/*p4-11 out enable */      
    
    AT91_SYS->PIOB_CODR |= LCD_E;
    
    AT91_SYS->PIOB_CODR |= LCD_DI;       /* set di=0  */
    AT91_SYS->PIOB_CODR |= LCD_RW;       /* set rw=0  */

    AT91_SYS->PIOB_ODSR &=  0xfffff00f;    /* pb4-11 clear*/
    AT91_SYS->PIOB_ODSR |= (cmdcode << 4);
    delay(0);
    AT91_SYS->PIOB_SODR |= LCD_E;
    delay(0);
    AT91_SYS->PIOB_CODR |= LCD_E;
}

/*-------------------  Write data to LCD  ---------------------*/

void write_data(U8 Dispdata)
{

    AT91_SYS->PIOB_OER  |= 0xFF0;   
    
    AT91_SYS->PIOB_CODR |= LCD_E;
    
    AT91_SYS->PIOB_SODR |= LCD_DI;        /* set di=1  */
    AT91_SYS->PIOB_CODR |= LCD_RW;        /* set rw=0  */

    AT91_SYS->PIOB_ODSR &=  0xfffff00f;    /* pb4-11 clear*/
    AT91_SYS->PIOB_ODSR |= (Dispdata << 4);
    delay(0);
    AT91_SYS->PIOB_SODR |= LCD_E;
    delay(0);
    AT91_SYS->PIOB_CODR |= LCD_E;
}

/*-----------------  Read status from LCD  ----------------------*/

U8 read_status(void)
{
    U8 tmpin=0;
    
    AT91_SYS->PIOB_ODR |= 0xFF0;         /*p4-11 input enable */

    AT91_SYS->PIOB_CODR |= LCD_E;
    
    AT91_SYS->PIOB_CODR |= LCD_DI;       /* set di=0  */
    AT91_SYS->PIOB_SODR |= LCD_RW;       /* set rw=1  */
    delay(0);
    AT91_SYS->PIOB_SODR |= LCD_E;
       
    delay(0);
    AT91_SYS->PIOB_CODR |= LCD_E;

    tmpin = ( AT91_SYS->PIOB_PDSR & LCD_DATA) >> 4;
    return tmpin;
}

/*-----------------  Read status from LCD  ----------------------*/

U8 read_data(void)
{
    U8 tmpin;
    
    AT91_SYS->PIOB_ODR |= 0xFF0;         /*p4-11 input enable */

    AT91_SYS->PIOB_CODR |= LCD_E;
    
    AT91_SYS->PIOB_SODR |= LCD_DI;        /* set di=1  */
    AT91_SYS->PIOB_SODR |= LCD_RW;        /* set rw=1  */
    delay(0);
    AT91_SYS->PIOB_SODR |= LCD_E;
    delay(0);
    AT91_SYS->PIOB_CODR |= LCD_E;

    tmpin = ( AT91_SYS->PIOB_PDSR & LCD_DATA) >> 4;
    
    return tmpin;
}


/*-----------------------      Clear lcd   -------------------*/
void Clr_Scr(void)
{   
    U8 j,k;
       
    /* select all the CS */
    AT91_SYS->PIOA_SODR |= LCD_CS1;
    AT91_SYS->PIOA_SODR |= LCD_CS2;
    AT91_SYS->PIOA_SODR |= LCD_CS3;
    
    write_com(PAGE_ADDR+0);
    while(read_status() & BUSY); 
    write_com(COL_ADDR+0);
    while(read_status() & BUSY); 
    for(k=0;k<8;k++)
   		{
    	write_com(PAGE_ADDR+k);
    	while(read_status() & BUSY); 
    	for(j=0;j<64;j++)
    		{
      	write_data(0x00);
      	while(read_status() & BUSY); 
      	} 
   		}
}


/*-----------------      Init LCD     -------------------------*/
void Init_Lcd(void)
{
    /* enable pio controller */
    AT91_SYS->PIOA_PER |= (LCD_CS1 | LCD_CS2 | LCD_CS3); 
    AT91_SYS->PIOB_PER |= (LCD_DI | LCD_RW | LCD_E | LCD_DATA);
    //AT91_SYS->PIOC_PER |= 0x1<<14;
         
    AT91_SYS->PIOA_OER |= (LCD_CS1 | LCD_CS2 | LCD_CS3);
    AT91_SYS->PIOB_OER |= (LCD_DI | LCD_RW | LCD_E);
    //AT91_SYS->PIOC_OER |= 0x1<<14;
                        
    AT91_SYS->PIOB_OWER |= LCD_DATA ;
     
    /* enable PMC clock */     
    AT91_SYS->PMC_PCER =0x1<< AT91C_ID_PIOA;
    AT91_SYS->PMC_PCER =0x1<< AT91C_ID_PIOB;
    AT91_SYS->PMC_PCER =0x1<< AT91C_ID_PIOC;    
    /* disable backlight */     
    //AT91_SYS->PIOC_CODR |= 0x1<<14;
             
    /* select all the CS */
    AT91_SYS->PIOA_SODR |= LCD_CS1;
    AT91_SYS->PIOA_SODR |= LCD_CS2;
    AT91_SYS->PIOA_SODR |= LCD_CS3;
         	
		//LCD Display off;
		while(read_status() & BUSY); 
    write_com(DISPLAY_OFF);  
     
    while(read_status() & BUSY); 
    write_com(PAGE_ADDR+0);

    while(read_status() & BUSY);
    write_com(START_LINE+0);
    
    while(read_status() & BUSY);
    write_com(COL_ADDR+0);
		
		//LCD Display on;
    while(read_status() & BUSY);
    write_com(DISPLAY_ON);    

    while(read_status() & BUSY);

}

/*-----------------      Read LCD data to user   -------------------------*/
ssize_t lcd_read(struct file * filp, char * buf, size_t count, loff_t * l)
{
	  U8 tembuf[1];
	  tembuf[0] = read_data();
	  while(read_status() & BUSY); 
	  copy_to_user(buf,tembuf,1);
	  return 1;  
}


/*-----------------      Write user data to   -------------------------*/
ssize_t lcd_write(struct file *filp, const char *buf, size_t count,loff_t *f_pos)
{  
	  U8 tempbuf[1];
	  U8 x_row=0,y_col=0;
	  /*	  
    if(u8CursorX>7)
    return -1; 	  	  
	  */
	  if(u8CursorX>7)
	  	{
	  		u8CursorX=0;
	  	}
	  		  
	  if(u8CursorY>63)
	  {
	    /* select  CS2 */
      AT91_SYS->PIOA_CODR |= LCD_CS1;
      AT91_SYS->PIOA_SODR |= LCD_CS2;
      AT91_SYS->PIOA_CODR |= LCD_CS3;
      y_col = u8CursorY-64 ;
      x_row = u8CursorX;
      AT91_SYS->PIOA_SODR |= LCD_CS2;
   
	  }
	  else
	  {
	    /* select  CS1 */
      AT91_SYS->PIOA_SODR |= LCD_CS1;
      AT91_SYS->PIOA_CODR |= LCD_CS2;
      AT91_SYS->PIOA_CODR |= LCD_CS3;
      y_col = u8CursorY;
      x_row = u8CursorX;   
	  }	
	  
	  copy_from_user(tempbuf, buf, 1); 
	  
	  while(read_status() & BUSY); 
	  write_com(PAGE_ADDR+x_row);
	  while(read_status() & BUSY);
    write_com(COL_ADDR+y_col); 
    while(read_status() & BUSY);   
    write_data(tempbuf[0]);
    while(read_status() & BUSY);
    u8CursorY = u8CursorY +1;   
    if(u8CursorY>127)
    {
      u8CursorX = u8CursorX +1;
      u8CursorY = 0;
      Init_Lcd();
		}
    
    return 1;
  
}

/*
 * Handle commands from user-space
 */
int lcd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
	 switch (cmd) 
		{	
	  case LCD_CLEAR:
	  	   Clr_Scr();
	       break;
	  //case BACKLIGHT_OFF:
	  //	   AT91_SYS->PIOC_CODR |= 0x1<<14;
	  //	   delay(0);
	  //    break;	 
	  //case BACKLIGHT_ON:
	  //	   AT91_SYS->PIOC_SODR |= 0x1<<14;
	  //	   delay(0);
	  //     break;	 
	  case XPAGE_GET:
	  	   put_user(u8CursorX, (int *)arg);
	       break;	 
	  case XPAGE_SET:
	  	   if(arg>64) return -1;
	  	   u8CursorX = (U8)arg ;
	       break;
	  case YCOL_GET:
	  	   put_user(u8CursorY, (int *)arg);
	       break;		     		       
	  case YCOL_SET:
	  	   if(arg>127) return -1;
	  	   u8CursorY = (U8)arg ;
	       break;	
	  default:
		     return -EINVAL;
		}
	
	return 0;	  	       	            
}


/*-----------------  register function --------------------*/
static int gMajor=251;		
int __init LCD_at91_init(void)
{	
	  unsigned int result = 0;
	
	  Init_Lcd();
		//printk("LCD Init!\r\n");
    result= register_chrdev(gMajor, LCD_MODULE_NAME, &lcd_fops);
	  if (result < 0) 
	 		{
			printk("<1>devfs_register_chrdev can't get major number 251\n");
			return result;
	 		}
  
    u8CursorX=0;
    u8CursorY=0;
    return 0;
}


void __exit LCD_at91_cleanup(void)
{
	
		write_com(DISPLAY_OFF);  
  	
  	/* de-select all the CS */ 
  	AT91_SYS->PIOA_CODR |= LCD_CS1;
  	AT91_SYS->PIOA_CODR |= LCD_CS2;
  	AT91_SYS->PIOA_CODR |= LCD_CS3;
  	
		unregister_chrdev(gMajor, LCD_MODULE_NAME);
}


module_init(LCD_at91_init);
module_exit(LCD_at91_cleanup);

MODULE_AUTHOR("casiawu <wujh@hyesco.com>");
MODULE_DESCRIPTION("AT91 LCD Driver (AT91_LCD)");
MODULE_LICENSE("GPL");
	  

⌨️ 快捷键说明

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