首先加载驱动模块,应用程序通过调用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 ;
}

[DM8168]Linux下控制GPIO控制12864液晶屏(ST7565控制器)的更多相关文章

  1. linux下操作gpio寄存器的方法

    一. 在驱动中: 1. 用的时候映射端口:ioremap; #define GPIO_OFT(x) ((x) - 0x56000000) #define GPFCON (*(volatile unsi ...

  2. Linux 下操作GPIO(两种方法,驱动和mmap)(转载)

    目前我所知道的在Linux下操作GPIO有两种方法: 1.编写驱动,这当然要熟悉Linux下驱动的编写方法和技巧,在驱动里可以使用ioremap函数获得GPIO物理基地址指针,然后使用这个指针根据io ...

  3. Linux 下操作gpio(两种方法,驱动和mmap)

    目前我所知道的在linux下操作GPIO有两种方法: 1.  编写驱动,这当然要熟悉linux下驱动的编写方法和技巧,在驱动里可以使用ioremap函数获得GPIO物理基地址指针,然后使用这个指针根据 ...

  4. linux设备驱动程序--gpio控制

    gpio驱动程序 上一章节linux设备驱动程序--创建设备节点章节主要介绍了linux字符设备驱动程序的框架,从这一章节开始我们讲解各种外设的控制,包括gpio,i2c,dma等等,既然是外设,那就 ...

  5. linux下的权限控制

    终于还是要弄服务器了,这是多年前用fedora的时候整理的,也贴出来,顺便也再复习一下. 先来了解一下文件属性,在shell环境里输入:ls -l 可以查看当前目录文件.如:drwxr-xr-x. 1 ...

  6. [转载]嵌入式linux下操作GPIO

    本文转自:http://blog.csdn.net/mirkerson/article/details/8464231 在嵌入式设备中对GPIO的操作是最基本的操作.一般的做法是写一个单独驱动程序,网 ...

  7. Linux下LCD 10分钟自动关屏的问题总结

    Linux下的LCD驱动默认10分钟后会自动关闭屏幕,我们可以修改一下代码让其不自动关屏 在有一个 drivers/char/vt.c 文件其中有一个变量(blankinterval)可以设置它来修改 ...

  8. linux下常用的截图、录屏工具

    录屏: 在linux下常用的录屏工具有5种,可以baidu或者google下喔,我选用的是recordMydesktop,使用非常方便,用时注意先把每秒桢数调高,否则效果必然很差. 在ubuntu下可 ...

  9. [DM8168]Linux下控制GPIO实现LED流水灯

    首先加载驱动模块,应用程序通过调用API实现GPIO控制功能. 驱动程序: /* * fileName: led_gpio.c * just for LED GPIO test * GP1_14 -& ...

随机推荐

  1. C++,C++编程,Windows编程,MFC

    编程 我们日常生活中接触到的电子类产品中的应用都是由编程而来 为什么编程,偷懒 我们通过编程驱使(指挥,命令)的是电信号 为什么上面说编程是偷懒,电的发现,给人们带来了便利,人们在各个方面驱使(换成“ ...

  2. C++中调用Python脚本(转载)

    转载▼ 标签: 杂谈 C++中调用Python脚本的意义就不讲了,至少你可以把它当成文本形式的动态链接库,需要的时候还可以改一改,只要不改变接口, C++的程序一旦编译好了,再改就没那么方便了先看Py ...

  3. HDU2433 最短路 + 剪枝优化

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2433 ,最短路(SPFA或优化过的Dijstra) + 剪枝优化 这道题关键还是在几个剪枝上面,没有剪 ...

  4. Sonar服务器搭建

    Sonar服务器搭建 Sonar概述 Sonar 是一个用于代码质量管理的开放平台.通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具.与持续集成工具(例如 Hudson ...

  5. this.value = this.placeholder || this.getAttribute('placeholder')

    this.value = this.placeholder || this.getAttribute('placeholder') 鉴于不同的浏览器对为止属性的实现方式有所不用,这里同时使用了HTML ...

  6. IPC Gateway 设计

    1. IPC Gateway对外提供的功能: IPC的register/request/reply/notification服务. 2. IPC Gatew的实现原理: 各个具体的服务注册自己的回调函 ...

  7. 三种序列化方式存取redis的方法

    常见的的序列化反序列方式的效率: protoBuf(PB) > fastjson > jackson > hessian > xstream > java 数据来自于:h ...

  8. JavaScript常用八种继承方案

    更新:在常用七种继承方案的基础之上增加了ES6的类继承,所以现在变成八种啦,欢迎加高级前端进阶群一起学习(文末). --- 2018.10.30 1.原型链继承 构造函数.原型和实例之间的关系:每个构 ...

  9. PHP实现的敏感词过滤方法

    PHP实现的敏感词过滤方法,以下是一份过滤敏感词的编码.有需要可以参考参考. /** * @todo 敏感词过滤,返回结果 * @param array $list 定义敏感词一维数组 * @para ...

  10. 删除Zend Studio项目

    导入了过大的项目,导致很卡,且Close Project和Delete操作不了,一直无响应. 调整项目目录下的隐藏文件夹,删除对应项目: E:\www\.metadata\.plugins\org.e ...