[DM8168]Linux下控制GPIO控制12864液晶屏(ST7565控制器)

时间:2023-03-09 08:11:20
[DM8168]Linux下控制GPIO控制12864液晶屏(ST7565控制器)

首先加载驱动模块,应用程序通过调用API实现GPIO控制功能。

驱动函数:

 /*
* fileName: st7565_driver.c
* just for LCD12864 driver
* GP1_14(46) -> D6(SCK)
* GP1_15(47) -> D7(SDA)
* GP1_27(59) -> RST
* GP1_28(60) -> RS
*/ #include <linux/device.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/list.h>
#include <linux/cdev.h>
#include <linux/proc_fs.h>
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <linux/io.h>
#include <mach/gpio.h>
#include <linux/device.h>
#include <linux/platform_device.h> #include <linux/delay.h> // ASCII code
#include "font.h" #define DRIVERNAME "lcd12864" // PANEL CON
#define CTRL_MODULE_BASE_ADDR 0x48140000
#define conf_gpio46 (CTRL_MODULE_BASE_ADDR + 0x0B04)
#define conf_gpio47 (CTRL_MODULE_BASE_ADDR + 0x0B08)
#define conf_gpio59 (CTRL_MODULE_BASE_ADDR + 0x0AB8)
#define conf_gpio60 (CTRL_MODULE_BASE_ADDR + 0x0ABC) #define WR_MEM_32(addr, data) *(unsigned int*)OMAP2_L4_IO_ADDRESS(addr) = (unsigned int)(data)
#define RD_MEM_32(addr) *(unsigned int*)OMAP2_L4_IO_ADDRESS(addr) // LCD spec
#define _delay_ms(n) mdelay(n)
#define ST7565_X_SIZE 128
#define ST7565_Y_SIZE 64
#define u8 unsigned char
#define u16 unsigned int #define LCD_SCK_H gpio_set_value(46, 1);
#define LCD_SCK_L gpio_set_value(46, 0);
#define LCD_SDA_H gpio_set_value(47, 1);
#define LCD_SDA_L gpio_set_value(47, 0);
#define LCD_CS_H
#define LCD_CS_L
#define LCD_RST_H gpio_set_value(59, 1);
#define LCD_RST_L gpio_set_value(59, 0);
#define LCD_RS_H gpio_set_value(60, 1);
#define LCD_RS_L gpio_set_value(60, 0); static dev_t lcd_dev;
static struct cdev lcd_cdev;
static struct class *lcd_class = NULL;
static int gpio[]; static int lcd12864_open(struct inode *inode, struct file *file);
static int lcd12864_close(struct inode *inode, struct file *file);
static ssize_t lcd12864_write(struct file *file, const char *buf, size_t count, loff_t *offset); // ST7565 gpio config
static void store_gpio_pin(void)
{
// store gpio pinmux
gpio[] = RD_MEM_32(conf_gpio46);
gpio[] = RD_MEM_32(conf_gpio47);
gpio[] = RD_MEM_32(conf_gpio59);
gpio[] = RD_MEM_32(conf_gpio60);
} static void recover_gpio_pin(void)
{
// recover gpio pinmux
WR_MEM_32(conf_gpio46, gpio[]);
WR_MEM_32(conf_gpio47, gpio[]);
WR_MEM_32(conf_gpio59, gpio[]);
WR_MEM_32(conf_gpio60, gpio[]);
gpio_free(gpio[]);
gpio_free(gpio[]);
gpio_free(gpio[]);
gpio_free(gpio[]);
} static void config_gpio_pin(void)
{
// config gpio direction
WR_MEM_32(conf_gpio46, );
gpio_request(, "gpio46_en"); // request gpio46
gpio_direction_output(, ); WR_MEM_32(conf_gpio47, );
gpio_request(, "gpio47_en"); // request gpio47
gpio_direction_output(, ); WR_MEM_32(conf_gpio59, );
gpio_request(, "gpio59_en"); // request gpio59
gpio_direction_output(, ); WR_MEM_32(conf_gpio60, );
gpio_request(, "gpio60_en"); // request gpio60
gpio_direction_output(, );
} // ST7565 basic driver
void ST7565_WrByte(u8 chr, u8 dir)
{
u8 i=;
if(dir == ){ LCD_RS_L;}
else { LCD_RS_H;}
for(i = ; i < ; i++){
LCD_SCK_L;
if(chr & 0x80){ LCD_SDA_H;}
else { LCD_SDA_L;}
chr = (chr << );
LCD_SCK_H;
}
} void ST7565_PgSet(u8 clm, u8 pag)
{
u8 lsb = ;
u8 msb = ;
lsb = clm & 0x0F; //
msb = clm & 0xF0; //
msb = msb >> ; //
msb = msb | 0x10; //
pag = pag | 0xB0; //
ST7565_WrByte(pag, ); //
ST7565_WrByte(msb, ); //
ST7565_WrByte(lsb, ); // 0 - 127
} void ST7565_Clear(void)
{
u8 i = ;
u8 j = ;
// LCD_CS_L;
for(i=; i < ST7565_Y_SIZE/; i++){
ST7565_PgSet(, i);
for(j=; j < ST7565_X_SIZE; j++){
ST7565_WrByte(0x00, );
}
}
// LCD_CS_H;
} void ST7565_Init(void)
{
// LCD_CS_L;
LCD_RST_L;
_delay_ms();
LCD_RST_H; ST7565_WrByte(0xE2, ); // software rst
_delay_ms();
ST7565_WrByte(0x2C, ); // burst stage1
_delay_ms();
ST7565_WrByte(0x2E, ); // burst stage2
_delay_ms();
ST7565_WrByte(0x2F, ); // burst stage3
_delay_ms();
ST7565_WrByte(0x25, ); //
ST7565_WrByte(0x81, ); //
ST7565_WrByte(0x16, ); //
ST7565_WrByte(0xA2, ); //
ST7565_WrByte(0xC8, ); //
ST7565_WrByte(0xA0, ); //
ST7565_WrByte(0x40, ); //
ST7565_WrByte(0xAF, ); // open display // LCD_CS_H;
ST7565_Clear();
} void ST7565_DispChr(u8 xpos, u8 ypos, char chr)
{
u8 i=;
ST7565_PgSet(xpos, ypos);
for(i=; i<; i++){
// six bytes
ST7565_WrByte(ascii_0806[][(chr-' ')* + i], );
}
} // lcd file operations
static int lcd12864_open(struct inode *inode, struct file *file)
{
store_gpio_pin();
config_gpio_pin(); ST7565_Init();
return ;
} static int lcd12864_close(struct inode *inode, struct file *file)
{
recover_gpio_pin();
return ;
} static ssize_t lcd12864_write(struct file *file, const char *buf, size_t count, loff_t *offset)
{
unsigned char cnt=;
unsigned char raw; // y
unsigned char col; // x char *data = NULL; if(count == )
ST7565_Clear();
else{
data = (char *)kzalloc(count, GFP_KERNEL); // kmalloc to kzalloc
memcpy(data, buf, count);
raw = *data;
col = *(data+);
while(cnt < (count-)){
// offset
ST7565_DispChr(col+*cnt, raw, *(data+cnt+));
cnt++; // char++
}
kfree(data);
data = NULL;
} return count;
} static struct file_operations lcd12864_fops =
{
.owner = THIS_MODULE,
.open = lcd12864_open,
.release = lcd12864_close,
.write = lcd12864_write,
}; static int __init LCD12864_init(void)
{
int result; result = alloc_chrdev_region(&lcd_dev, , , DRIVERNAME);
if(result < ){
printk("Error registering led_gpio character device\n");
return -ENODEV;
}
printk("st7565_driver major#: %d, minor#: %d\n", MAJOR(lcd_dev), MINOR(lcd_dev)); cdev_init(&lcd_cdev, &lcd12864_fops);
lcd_cdev.owner = THIS_MODULE;
lcd_cdev.ops = &lcd12864_fops; result = cdev_add(&lcd_cdev, lcd_dev, );
if(result){
unregister_chrdev_region(lcd_dev, );
printk("Error adding led_gpio.. error no:%d\n", result);
return -EINVAL;
}
lcd_class = class_create(THIS_MODULE, DRIVERNAME);
device_create(lcd_class, NULL, lcd_dev, NULL, DRIVERNAME); printk(DRIVERNAME " initialized!\n"); return ;
} static void __exit LCD12864_exit(void)
{
printk(KERN_EMERG "lcd12864 driver exit!\n");
cdev_del(&lcd_cdev);
unregister_chrdev_region(lcd_dev, );
device_destroy(lcd_class, lcd_dev);
class_destroy(lcd_class);
} module_init(LCD12864_init);
module_exit(LCD12864_exit);
MODULE_LICENSE("GPL");

