[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 -& ...
随机推荐
- go语言,爬取百度贴吧指定贴所有内容
初级爬虫,为了学习一下常用的goquery. goquery 配置 go get https://github.com/PuerkitoBio/goquery 会提示不支持https方式 解决方案: ...
- 【洛谷2577】[ZJOI2005] 午餐(较水DP)
点此看题面 大致题意: 有\(N\)个学生去食堂打饭,每个学生有两个属性:打饭时间\(a_i\)和吃饭时间\(b_i\).现要求将这些学生分成两队分别打饭,求最早何时所有人吃完饭. 贪心 首先,依据贪 ...
- 深入理解计算机系统_3e 第九章家庭作业 CS:APP3e chapter 9 homework
9.11 A. 00001001 111100 B. +----------------------------+ | Parameter Value | +--------------------- ...
- jq中append(),appendTo(),after(),before(),prepend(),prependTo()的用法
1. append():往当前元素的内部的后面追加元素; eg:$("div").append($("span")); 将span放在div内部的后面. 2. ...
- Jmeter模拟http请求
一.获取用户信息(GET请求):http://hostname/getuser?userid=1 1.打开jmeter,创建一个线程组,再添加一个http请求Sampler 2.设置域名.路径.请求方 ...
- js 数组方法大集合,各方法是否改变原有的数组详解
不会改变原来数组的有: concat()---连接两个或更多的数组,并返回结果. every()---检测数组元素的每个元素是否都符合条件. some()---检测数组元素中是否有元素符合指定条件. ...
- Oracle表连接学习笔记
目录 一.表连接类型 1.1 内连接 1.2 外连接 二.表连接方法 2.1 表连接方法分类 2.2 表连接方法特性区别 @ 一.表连接类型 表连接类型可以分为:内连接.外连接,在看<收获,不止 ...
- 洛谷P1111修复公路并查集改
看了他们的题解感觉很震惊,为什么要用kruskal,这题要用到最小生成树吗??? 38行短短的程序就可以了,我觉得学习不是一种套用,套自己学的,而且题解很大一部分都是kruskal. 个人认为自己的程 ...
- js获取整型数组最大值、最小值、平均值
---恢复内容开始--- let values = [];//数组(整型数字) //获取数组最大值function arrMaxNum(arr){ var maxNum = null; for (va ...
- FreeRTOS的学习路线
背景 由于之前接触过一些嵌入式RTOS,如Keil-RTX,uCOS-II,也曾经关注过FreeRTOS,但一直没有机会采用FreeRTOS开发.目前FreeRTOS做为主流RTOS,风声正盛.作为嵌 ...