基于s3c2440的12864液晶驱动

发布者:数据梦行者最新更新时间:2022-07-27 来源: csdn关键字:s3c2440  液晶驱动 手机看文章 扫描二维码
随时随地手机看文章

12864是128*64点阵液晶模块的点阵数简称,业界约定俗成的简称。


一、液晶显示模块概述
12864A-1 汉字图形点阵液晶显示模块,可显示汉字及图形,内置 8192 个中文汉字(16X16 点阵,16*8=128,16*4=64,一行只能写 8 个汉字,4 行;、128 个字符(8X16 点阵)及 64X256 点阵显示 RAM(GDRAM))。
主要技术参数和显示特性:
电源:VDD 3.3V~+5V(内置升压电路,无需负压);
显示内容:128 列× 64 行(128 表示点数)
显示颜色:黄绿
显示角度:6:00 钟直视
LCD 类型:STN
与 MCU 接口:8 位或 4 位并行/3 位串行
配置 LED 背光
多种软件功能:光标显示、画面移位、自定义字符、睡眠模式等

引脚定义:D0-D7,RS,RES,RD,WR,CS,BL;具体头文件定义如下:

#ifndef LCD12864_H
#define LCD12864_H

#define LCD12864_MAJOR 242
#define DEV_NAME "lcd12864"

#define LCD12864_IOCTL 'l'
#define SET_FONT_SIZE _IOW(LCD12864_IOCTL,0 ,unsigned int)
#define SET_LCD_PAGE _IOW(LCD12864_IOCTL,1 ,unsigned int)
#define SET_LCD_COLUMN _IOW(LCD12864_IOCTL,2 ,unsigned int)
#define CLR_SCREEN _IOW(LCD12864_IOCTL,3 ,unsigned int)
#define BACKLIGHT_CTRL _IOW(LCD12864_IOCTL,4 ,unsigned int)
#define CONTRAST_SETTING _IOW(LCD12864_IOCTL,5 ,unsigned int)

#define LCD_DATA_0 S3C2410_GPC8
#define LCD_DATA_1 S3C2410_GPC9
#define LCD_DATA_2 S3C2410_GPC10
#define LCD_DATA_3 S3C2410_GPC11

#define LCD_DATA_4 S3C2410_GPC12
#define LCD_DATA_5 S3C2410_GPC13
#define LCD_DATA_6 S3C2410_GPC14
#define LCD_DATA_7 S3C2410_GPC15


#define LCD_E_RD S3C2410_GPD0
#define LCD_RW_WR S3C2410_GPD1
#define LCD_RS S3C2410_GPD2
#define LCD_RES S3C2410_GPD3
#define LCD_CS1 S3C2410_GPD4
#define LCD_BL S3C2410_GPD5


#define LCD_DATA_CFG0_OUTP S3C2410_GPC8_OUTP
#define LCD_DATA_CFG1_OUTP S3C2410_GPC9_OUTP
#define LCD_DATA_CFG2_OUTP S3C2410_GPC10_OUTP
#define LCD_DATA_CFG3_OUTP S3C2410_GPC11_OUTP

#define LCD_DATA_CFG4_OUTP S3C2410_GPC12_OUTP
#define LCD_DATA_CFG5_OUTP S3C2410_GPC13_OUTP
#define LCD_DATA_CFG6_OUTP S3C2410_GPC14_OUTP
#define LCD_DATA_CFG7_OUTP S3C2410_GPC15_OUTP


#define LCD_E_RD_CFG_OUTP S3C2410_GPD0_OUTP
#define LCD_RW_WR_CFG_OUTP S3C2410_GPD1_OUTP
#define LCD_RS_CFG_OUTP S3C2410_GPD2_OUTP
#define LCD_RES_CFG_OUTP S3C2410_GPD3_OUTP
#define LCD_CS1_CFG_OUTP S3C2410_GPD4_OUTP
#define LCD_BL_CFG_OUTP S3C2410_GPD5_OUTP


#define FONT_SIZE_8 8
#define FONT_SIZE_16 16


#endif

将引脚单独用头文件重新自己定义一次,以提高代码的可移植性。


下面看看模块初始化/释放函数:




