求助:linux下lcd 液晶(192*32 st7920控制器,带中文字库)驱动问题,希望开发过st7920控制
目前在学习linux 下开发lcd液晶驱动,lcd 是192*32的,st19232控制器,带中文字符,硬件平台是:arm9200的现在出现了问题,搞不懂错在哪,望路过的各位高手帮忙看看,帮帮我啊,先谢谢各位了!!
程序驱动部分如下:
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#define DEBUG_HG19232
//#undefDEBUG_HG19232
#ifdef DEBUG_HG19232
#define DBG_HG19232(fmt, args...) printk(fmt,## args)
#else
#define DBG_HG19232(fmt, args...)
#endif
/* PB9 --> RS, PB10 --> RW, PB11 --> E */
#define JHD_RS AT91C_PIO_PB9 //指令数据选择--H:数据,L:指令
#define JHD_RW AT91C_PIO_PB10 //读写选择--H:读,L:写
#define JHD_E AT91C_PIO_PB11 //使能信号
#define JHD_DIR AT91C_PIO_PB0 //方向选择,H--输出,L写入
/* DB0-DB7 --> PB0-PB7 */ //8个引脚
#define DB0 AT91C_PIO_PB1
#define DB1 AT91C_PIO_PB2
#define DB2 AT91C_PIO_PB3
#define DB3 AT91C_PIO_PB4
#define DB4 AT91C_PIO_PB5
#define DB5 AT91C_PIO_PB6
#define DB6 AT91C_PIO_PB7
#define DB7 AT91C_PIO_PB8
#define DISP_READY_()while (disp_test_busy())
#define DISP_CLR 0x1
#define DISP_RET_HOME 0x2
#define LCD_AC_INC_SHIFT_OFF 0x6 //input set
#define DIS_OFF_CUR_OFF_BLIN_OFF 0x8
#define DIS_ON_CUR_OFF_BLIN_OFF 0x0c
#define DIS_ON_CUR_ON_BLIN_OFF 0x0e
//--------------------------
#define FUNC_CONFIG (0X1<<5)
#define BUS_8BIT (0x1<<4)
#define GMOD_ON (0X1<<1)
#define RE_ENABLE (0X1<<2)
//---------------------------------
#define BIT8_BASIC_DOTS 0x30
#define NOSHIFT_ACINC_RIGHT 0x7
#define CMD 0
#define DATA 1
#define HG19232_MAJOR 254
static void hg19232_hardware_init (void);
static int hg19232_open(struct inode *, struct file *);
static int hg19232_close(struct inode *, struct file *);
static int hg19232_read(struct file *, char *, size_t, loff_t *);
static int hg19232_write(struct file *, const char *, size_t, loff_t *);
static void __init hg19232_init (void);
static void __exit hg19232_cleanup (void);
static int disp_test_busy(void);
static int write_bus(unsigned int bus);
static int disp_data (unsigned int data);
static int disp_cmd (unsigned int cmd);
static struct file_operations hg19232_fops = {
open: hg19232_open,
read: hg19232_read,
write: hg19232_write,
release: hg19232_close,
};
static unsigned int data;
static int jhd_initialized = 0;
static void hg19232_hardware_init (void)
{
// I/O init
//pin0--pin11使能
AT91_SYS->PIOB_PER |= JHD_RS | JHD_RW | JHD_DIR | JHD_E | DB0 | DB1 | DB2 | DB3 | DB4 | DB5 |DB6 | DB7;
AT91_SYS->PIOB_OER |= JHD_RS | JHD_RW | JHD_DIR | JHD_E | DB0 | DB1 | DB2 | DB3 | DB4 | DB5 |DB6 | DB7;
AT91_SYS->PIOB_SODR |= JHD_RS | JHD_RW | JHD_DIR | JHD_E | DB0 | DB1 | DB2 | DB3 | DB4 | DB5 |DB6 | DB7;
//**************************************************************************************
// Lcd init
//功能设置,8位数据接口,
mdelay(45);
//Function set
disp_cmd(FUNC_CONFIG|BUS_8BIT);
mdelay(1);
disp_cmd(FUNC_CONFIG|BUS_8BIT);
mdelay(1);
// disp_cmd(FUNC_CONFIG|BUS_8BIT|GMOD_ON);
//Display ON/OFF control ,BCD
disp_cmd(DIS_ON_CUR_OFF_BLIN_OFF);
mdelay(1);
// Display clear
disp_cmd(DISP_CLR);
mdelay(15);
// disp_cmd(0x80);
// mdelay(1);
//Entry mode set
disp_cmd(LCD_AC_INC_SHIFT_OFF);
//************************************************************************************
}
static void disp_refresh()
{
}
static int disp_test_busy(void)
{
unsigned char flag;
//PIO禁止
AT91_SYS->PIOB_PDR |= DB0 | DB1 | DB2 | DB3 | DB4 | DB5 |DB6 | DB7;//set Input
//EA = 0;
//write_bus(0xff);// lockinputdata.
AT91_SYS->PIOB_CODR |= JHD_RS; // select command register. RS=0,为指令
AT91_SYS->PIOB_SODR |= JHD_RW | JHD_DIR; // read mode on.RW=1,读,输出
AT91_SYS->PIOB_SODR |= JHD_E; // read Data... ,高电平
flag = AT91_SYS->PIOB_PSR;//状态寄存器
AT91_SYS->PIOB_CODR |= JHD_E;
//EA = 1;
AT91_SYS->PIOB_PER |= DB0 | DB1 | DB2 | DB3 | DB4 | DB5 |DB6 | DB7;//reset Output
return (flag & DB7)? 1 : 0;
}
// write $bus to DB0-DB7
static int write_bus(unsigned int bus)
{
if ((bus >> 0 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB0;//置1清除,为0
else
AT91_SYS->PIOB_SODR |= DB0;//置1写入1
if ((bus >> 1 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB1;
else
AT91_SYS->PIOB_SODR |= DB1;
if ((bus >> 2 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB2;
else
AT91_SYS->PIOB_SODR |= DB2;
if ((bus >> 3 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB3;
else
AT91_SYS->PIOB_SODR |= DB3;
if ((bus >> 4 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB4;
else
AT91_SYS->PIOB_SODR |= DB4;
if ((bus >> 5 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB5;
else
AT91_SYS->PIOB_SODR |= DB5;
if ((bus >> 6 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB6;
else
AT91_SYS->PIOB_SODR |= DB6;
if ((bus << 7 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB7;
else
AT91_SYS->PIOB_SODR |= DB7;
return bus;
}
//数据操作,且为写;即RS=1,RW=0
static int disp_data (unsigned int data)
{
DISP_READY_();//忙等待
//------------------------------------设置命令的执行环境
//设置RS=1,RW=0,写数据,方向写入
AT91_SYS->PIOB_CODR |=JHD_DIR;
AT91_SYS->PIOB_SODR |= JHD_RS ;
AT91_SYS->PIOB_CODR |= JHD_RW ;
write_bus(data); //将cmd 写入到引脚
AT91_SYS->PIOB_SODR |= JHD_E;
mdelay(1);
AT91_SYS->PIOB_CODR |= JHD_E;
// mdelay(1);
return 0;
}
//执行指令,且为写,即RS=0,RW=0
static int disp_cmd (unsigned int cmd)
{
DISP_READY_();//忙等待
// write_bus(cmd); //将cmd 写入到引脚
//------------------------------------设置命令的执行环境
//设置RS=0,RW=0,写指令,方向写入
AT91_SYS->PIOB_CODR |=JHD_DIR;
AT91_SYS->PIOB_CODR |= JHD_RW | JHD_RS;
write_bus(cmd); //将cmd 写入到引脚
AT91_SYS->PIOB_SODR |= JHD_E;
mdelay(1);
AT91_SYS->PIOB_CODR |= JHD_E;
mdelay(1);
return 0;
}
static int hg19232_open (struct inode *inode, struct file *file)
{
MOD_INC_USE_COUNT;
return 0;
}
static int hg19232_close (struct inode *inode, struct file *file)
{
MOD_DEC_USE_COUNT;
return 0;
}
static int hg19232_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
return 0;
}
// 2个字节数据/指令
static int hg19232_write (struct file *file, const char *buf, size_t count, loff_t *ppos)
{
unsigned char choice,disp;
get_user(choice,buf++);//从buf处取一个字节到disp
//DBG_HG19232("choice:%d\n",choice);
switch (choice){
case CMD://指令
//DBG_HG19232("cmd\n");
get_user(disp,buf);//从buf处取一个字节到disp
disp_cmd(disp);//操作指令
break;
case DATA://数据
//DBG_HG19232("data\n");
get_user(disp,buf);//从buf处取一个字节到disp
disp_data(disp);//操作数据
break;
default:
//DBG_HG19232("default\n");
}
return 0;
}
static void __init hg19232_init (void)
{
int i;
if (jhd_initialized == 1)
return 0;
hg19232_hardware_init(); //液晶初始化
i = register_chrdev(HG19232_MAJOR, "hg19232", &hg19232_fops);
if(i<0){//失败
printk(KERN_CRIT"hg19232:i = %d\n",i);
return -EIO;
}
printk(KERN_CRIT"hg19232:hg19232_drv registered:)=\n");
jhd_initialized = 1;
return 0;
}
static void __exit hg19232_cleanup (void)
{
unregister_chrdev(HG19232_MAJOR, "hg19232");
return;
}
module_init(hg19232_init);
module_exit(hg19232_cleanup);
测试程序如下:
#include <stdio.h>
#include <fcntl.h>
#define LCD_CLEAR 1 // clear screen
#define LCD_HOME 2 // cursor home
#define BIT8_BASIC_DOTS 0x30
#define LCD_AC_INC_SHIFT_OFF 0x06 // input set
//--------------------------
#define FUNC_CONFIG (0X1<<5)
#define BUS_8BIT (0x1<<4)
#define GMOD_ON (0X1<<1)
#define RE_ENABLE (0X1<<2)
//---------------------------------
int lcdfd = -1;
int lcd_open()
{
lcdfd = open("/dev/hg19232", O_RDWR);
if (lcdfd == -1)
{
printf("open /dev/hg19232 failed\n");
return EOF;
}
//printf("open hg19232 ok\n");
//init set
// lcd_set(BIT8_BASIC_DOTS);
lcd_set(LCD_CLEAR);
lcd_set(FUNC_CONFIG|BUS_8BIT);//function set
lcd_set(LCD_HOME); //cursor go home
lcd_set(0x04);
lcd_set(LCD_AC_INC_SHIFT_OFF); //input set
lcd_set(LCD_CLEAR);
lcd_set(0x80);
return lcdfd;
}
int lcd_close()
{
if (lcdfd == -1)
return EOF;
close(lcdfd);
return 0;
}
//-----------------------------------------------
//执行数据
void lcd_put(char dat)
{
char buf;
buf = 1; //data flag
buf = dat;
write(lcdfd, buf, 2);
}
//执行指令
void lcd_set(char cmd)
{
char buf;
buf = 0; //commad flag
buf = cmd;
write(lcdfd, buf, 2);
}
int main()
{
lcd_open();
lcd_put('a');
lcd_close();
}
在测试时,在液晶上显示不了字符‘a';
不知问题出在哪里,向大家求助!! 希望大家帮忙看看啊!! st7920控制器的初始化一般步骤是怎样的呢??
下面的写法对吗
//---------------------------------
mdelay(45);
//Function set
disp_cmd(0x30);
mdelay(1);
disp_cmd(0x30);
mdelay(1);
//Display ON/OFF control ,BCD
disp_cmd(0x0c);
mdelay(1);
// Display clear
disp_cmd(0x01);
mdelay(15);
//Entry mode set
disp_cmd(0x06); 唉,没人理呀,还是这里没人才呢?? 这个根本就不是系统平台的事,arm-gcc?? windows 也可以用啊。
lz这样貼长篇的代码叫人家帮你找错误,这难度也太大了。你还不如问一下大家有没有相同或类似lcd的驱动程序,让你参考一下。 和LINUX有什么关系?先检查一下程序吧 恩,楼上几位说的对.
这几天我试着先用单片机来驱动,想如果在单片机下能驱动的话,那就好找出错在什么地方了,
我就用他们公司发给汇编程序,结果也没有用,我现在真怀疑是不是液晶本身存在问题. 对了,如果哪位有st19232控制器液晶驱动的话,可不可以发给我一份参考一下.
我在网上也搜了许多类似的,不过没找到st19232控制器的.
我的邮箱:th_chen@126.com
先谢谢各位了,谢谢那些抽空帮忙的好心人! 我在WIN下的程序在LINUX下小改一下(加一句 #define F_CPU 8000000UL )就可以用了,所以是你的程序的问题,和平台没多大关系 如果不是软件的问题,看看是不是接线错了,或者对比度调得看不见字了 ok,已解决 请问如何解决的呢?还有你的程序有没有错误,如果没错误可以参考一下,谢谢! 主要是硬件上的问题,线没接好,亮度也没调好。
还有在后来发现程序有个地方写错了。该好之后,汉字字符也可以显示了,否则只能显示普通的ascii字符。
代码重新贴一遍。
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#define DEBUG_HG19232
//#undefDEBUG_HG19232
#ifdef DEBUG_HG19232
#define DBG_HG19232(fmt, args...) printk(fmt,## args)
#else
#define DBG_HG19232(fmt, args...)
#endif
/* PB9 --> RS, PB10 --> RW, PB11 --> E */
#define JHD_RS AT91C_PIO_PB9 //指令数据选择--H:数据,L:指令
#define JHD_RW AT91C_PIO_PB10 //读写选择--H:读,L:写
#define JHD_E AT91C_PIO_PB11 //使能信号
#define JHD_DIR AT91C_PIO_PB0 //方向选择,H--输出,L写入
/* DB0-DB7 --> PB0-PB7 */ //8个引脚
#define DB0 AT91C_PIO_PB1
#define DB1 AT91C_PIO_PB2
#define DB2 AT91C_PIO_PB3
#define DB3 AT91C_PIO_PB4
#define DB4 AT91C_PIO_PB5
#define DB5 AT91C_PIO_PB6
#define DB6 AT91C_PIO_PB7
#define DB7 AT91C_PIO_PB8
#define DISP_READY_()while (disp_test_busy())
#define DISP_CLR 0x1
#define DISP_RET_HOME 0x2
#define LCD_AC_INC_SHIFT_OFF 0x6 //input set
#define DIS_OFF_CUR_OFF_BLIN_OFF 0x8
#define DIS_ON_CUR_OFF_BLIN_OFF 0x0c
#define DIS_ON_CUR_ON_BLIN_OFF 0x0e
//--------------------------
#define FUNC_CONFIG (0X1<<5)
#define BUS_8BIT (0x1<<4)
#define GMOD_ON (0X1<<1)
#define RE_ENABLE (0X1<<2)
//---------------------------------
#define BIT8_BASIC_DOTS 0x30
#define NOSHIFT_ACINC_RIGHT 0x7
#define CMD 0
#define DATA 1
#define HG19232_MAJOR 254
static void hg19232_hardware_init (void);
static int hg19232_open(struct inode *, struct file *);
static int hg19232_close(struct inode *, struct file *);
static int hg19232_read(struct file *, char *, size_t, loff_t *);
static int hg19232_write(struct file *, const char *, size_t, loff_t *);
static void __init hg19232_init (void);
static void __exit hg19232_cleanup (void);
static int disp_test_busy(void);
static int write_bus(unsigned int bus);
static int disp_data (unsigned int data);
static int disp_cmd (unsigned int cmd);
static struct file_operations hg19232_fops = {
open: hg19232_open,
read: hg19232_read,
write: hg19232_write,
release: hg19232_close,
};
static unsigned int data;
static int jhd_initialized = 0;
static void hg19232_hardware_init (void)
{
// I/O init
//pin0--pin11使能
AT91_SYS->PIOB_PER |= JHD_RS | JHD_RW | JHD_DIR | JHD_E | DB0 | DB1 | DB2 | DB3 | DB4 | DB5 |DB6 | DB7;
AT91_SYS->PIOB_OER |= JHD_RS | JHD_RW | JHD_DIR | JHD_E | DB0 | DB1 | DB2 | DB3 | DB4 | DB5 |DB6 | DB7;
AT91_SYS->PIOB_SODR |= JHD_RS | JHD_RW | JHD_DIR | JHD_E | DB0 | DB1 | DB2 | DB3 | DB4 | DB5 |DB6 | DB7;
//**************************************************************************************
// Lcd init
//功能设置,8位数据接口,
mdelay(45);
//Function set
disp_cmd(FUNC_CONFIG|BUS_8BIT);
mdelay(1);
disp_cmd(FUNC_CONFIG|BUS_8BIT);
mdelay(1);
// disp_cmd(FUNC_CONFIG|BUS_8BIT|GMOD_ON);
//Display ON/OFF control ,BCD
disp_cmd(DIS_ON_CUR_OFF_BLIN_OFF);
mdelay(1);
// Display clear
disp_cmd(DISP_CLR);
mdelay(15);
// disp_cmd(0x80);
// mdelay(1);
//Entry mode set
disp_cmd(LCD_AC_INC_SHIFT_OFF);
//************************************************************************************
}
static void disp_refresh()
{
}
static int disp_test_busy(void)
{
unsigned char flag;
//PIO禁止
AT91_SYS->PIOB_PDR |= DB0 | DB1 | DB2 | DB3 | DB4 | DB5 |DB6 | DB7;//set Input
//EA = 0;
//write_bus(0xff);// lockinputdata.
AT91_SYS->PIOB_CODR |= JHD_RS; // select command register. RS=0,为指令
AT91_SYS->PIOB_SODR |= JHD_RW | JHD_DIR; // read mode on.RW=1,读,输出
AT91_SYS->PIOB_SODR |= JHD_E; // read Data... ,高电平
flag = AT91_SYS->PIOB_PSR;//状态寄存器
AT91_SYS->PIOB_CODR |= JHD_E;
//EA = 1;
AT91_SYS->PIOB_PER |= DB0 | DB1 | DB2 | DB3 | DB4 | DB5 |DB6 | DB7;//reset Output
return (flag & DB7)? 1 : 0;
}
// write $bus to DB0-DB7
static int write_bus(unsigned int bus)
{
if ((bus >> 0 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB0;//置1清除,为0
else
AT91_SYS->PIOB_SODR |= DB0;//置1写入1
if ((bus >> 1 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB1;
else
AT91_SYS->PIOB_SODR |= DB1;
if ((bus >> 2 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB2;
else
AT91_SYS->PIOB_SODR |= DB2;
if ((bus >> 3 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB3;
else
AT91_SYS->PIOB_SODR |= DB3;
if ((bus >> 4 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB4;
else
AT91_SYS->PIOB_SODR |= DB4;
if ((bus >> 5 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB5;
else
AT91_SYS->PIOB_SODR |= DB5;
if ((bus >> 6 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB6;
else
AT91_SYS->PIOB_SODR |= DB6;
if ((bus >> 7 & 0x1 ) == 0)
AT91_SYS->PIOB_CODR |= DB7;
else
AT91_SYS->PIOB_SODR |= DB7;
return bus;
}
//数据操作,且为写;即RS=1,RW=0
static int disp_data (unsigned int data)
{
DISP_READY_();//忙等待
//------------------------------------设置命令的执行环境
//设置RS=1,RW=0,写数据,方向写入
AT91_SYS->PIOB_CODR |=JHD_DIR;
AT91_SYS->PIOB_SODR |= JHD_RS ;
AT91_SYS->PIOB_CODR |= JHD_RW ;
write_bus(data); //将cmd 写入到引脚
AT91_SYS->PIOB_SODR |= JHD_E;
mdelay(1);
AT91_SYS->PIOB_CODR |= JHD_E;
// mdelay(1);
return 0;
}
//执行指令,且为写,即RS=0,RW=0
static int disp_cmd (unsigned int cmd)
{
DISP_READY_();//忙等待
// write_bus(cmd); //将cmd 写入到引脚
//------------------------------------设置命令的执行环境
//设置RS=0,RW=0,写指令,方向写入
AT91_SYS->PIOB_CODR |=JHD_DIR;
AT91_SYS->PIOB_CODR |= JHD_RW | JHD_RS;
write_bus(cmd); //将cmd 写入到引脚
AT91_SYS->PIOB_SODR |= JHD_E;
mdelay(1);
AT91_SYS->PIOB_CODR |= JHD_E;
mdelay(1);
return 0;
}
static int hg19232_open (struct inode *inode, struct file *file)
{
MOD_INC_USE_COUNT;
return 0;
}
static int hg19232_close (struct inode *inode, struct file *file)
{
MOD_DEC_USE_COUNT;
return 0;
}
static int hg19232_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
return 0;
}
// 2个字节数据/指令
static int hg19232_write (struct file *file, const char *buf, size_t count, loff_t *ppos)
{
unsigned char choice,disp;
get_user(choice,buf++);//从buf处取一个字节到disp
//DBG_HG19232("choice:%d\n",choice);
switch (choice){
case CMD://指令
//DBG_HG19232("cmd\n");
get_user(disp,buf);//从buf处取一个字节到disp
disp_cmd(disp);//操作指令
break;
case DATA://数据
//DBG_HG19232("data\n");
get_user(disp,buf);//从buf处取一个字节到disp
disp_data(disp);//操作数据
break;
default:
//DBG_HG19232("default\n");
}
return 0;
}
static void __init hg19232_init (void)
{
int i;
if (jhd_initialized == 1)
return 0;
hg19232_hardware_init(); //液晶初始化
i = register_chrdev(HG19232_MAJOR, "hg19232", &hg19232_fops);
if(i<0){//失败
printk(KERN_CRIT"hg19232:i = %d\n",i);
return -EIO;
}
printk(KERN_CRIT"hg19232:hg19232_drv registered:)=\n");
jhd_initialized = 1;
return 0;
}
static void __exit hg19232_cleanup (void)
{
unregister_chrdev(HG19232_MAJOR, "hg19232");
return;
}
module_init(hg19232_init);
module_exit(hg19232_cleanup); 不好意思,隔了这么长时间才回复。
页:
[1]