基于S3C2440的LCD1602驱动的设计
扫描二维码
随时随地手机看文章
开发目标平台:linux-2.6.28+S3C2440+CRAMFS/YAFFS2
开发环境:UBUNTU-9.04+arm-linux-gcc-3.4.1
这次需要在s3c2440上开发一个简单的字符型LCD驱动,具体情况如下:
LCD1602共有16根管脚,控制信号3根RS,RW,RE,数据线8根DB0~DB7,可以支持8位数据格式和4位数据格式。
RS:寄存器选择1:数据;0:指令【由GPIO控制】
R/W:读、写操作选择1:读;0:写【我的硬件里直接置低电平】
RE:使能信号【由GPIO控制】
数据线DB4~DB7,分别连接4根GPIO口,DB0~DB3置高。
首先内核注册驱动函数:
static int __init mylcd_init(void)
{
int i;
int ret = 0;
for(i = 0;i < MAX_NUM;i++){
s3c2410_gpio_cfgpin(plcd[i].pin,plcd[i].pin_out);
}
//初始化GPIO为输出
ret =register_chrdev(LCD_MAJOR,DEVICE_NAME,&mylcd_fops);
if(ret < 0){
printk(KERN_WARNING "Cannot register driver of mylcdn");
return ret;
}
printk(DEVICE_NAME " Init Is Okn");
return 0;
}
驱动注销函数
static void __exit mylcd_exit(void)
{
unregister_chrdev(LCD_MAJOR,DEVICE_NAME);
printk(KERN_INFO " remove driver of myLCDn");
}
module_init(mylcd_init);
module_exit(mylcd_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("qlx-1983@163.com");
MODULE_DESCRIPTION("mylcd driver for s3c2440");
驱动文件操作结构体,我对外提供IOCTL接口:
static struct file_operations mylcd_fops = {
.owner = THIS_MODULE,
.ioctl = mylcd_ioctl,
.open = mylcd_open,
.release = mylcd_release
};
驱动的open和release函数的实现:
static int mylcd_open(struct inode *inode,struct file *file)
{
return 0;
}
static int mylcd_release(struct inode *inode,struct file *file)
{
return 0;
}
ioctl函数的实现:
static int mylcd_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned int arg)
{
if(_IOC_TYPE(cmd) != GPIO_IOF_MAGIC)
{
return -ENOTTY;
}
if(_IOC_NR(cmd) >= GPIO_MAXNR)
{
return -ENOTTY;
}
switch(cmd)
{
case LCD_INIT: //初始化
myLcd_port_init();
break;
case LCD_SCREEN_CLEAR: //清屏
myLcd_Screen_Clear();
break;
case LCD_CURSOR_RETURN: //归位
myLcd_Cursor_Home();
break;
case LCD_DDRAM_AD_SET: //设置DDRAM地址
myLcd_ddram_ad_set(arg);
break;
case LCD_DATA_WRITE: //写数据
myLcd_data_write(arg);
break;
default:
break;
}
return 0;
}
因为我对LCD的功能要求比较简单,所以,只是提供了上面这些功能,当然,LCD1602还有很多接口可以对外提供,如果你感兴趣,可以补充一下!
另外,附上针对这个LCD我写的上层接口函数:
int OpenLcd(const char *lcd_name)
{
int Lcd_fd;
if(access(lcd_name,F_OK) == 0){
printf("%s Can Be opened!n",lcd_name);
}else{
system("mknod /dev/myLcd c 204 0");
}
Lcd_fd = open(lcd_name,O_RDWR);
if(Lcd_fd < 0){
printf("Open %s Is Failed!n");
return 0;
}
printf("Open The Screen!n");
return Lcd_fd;
}
void CloseLcd(int Lcd_fd)
{
printf("Close The Screen!n");
close(Lcd_fd);
}
void InitLcd(int Lcd_fd)
{
printf("Init The Screen!n");
ioctl(Lcd_fd,LCD_INIT,0);
}
void ClearLcd(int Lcd_fd)
{
printf("Clear The Screen!n");
ioctl(Lcd_fd,LCD_SCREEN_CLEAR,0);
ioctl(Lcd_fd,LCD_CURSOR_RETURN,0);
}
void PrintfLcd(int Lcd_fd,const char *src,unsigned int pos)
{
int src_len = 0;
int i;
src_len = strlen(src);
if((pos >= 0)&&(pos <= 32)){
if(src_len <= (32-pos)){
ioctl(Lcd_fd,LCD_DDRAM_AD_SET,pos);
for(i = 0;i < src_len ;i++){
ioctl(Lcd_fd,LCD_DATA_WRITE,src[i]);
}
}else{
printf("The Lcd Is Not Enough Lengthn");
}
}else{
printf("The Pos Is Out Size Of Addressn");
}
}
以下是测试应用程序:
int main(int argc, char *argv[])
{
int Lcd_fd;
Lcd_fd = OpenLcd(DEV_NAME);
InitLcd(Lcd_fd);
PrintfLcd(Lcd_fd,"AAAABBB",0);
PrintfLcd(Lcd_fd,"FFFFFFFFFFF",16);
sleep(10);
ClearLcd(Lcd_fd);
PrintfLcd(Lcd_fd,"AAAABBB",0);
PrintfLcd(Lcd_fd,"DDDDDDDD",16);
CloseLcd(Lcd_fd);
}