static int __init lcd12864_init( void )
{
int ret;
dev_t devno;

DBPRINTF(KERN_ALERT " %s enter!n " ,__func__);
devno = MKDEV(lcd12864_major, 0 );
if ((ret = register_chrdev_region(devno, 1 ,DEV_NAME)) < 0 )
{
if ((ret = alloc_chrdev_region( & devno, 0 , 1 , DEV_NAME)) < 0 )
{
DBPRINTF(KERN_ALERT " chrdev region fail!ret=%d;n " ,ret);
return ret;
}
else
{
lcd12864_major = MAJOR(devno);
}
}
cdev_init( & lcd_cdev, & lcd12864_ops);
lcd_cdev.owner = THIS_MODULE;
lcd_cdev.ops = & lcd12864_ops;

ret = cdev_add( & lcd_cdev, devno, 1 );
if (ret < 0 )
{
goto fail_reg;
}

lcd_dev_class = class_create(THIS_MODULE, DEV_NAME);
if (IS_ERR(lcd_dev_class))
{
goto fail_cdev;
}
device_create(lcd_dev_class, NULL, devno, NULL, DEV_NAME);

lcd_bd_info = kmalloc( sizeof ( struct lcd_board_info),GFP_KERNEL);
lcd_bd_info -> font_size = 16 ;

#ifdef NORMAL
lcd_bd_info -> pag = 0 ;
lcd_bd_info -> column = 0 ;
#else
lcd_bd_info -> pag = 6 ;
lcd_bd_info -> column = 112 ;
#endif
lcd_bd_info -> lcd_data_t = lcd_data_table;
lcd_bd_info -> lcd_data_cfg_t = lcd_data_cfg_table;

spin_lock_init( & lock );

gpio_pin_init();
// gpio_pin_init();


ret = init_lcd12864();
if (ret < 0 )
{
goto fail_dev;
}
back_light_ctrl( 1 );
clear_lcd_screen( 0x00 );
DBPRINTF(KERN_ALERT " %s leave,init success!n " ,__func__);
return ret;

fail_dev:
device_destroy(lcd_dev_class, devno);
class_destroy(lcd_dev_class);

fail_cdev:
cdev_del( & lcd_cdev);
fail_reg:
unregister_chrdev_region(devno, 1 );
return ret;
}


static void __exit lcd12864_exit( void )
{
kfree(lcd_bd_info);
device_destroy(lcd_dev_class, MKDEV(lcd12864_major, 0 ));
class_destroy(lcd_dev_class);
cdev_del( & lcd_cdev);
unregister_chrdev_region(MKDEV(lcd12864_major, 0 ), 1 );
}

module_init(lcd12864_init);
module_exit(lcd12864_exit);

MODULE_LICENSE( " GPL " );
MODULE_AUTHOR( " HOY " );
MODULE_DESCRIPTION( " gonsin 128x64 lcd driver " );



以上主要工作是:通过register_chrdev_region静态分配设备号devno,如果分配失败,则通过系统alloc_chrdev_region动态分配;


此处通过cdev创建字符设备;通过cdev_add添加入系统中。通过class_create和device_create生成并注册一个逻辑设备,通过此工作,可以在/dev/下面看到设备名;


初始化lcd_board_info结构,lcd_board_info结构定义如下:




struct lcd_board_info{

unsigned int font_size;
unsigned int pag;
unsigned int column;
unsigned long * lcd_data_t;
unsigned long * lcd_data_cfg_t;
};

static struct lcd_board_info * lcd_bd_info;



其他变量和头文件定义如下:




#include < linux / fs.h >
#include < linux / module.h >
#include < linux / init.h >
#include < mach / regs - gpio.h >
#include < linux / ioctl.h >
#include < linux / cdev.h >
#include < linux / slab.h >
#include < linux / uaccess.h >
#include < linux / device.h >
#include < asm / io.h >
#include < linux / delay.h >

#define DEBUG // 调试状态
#ifdef DEBUG
#define DBPRINTF(fmt,args...) printk(KERN_ALERT "lcd:" fmt, ##args)
#else
#define DBPRINTF(fmt,args...)
#endif

#include " lcd_12864.h "

#define NORMAL // 正常模式


static struct class * lcd_dev_class;

struct cdev lcd_cdev;

static int lcd12864_major = LCD12864_MAJOR;

static unsigned long lcd_data_table[] = {
LCD_DATA_0,
LCD_DATA_1,
LCD_DATA_2,
LCD_DATA_3,

LCD_DATA_4,
LCD_DATA_5,
LCD_DATA_6,
LCD_DATA_7,
};