API函数:

 #ifndef API_LCD12864_H
#define API_LCD12864_H
#include <stdio.h> #ifdef __cplusplus
extern "C" {
#endif #define u8 unsigned char
#define u16 unsigned int int api_lcd12864_open(void);
int api_lcd12864_close(int fd_lcd);
int api_lcd12864_dispstr(int fd_lcd, u8 row, u8 col, char *str); #ifdef __cplusplus
}
#endif #endif
 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "api_lcd12864.h" // #define u8 unsigned char
// #define u16 unsigned int #define DEVICENAME "/dev/lcd12864" int api_lcd12864_open(void)
{
int fd_lcd;
if((fd_lcd = open(DEVICENAME, O_RDWR)) <= -){
printf("open device error\n");
return -;
}
return fd_lcd;
} int api_lcd12864_close(int fd_lcd)
{
if( == close(fd_lcd))
return ;
else
return -;
} int api_lcd12864_dispstr(int fd_lcd, u8 row, u8 col, char *str)
{
unsigned int cnt;
char ret;
char *data = NULL; cnt = +(strlen(str));
data = (char *)malloc(cnt); *data = row;
*(data+) = col; memcpy(data+, str, cnt-); if(write(fd_lcd, data, cnt) < ){
printf("write error\n");
ret = -;
}
else{
ret = ;
} free(data);
data = NULL; return ret;
} /*--
void ST7565_DispStr(u8 xpos, u8 ypos, u8 *str)
{
u8 i=0; // the num of bytes
LCD_CS_L;
while(*(str+i) != '\0'){
// offset
ST7565_DispChr(xpos+6*i, ypos, *(str+i));
i++; // char++
}
LCD_CS_H;
}
--*/
/*--
void ST7565_DispNum(u8 xpos,u8 ypos, u32 num, u8 len)
{
LCD_CS_L;
while(len > 0){
// ascii
ST7565_DispChr(xpos+6*(--len), ypos, num%10 + '0');
num = num / 10;
}
LCD_CS_H;
}
--*/

应用程序:

 /*- test for Lcd12864 -*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "api_lcd12864.h"
int main(void)
{
int fd_lcd;
// unsigned int num=0;
char date_str[];
char num_str1[];
char num_str2[];
time_t rawtime;
struct tm *timeinfo; // int delay = 10; fd_lcd = api_lcd12864_open();
// my_tt = time(&NULL); if(fd_lcd < ){
printf("fd_lcd open failed!\n");
return -;
} api_lcd12864_dispstr(fd_lcd, , , "hello, linux"); printf("Hello, LCD displaying!\n"); // api_lcd12864_close(fd_lcd); while(){
// sprintf(num_str, "%d", num);
time(&rawtime);
timeinfo = localtime(&rawtime);
strcpy(date_str, asctime(timeinfo)); // printf("Time is: %s\n", date_str); memcpy(num_str1, date_str+, );
num_str1[] = '\0';
api_lcd12864_dispstr(fd_lcd, , , num_str1); // Web Feb 13 memcpy(num_str2, date_str+, );
num_str2[] = '\0';
api_lcd12864_dispstr(fd_lcd, , , num_str2); // 09:49:30 2014 // if(num == 65535) num=0;
// num ++;
usleep();
} api_lcd12864_close(fd_lcd); return ;
}