版主帮我看看这个lcd的程序噢
这是我在linux下编写的一个lcd(16*2)驱动程序,参考了lumit网站上的lcd程序,其中的初始化程序,已经可以清屏.但是向lcd中写数据时,发现仍然显示清屏,并不显示我所要写的数据,看了好几天了,没进展,呵呵,版主帮忙看看吧,谢谢! :P ,在这个程序里面,我在初始化函数里面包含了lcd的初始化及向其里面写数据,没有单独编写向lcd写数据的函数,可以只看这个init_chardev函数,其他的程序可以不看./*#if defined(CONFIG_MODVERSIONS) && ! defined(MODVERSIONS)
*#include <linux/modversions.h>
*#define MODVERSIONS
*#endif
*/
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
char kernel_version[]=UTS_RELEASE;
#else
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#endif
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h> /* for put_user */
#define IOPMOD (*(volatile unsigned *)0x3ff5000)
#define IOPDATA (*(volatile unsigned *)0x3ff5008)
#define LCD_MAX_LINES 2
#define LCD_MIN_LINES 1
#define LCD_MAX_COLUMNS 16
#define LCD_MIN_COLUMNS 1
#define ERROR 0xff
#define OK 0
#define UINT8 unsigned short
/* Prototypes - this would normally go in a .h file
*/
void init_chardev(void);
void cleanup_module(void);
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
#define SUCCESS 0
#define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices */
#define BUF_LEN 80 /* Max length of the message from the device */
/* Global variables are declared as static, so are global within the file. */
static int Major; /* Major number assigned to our device driver */
static int Device_Open = 0; /* Is device open? Used to prevent multiple */
/*access to the device */
static char msg; /* The msg the device will give when asked */
static char *msg_Ptr;
static struct file_operations fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
/* Functions
*/
void init_chardev(void)
{
int data,led,i;
char *ch= "--- C U M T ---";
char val;
Major =register_chrdev(254, DEVICE_NAME, &fops);
if (Major < 0) {
printk ("Registering the character device failed with %d\n", Major);
/*return Major;*/
}
printk("I was assigned major number 254. To talk to\n");
printk("<1>the driver, create a dev file with\n");
printk("'mknod /dev/hello c 254 0'.\n");
printk("<1>Try various minor numbers. Try to cat to\n");
printk("the device file.\n");
printk("<1>Remove the device file and module when done.\n");
/* *(volatile unsigned *)0x3FF303c &= 0xffff0000; */
*(volatile unsigned *)0x3FF303c |= 0x3fd;
led=0x8;
IOPMOD=0xffffffff;
IOPDATA=~led;
*(volatile unsigned *)0x3FF3008 |= 0xf58;
led=0x8;
IOPMOD=0xffffffff;
IOPDATA=~led;
*(volatile unsigned *)0x3FF3010 |= 0x100000;
*(volatile UINT8 *)0x3FD0000= 0x38;
for(i=0;i<3000;i++)
;
*(volatile UINT8 *)0x3FD0000= 0xf;
for(i=0;i<3000;i++)
;
*(volatile UINT8 *)0x3FD0000= 0x1;
for(i=0;i<3000;i++)
;
*(volatile UINT8 *)0x3FD0000= 0x6;
for(i=0;i<3000;i++)
;
/*val = 0xff << 7 ; */
/**(volatile UINT8 *) 0x3FD0000 = val; */
for(i=0;i<1000;i++)
;
/**(volatile UINT8 *)0x3FD0002 = 'a';
*/
while(*ch != '\0')
{
for(i=0;i<1000;i++)
;
*(volatile UINT8 *)0x3FD0002 = *ch;
ch++;
}
/*return 0;*/
}
void cleanup_module(void)
{
/* Unregister the device */
int ret = unregister_chrdev(Major, DEVICE_NAME);
if (ret < 0) printk("Error in unregister_chrdev: %d\n", ret);
}
/* Methods
*/
/* Called when a process tries to open the device file, like
* "cat /dev/chardev"
*/
static int device_open(struct inode *inode, struct file *file)
{
static int counter = 0;
if (Device_Open) return -EBUSY;
Device_Open++;
sprintf(msg,"I already told you %d times Hello world!\n", counter++);
msg_Ptr = msg;
MOD_INC_USE_COUNT;
return SUCCESS;
}
/* Called when a process closes the device file.
*/
static int device_release(struct inode *inode, struct file *file)
{
Device_Open--; /* We're now ready for our next caller */
/* Decrement the usage count, or else once you opened the file, you'll
*never get get rid of the module. */
MOD_DEC_USE_COUNT;
return 0;
}
/* Called when a process, which already opened the dev file, attempts to
*read from it.
*/
static ssize_t device_read(struct file *filp,
char *buffer, /* The buffer to fill with data */
size_t length, /* The length of the buffer */
loff_t *offset) /* Our offset in the file */
{
/* Number of bytes actually written to the buffer */
int bytes_read = 0;
/* If we're at the end of the message, return 0 signifying end of file */
if (*msg_Ptr == 0) return 0;
/* Actually put the data into the buffer */
while (length && *msg_Ptr) {
/* The buffer is in the user data segment, not the kernel segment;
* assignment won't work. We have to use put_user which copies data from
* the kernel data segment to the user data segment. */
put_user(*(msg_Ptr++), buffer++);
length--;
bytes_read++;
}
/* Most read functions return the number of bytes put into the buffer */
return bytes_read;
}
/* Called when a process writes to dev file: cat /mnt/test > /dev/chardev */
static ssize_t device_write(struct file *filp,
const char *buff,
size_t len,
loff_t *off)
{
printk ("<1>No such file or directory.\n");
return -EINVAL;
}
:P:P 不同液晶型号,驱动有些相似,但未必可以通用。
lumit4510 上最早用的是 FM1602C 的 16×2 的字符液晶,但调试了很久也没有正确显示,后来换成 GMC1602C 同样的 16×2 的字符液晶,程序一个字没改就可以用了。 噢,不好意思,我是说斑竹帮我看看向lcd写数据这个地方有没有问题呢?这种写法对吗? 哪儿是你所说的 “向lcd写数据这个地方” ?:? while(*ch != '\0')
{
for(i=0;i<1000;i++)
;
*(volatile UINT8 *)0x3FD0002 = *ch;
ch++;
}
这个地方 这种写法没问题,可以参考看Learn lumit Step 19 里面关于写 lcd 的格式。
int lcd_write( unsigned char * buf, int count )
{
int i = 0;
for( i = 0; i<count; i++ )
{
*(unsigned char *)LDATAWR = *(buf+i);
lcd_ioctl( LCD_WAIT, 3 );
}
return count;
}
页:
[1]