/**/
static unsigned long lcd_data_cfg_table[] =
{
LCD_DATA_CFG0_OUTP,
LCD_DATA_CFG1_OUTP,
LCD_DATA_CFG2_OUTP,
LCD_DATA_CFG3_OUTP,

LCD_DATA_CFG4_OUTP,
LCD_DATA_CFG5_OUTP,
LCD_DATA_CFG6_OUTP,
LCD_DATA_CFG7_OUTP,
};

/*
static unsigned char io_read_byte()
{

}
*/
spinlock_t lock ;




然后调用以下函数进行gpio引脚的初始化、液晶屏的初始化:




static int gpio_pin_init( void )
{

int ii;
s3c2410_gpio_cfgpin(LCD_CS1, LCD_CS1_CFG_OUTP);
s3c2410_gpio_cfgpin(LCD_RES, LCD_RES_CFG_OUTP);
s3c2410_gpio_cfgpin(LCD_RS, LCD_RS_CFG_OUTP);
s3c2410_gpio_cfgpin(LCD_RW_WR, LCD_RW_WR_CFG_OUTP);
s3c2410_gpio_cfgpin(LCD_E_RD, LCD_E_RD_CFG_OUTP);
s3c2410_gpio_cfgpin(LCD_BL, LCD_BL_CFG_OUTP);

for (ii = 0 ; ii < 8 ; ii ++ )
{
s3c2410_gpio_cfgpin(lcd_bd_info -> lcd_data_t[ii], lcd_bd_info -> lcd_data_cfg_t[ii]);
}
return 0 ;
}


static unsigned char init_cmd[] = {
0xe2 ,
0xa0 ,
0xc0 ,
0xA2 ,
0x2B ,
0x2E ,
0x2F ,
0x27 ,
0xAF ,
0 ,
};


static int init_lcd12864( void )
{

int ii;
s3c2410_gpio_setpin(LCD_CS1, 0 );
udelay( 500 );
s3c2410_gpio_setpin(LCD_RES, 0 );
udelay( 500 );
s3c2410_gpio_setpin(LCD_RES, 1 );
udelay( 500 );

for (ii = 0 ;init_cmd[ii] != 0 ;ii ++ )
{
send_cmd(init_cmd[ii]);
udelay( 50 );
}
return 0 ;
}




以下为写液晶屏和写命令的操作:




#ifdef NORMAL
/* 往液晶中写入1个字符数据 */
static void io_write_byte(unsigned char data)
{
unsigned char ii;
spin_lock( & lock );

for (ii = 0 ;ii < 8 ;ii ++ )
{
if (data & 0b1)
{
s3c2410_gpio_setpin(lcd_bd_info -> lcd_data_t[ii], 1 );
}
else
{
s3c2410_gpio_setpin(lcd_bd_info -> lcd_data_t[ii], 0 );
}
data = data >> 1 ;
}
// __raw_writel(((__raw_readl(S3C2410_GPCDAT)&~(0xff<<8))|(data<<8)),S3C2410_GPCDAT);

spin_unlock( & lock );

s3c2410_gpio_setpin(LCD_RS, 1 );
s3c2410_gpio_setpin(LCD_RW_WR, 0 );
s3c2410_gpio_setpin(LCD_E_RD, 1 );
s3c2410_gpio_setpin(LCD_CS1, 1 );
udelay( 1 );
s3c2410_gpio_setpin(LCD_CS1, 0 );
udelay( 1 );

}
#else
static void io_write_byte(unsigned char data)
{
unsigned char ii;
spin_lock( & lock );
for (ii = 0 ;ii < 8 ;ii ++ )
{
if (data & 0x80 )
{
// DBPRINTF(KERN_ALERT "[||||||||||||||||||||]n");
s3c2410_gpio_setpin(lcd_bd_info -> lcd_data_t[ii], 1 );
}
else
{
// DBPRINTF(KERN_ALERT "[--------------------]n");
s3c2410_gpio_setpin(lcd_bd_info -> lcd_data_t[ii], 0 );
}
data = data << 1 ;
}
spin_unlock( & lock );
// DBPRINTF(KERN_ALERT "n");

s3c2410_gpio_setpin(LCD_RS, 1 );
s3c2410_gpio_setpin(LCD_RW_WR, 0 );
s3c2410_gpio_setpin(LCD_E_RD, 1 );

s3c2410_gpio_setpin(LCD_CS1, 1 );
udelay( 1 );
s3c2410_gpio_setpin(LCD_CS1, 0 );
udelay( 1 );
}
#endif

