[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 ;
}
[DM8168]Linux下控制GPIO控制12864液晶屏(ST7565控制器)的更多相关文章
- linux下操作gpio寄存器的方法
一. 在驱动中: 1. 用的时候映射端口:ioremap; #define GPIO_OFT(x) ((x) - 0x56000000) #define GPFCON (*(volatile unsi ...
- Linux 下操作GPIO(两种方法,驱动和mmap)(转载)
目前我所知道的在Linux下操作GPIO有两种方法: 1.编写驱动,这当然要熟悉Linux下驱动的编写方法和技巧,在驱动里可以使用ioremap函数获得GPIO物理基地址指针,然后使用这个指针根据io ...
- Linux 下操作gpio(两种方法,驱动和mmap)
目前我所知道的在linux下操作GPIO有两种方法: 1. 编写驱动,这当然要熟悉linux下驱动的编写方法和技巧,在驱动里可以使用ioremap函数获得GPIO物理基地址指针,然后使用这个指针根据 ...
- linux设备驱动程序--gpio控制
gpio驱动程序 上一章节linux设备驱动程序--创建设备节点章节主要介绍了linux字符设备驱动程序的框架,从这一章节开始我们讲解各种外设的控制,包括gpio,i2c,dma等等,既然是外设,那就 ...
- linux下的权限控制
终于还是要弄服务器了,这是多年前用fedora的时候整理的,也贴出来,顺便也再复习一下. 先来了解一下文件属性,在shell环境里输入:ls -l 可以查看当前目录文件.如:drwxr-xr-x. 1 ...
- [转载]嵌入式linux下操作GPIO
本文转自:http://blog.csdn.net/mirkerson/article/details/8464231 在嵌入式设备中对GPIO的操作是最基本的操作.一般的做法是写一个单独驱动程序,网 ...
- Linux下LCD 10分钟自动关屏的问题总结
Linux下的LCD驱动默认10分钟后会自动关闭屏幕,我们可以修改一下代码让其不自动关屏 在有一个 drivers/char/vt.c 文件其中有一个变量(blankinterval)可以设置它来修改 ...
- linux下常用的截图、录屏工具
录屏: 在linux下常用的录屏工具有5种,可以baidu或者google下喔,我选用的是recordMydesktop,使用非常方便,用时注意先把每秒桢数调高,否则效果必然很差. 在ubuntu下可 ...
- [DM8168]Linux下控制GPIO实现LED流水灯
首先加载驱动模块,应用程序通过调用API实现GPIO控制功能. 驱动程序: /* * fileName: led_gpio.c * just for LED GPIO test * GP1_14 -& ...
随机推荐
- oracle 的启动与连接
1. Oracle的启动 oracle的服务如下图所示: 启动oracle有两个重要的服务(如上图标识处): l OracleOraDb11g_home1TNSListener:监听服务,主要用于客户 ...
- hdu-1556 Color the ball---树状数组+区间修改单点查询
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1556 题目大意: Problem Description N个气球排成一排,从左到右依次编号为1,2 ...
- 利用kvo实现列表倒计时
自己稍微记录一下,方便以后用到: 先创建一个定时器的类: #import "TimeCenter.h" @interface TimeCenter () @property (no ...
- 2018.6.20 Java考试试题总结(Java语言基础与面向对象编程)最新版
Java考试试题总结 一.单选题(每题1分 * 50 = 50分) 1.java程序的执行过程中用到一套JDK工具,其中javac.exe指( B ) A.java语言解释器 B.java字节码编译器 ...
- dojo中类的继承
类似于c# java等后台语言,在基于类的面向对象编程中,通常需要在子类中扩展某些父类的方法,这时可以在子类的方法中,先调用从父类继承的方法,然后再执行子类自定义的操作.凡是使用declare创建的类 ...
- 小弟在研究CUDA时出现一个问题,求解
这是<GPU高性能编程CUDA中文实战>中的例子,第七章,热传导模拟,但是出现下面的问题,求牛人解读.小弟跪谢... 主要问题就是关键字变白. 但是添加需要的头文件后一些系统自带的关键字也 ...
- SpringBoot学习4:springboot整合listener
整合方式一:通过注解扫描完成 Listener 组件的注册 1.编写listener package com.bjsxt.listener; import javax.servlet.ServletC ...
- Java基础面试题:String 和StringBuffer的区别
package com.swift; import java.util.Date; public class Getclass_Test extends Date { public static vo ...
- 正则表达式通用匹配ip地址及主机检测
在使用正则表达式匹配ip地址时如果不限定ip正确格式,一些场景下可能会产生不一样的结果,比如ip数值超范围,ip段超范围等,在使用正则表达式匹配ip地址时要注意几点: 1,字符界定:使用 \< ...
- jsp--提交表单→插入数据库→成功后返回提示信息
<%@ page language="java" import="java.util.*,java.sql.*" pageEncoding="u ...