// 发送命令
static int send_cmd(unsigned char cmd)
{
int ii;
unsigned char tmp;
tmp = 0x00 ;
spin_lock( & lock );

for (ii = 0 ;ii < 8 ;ii ++ )
{
if (cmd & 0x80 )
{
s3c2410_gpio_setpin(lcd_bd_info -> lcd_data_t[ii], 1 );
}
else
{
s3c2410_gpio_setpin(lcd_bd_info -> lcd_data_t[ii], 0 );
}
cmd = cmd << 1 ;
}
/* ***************** */
/*
for(ii=0;ii<8;ii++)
{
tmp = tmp<<1;
if(cmd&0b1)
{
tmp|=0b1;
}
else
{
tmp &= 0b0;
}
cmd = cmd>>1;

}
__raw_writel(((__raw_readl(S3C2410_GPCDAT)&~(0xff<<8))|(tmp<<8)),S3C2410_GPCDAT); */
/* ***************** */

spin_unlock( & lock );


s3c2410_gpio_setpin(LCD_RS, 0 );
s3c2410_gpio_setpin(LCD_RW_WR, 0 );
s3c2410_gpio_setpin(LCD_E_RD, 1 );
s3c2410_gpio_setpin(LCD_CS1, 1 );
udelay( 1 );

s3c2410_gpio_setpin(LCD_CS1, 0 );
udelay( 1 );
return 0 ;
}



static int dev_write_data( const char * data)
{
unsigned char dl,dh;
int i,j;
spin_lock( & lock );
dh = lcd_bd_info -> column / 16 ;
dl = lcd_bd_info -> column - dh * 16 ;
for (i = 0 ; i < 2 ; i ++ )
{
send_cmd( 0xB7 - i - lcd_bd_info -> pag);
send_cmd( 0x10 + dh);
send_cmd(dl);

#ifdef NORMAL
for (j = 0 ;j < 16 ;j ++ )
io_write_byte(data[lcd_bd_info -> font_size * i + j]);
#else
for (j = 0 ;j < 16 ;j ++ )
io_write_byte(data[lcd_bd_info -> font_size * ( 1 - i) + ( 15 - j)]);
#endif
}
spin_unlock( & lock );
return 0 ;
}

[1] [2]
关键字:s3c2440  液晶驱动 引用地址:基于s3c2440的12864液晶驱动

上一篇:s3c2440(2410) USB HOST不稳定的原因及解决方法
下一篇:S3C2410触摸屏驱动代码分析1

推荐阅读最新更新时间:2024-11-13 10:55

s3c2440学习之路-008 uart实现printf函数
1.基本原理 因为程序目前处于裸板阶段,只能输出字符串,没有C语言的printf函数可以调用。但是在调试程序时,想像C语言一样调用printf来调试,因此只能自己来实现了。 C语言中,printf函数的原型为: int printf(const char *format, ...); 1.1 可变参数 … 参数有2个, “const char *format” 和 “…”,这个“…”就是可变参数,下面先讲解一下如何识别这个可变参数。 参数的传递会顺序的放到栈里面,而printf函数可获取的参数只有 “const char *format” 和 “…”,不过format刚好指向了第1个参数的首地址,因此可以通过form
[单片机]
<font color='red'>s3c2440</font>学习之路-008 uart实现printf函数
移植u-boot-2010.09到S3C2440(六)—— SDRAM地址与容量的计算
对于 GEC2410 开发板,SDRAM 的物理起始地址是 0x30000000,结束地址是0x34000000,大小是64Mbytes。 我有个疑问?为什么SDRAM 的物理起始地址是 0x30000000,结束地址是 0x34000000,得出的大小是64Mbytes? 因为容量是用10进制显示的,故我们得把0x34000000-0x30000000=0x4000000转换成10进制。(转换方法见附) 4*16^6+0*16^5+0*16^4+0*16^3+0*16^2+0*16^1+0*16^0=67108864(Byte) 一般不要用十六进制转成二进制,二进制转成10进制方法算那个比较麻烦: 0x4000000=0
[单片机]
linux-2.6.35.3内核移植(s3c2440
宿 主机:Fedora13 目标 机:s3c2440 交叉 编译 器:arm-linux-gcc-3.4.1 交叉编译器路径:/usr/local/arm/3.4.1 要移植 的内核 版本:linux-2.6.35.3 文件 系统 类型: yaffs2 一、准备工作 1、下载 解压内核 从官网上下载linux-2.6.35的内核, ftp://ftp.kernel.org/pub/linux/kernel/v2.6/ ,文件不大,约85M。 新建一个工作目录s3c2440,将内核源码包拷贝至工作目录下,再解压。 2、移植yaffs2驱动 下载最新的驱动http://www.aleph1.co.uk/cgi
[单片机]
ARM9的中断处理技术详细深入剖析-三星S3C2440处理器
1、中断的生命周期 中断信号产生(中断源)—》中断信号过滤(中断控制器)—》中断信号处理(CPU) 1.1 中断源 在中断的生命周期中,中断源的作用是负责产生中断信号。 S3C2440支持60个中断源(包含子中断源,不包括EINT8_23等里面的独立中断源,例如串口的发送中断、接收中断、错误中断属于串口的子中断源。); S3C6410支持64个中断源; S5PV210支持93个中断源; 1.2 中断控制器 1.3 中断处理 1)非向量方式(2440) 2)向量方式(6410/210) (对于向量方式,是直接进入中断函数(而不是跳转到中断程序总入口),因为中断函数(的地址)保存在相应寄存器里,根据相应中断源跳转
[单片机]
S3C2440 代码重定位实验(一)
实验环境 本实验基于这样的开发环境:在Ubuntu18.04.3发行版上使用编译器arm-linux-gcc(arm-none-linux-gnueabi, 4.3.2 Sourcery G++ Lite 2008q3-72)编译,并运行于S3C2440 ARM硬件平台上。S3C2440是一款32位的ARM SoC。 链接(linking) 所谓链接,就是将各种代码和数据部分收集起来并组合成一个单一文件的过程,这个单一文件可以被加载到存储器内并被执行。链接既可以执行于编译时,也可以执行于加载时,也可以执行于运行时。若执行于编译时,则是由编译器在将源代码翻译成机器码时负责;若执行于加载时,则是由加载器(loader)把可执行程序
[单片机]
<font color='red'>S3C2440</font> 代码重定位实验(一)
LPC2138+LCD12864显示实时时钟程序 keil与proteus联调
近年来,随着计算机技术及集成电路技术的发展,嵌入式技术日渐普及,在通讯、网络、工控、医疗、电子等领域发挥着越来越重要的作用。嵌入式系统无疑成为当前最热门最有发展前途的IT应用领域之一。32位嵌入式系统发展很快,32位单片机已逐渐占领8位机的市场,并以很高的性价比赢得了越来越多的用户的青睐。随着科技和工艺的进步,32位单片机的优势会更加突显出来,将会成为嵌入式系统的主流。在32位嵌入式系统中,基于ARM的应用占据了大部分份额。 实时时钟(RTC)器件是一种能提供日历/时钟、数据存储等功能的专用集成电路,常用作各种计算机系统的时钟信号源和参数设置存储电路。RTC具有计时准确、耗电低和体积小等特点,特别适用于在各种嵌入式系统忠记录事件
[单片机]
LPC2138+LCD<font color='red'>12864</font>显示实时时钟程序 keil与proteus联调
根文件系统构建(JZ2440-S3C2440)
uboot的目的是启动内核,内核的目的是为了启动应用程序,应用程序位于根文件系统上面。 一、使用busybox制作根文件系统 busybox下载地址:http://www.busybox.net/downloads/ 这里使用busybox-1.7.0(包名:busybox-1.7.0.tar.bz2 ) 解压命令:tar xjf busybox-1.7.0.tar.bz2 busybox目录下的INSTALL文件中部分代码: 1、配置busybox 在busybox-1.7.0目录下,执行:“make menuconfig”命令进入配置界面 (1)设置“TAB”键补全 Busyb
[单片机]
根文件系统构建(JZ2440-S3C2440)
S3C2440的NAND Flash控制器
首先还是启动方式NAND Flash的过程,因为NAND Flash是不支持程序在NAND内部运行的所以要把NAND搬到内存中运行,由于S3C2440内部的SRAM只有4K,当程序远大于4K时,这种方法是行不通的,于是我们可以让NAND中4K之后的程序搬到SDRAM中来运行 正如数据手册上所说,NOR的价格较NAND来说比较昂贵,再加上NOR的容量远比NAND小的多,再比如NOR一页的字节数也比NAND大的很多,而要在某个地址写入数据,必须先把地址所在的页擦除,所以更多的时候NAND用来存储数据,NOR用来存储程序。 如上图模型,当程序的容量大于4K的时候,NAND的前4K的程序将会被硬件自动引导到2440的S
[单片机]
<font color='red'>S3C2440</font>的NAND Flash控制器
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved