(RK3566驱动开发 - 2).IIC驱动
一.设备树
(1).流程图
(2).设备树代码
二.驱动代码部分
(1).流程图
(2).驱动代码
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/i2c.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include "oledfont.h"
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/version.h>
#define OLED_CNT 1
#define OLED_NAME "oled"
#define OLED_CMD 0X00 //OLED 写命令
#define OLED_DATA 0X40 //OLED 写数据
#define Max_Column 128 //OLED 的 x方向的像素个数
//IIC从用户控件接收的数据格式
struct display_stru
{
int x; //x坐标
int y; //y坐标
char *buf; //接收数据缓冲区
};
/* 设备结构体 */
struct oled_dev
{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
struct device_node *nd; /* 设备结点 */
int major; /* 主设备号 */
void *private_data; /* 私有数据 */
};
/* OLED 设备 */
struct oled_dev oleddev;
/**
* @description: 向 OLED 写入若干个字节的数据
* @param - dev : OLED 设备
* @param - reg : 寄存器首地址
* @param - buf : 要写入的数据缓冲区
* @param - len : 要写入的字节数
* @return : 成功则返回(发送的 msg 数量),失败则返回(负值)
*/
static s32 oled_write_regs(struct oled_dev *dev,u8 reg,u8 *buf,int len)
{
u8 b[256] = {};
struct i2c_msg msg;
struct i2c_client *client = (struct i2c_client *)dev->private_data;
b[0] = reg; //填充寄存器的首地址
memcpy(&b[1],buf,len); //填充要写入的数据
msg.addr = client->addr; //OLED 设备
msg.buf = b;
msg.flags = 0; //表示为写数据
msg.len = len + 1; //数据长度 = 1个字节的寄存器首地址 + 要写入的数据长度
return i2c_transfer(client->adapter,&msg,1);
}
/**
* @description: 向 OLED 写入单个字节的数据
* @param - dev : OLED 设备
* @param - reg : 寄存器首地址
* @param - data : 要写入的单个字节的数据
* @return : 成功则返回(发送的 msg 数量),失败则返回(负值)
*/
static s32 oled_write_reg(struct oled_dev *dev,u8 reg,u8 data)
{
u8 buf = data;
return oled_write_regs(dev,reg,&buf,1);
}
/**
* @description: oled 初始化
* @param : 无
* @return : 无
*/
void oled_init(void)
{
int ret;
u8 i = 0;
u8 data[] ={ 0xAE, 0x00, 0x10, 0x40, 0xB0, 0x81, 0xFF, 0xA1, 0xA6,
0xA8, 0x3F, 0xC8, 0xD3, 0x00, 0xD5, 0x80, 0xD8, 0x05,
0xD9, 0xF1, 0xDA, 0x12, 0xDB, 0x30, 0x8D, 0x14, 0xAF };
for(i = 0 ; i < sizeof(data) ; i++)
{
ret = oled_write_reg(&oleddev,OLED_CMD,data[i]);
}
}
/**
* @description: oled 清屏
* @param : 无
* @return : 无
*/
void oled_clear(void)
{
u8 i,n;
for(i = 0 ; i < 8 ; i++)
{
oled_write_reg(&oleddev,OLED_CMD,0XB0+i); //设置页地址
oled_write_reg(&oleddev,OLED_CMD,0x00); //设置显示位置-列低地址
oled_write_reg(&oleddev,OLED_CMD,0x10); //设置显示位置-列高地址
}
for(n = 0 ; n < 128 ; n++)
{
oled_write_reg(&oleddev,OLED_DATA,0x00);
}
}
/**
* @description: 设置 OLED 某个点
* @param - x : x坐标
* @param - y : y坐标
* @return : 无
*/
void oled_set_pos(u8 x, u8 y)
{
oled_write_reg(&oleddev,OLED_CMD, 0xb0 + y);
oled_write_reg(&oleddev,OLED_CMD, ((x & 0xf0) >> 4) | 0x10);
oled_write_reg(&oleddev,OLED_CMD, x & 0x0f);
}
/**
* @description: oled 显示单个字符
* @param - x : x坐标
* @param - y : y坐标
* @param - chr : 要显示的字符
* @return : 无
*/
void oled_showchar(u8 x, u8 y, u8 chr)
{
u8 c=0, i=0;
c = chr - ' ';
if(x > Max_Column-1)
{
x = 0;
y = y + 2;
}
oled_set_pos(x, y);
for(i=0; i<8; i++)
{
oled_write_reg(&oleddev,OLED_DATA, F8X16[c*16+i]);
}
oled_set_pos(x,y+1);
for(i=0; i<8; i++)
{
oled_write_reg(&oleddev,OLED_DATA, F8X16[c*16+i+8]);
}
}
/**
* @description: oled显示字符串
* @param - x : x坐标
* @param - y : y坐标
* @param - chr : 字符串首地址
* @return : 无
*/
void oled_showstring(u8 x, u8 y, u8 *chr)
{
unsigned char j=0;
while(chr[j] != '\0')
{
oled_showchar(x, y, chr[j]);
x += 8;
if(x > 120)
{
x = 0;
y += 2;
}
j++;
}
}
/**
* @description: open 函数
*/
static int oled_open(struct inode *inode,struct file *filp)
{
filp->private_data = &oleddev;
/* 初始化 OLED */
oled_init();
oled_clear();
return 0;
}
/**
* @description: write 函数
*/
static ssize_t oled_write(struct file *filp,const char __user *buf,size_t cnt,loff_t *offt)
{
/* 可根据用户空间传进来的 buf , 自行编写对应的逻辑实现 */
oled_showstring(0,0,"hello");
return 0;
}
/**
* @description: release 函数
*/
static int oled_release(struct inode *inode,struct file *filp)
{
return 0;
}
/* 绑定设备操作函数 */
static const struct file_operations fops =
{
.open = oled_open,
.write = oled_write,
.release = oled_release,
};
/**
* @description: probe 函数
*/
static int oled_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
dev_err(oleddev.device,"enter oled_probe\r\n");
/* 1.创建设备号 */
if(oleddev.major)
{
oleddev.devid = MKDEV(oleddev.major,0);
register_chrdev_region(oleddev.devid,OLED_CNT,OLED_NAME);
}
else
{
alloc_chrdev_region(&oleddev.devid,0,OLED_CNT,OLED_NAME);
oleddev.major = MAJOR(oleddev.devid);
}
/* 2.注册cdev */
cdev_init(&oleddev.cdev,&fops);
cdev_add(&oleddev.cdev,oleddev.devid,OLED_CNT);
/* 3.创建类 */
oleddev.class = class_create(THIS_MODULE,OLED_NAME);
if(IS_ERR(oleddev.class))
{
return PTR_ERR(oleddev.class);
}
/* 4.创建设备 */
oleddev.device = device_create(oleddev.class,NULL,oleddev.devid,NULL,OLED_NAME);
if(IS_ERR(oleddev.device))
{
return PTR_ERR(oleddev.device);
}
oleddev.private_data = client;
return 0;
}
/**
* @description: remove 函数
*/
static int oled_remove(struct i2c_client *client)
{
dev_err(oleddev.device,"enter oled_remove\r\n");
/* 1.注销字符设备驱动 */
cdev_del(&oleddev.cdev);
unregister_chrdev_region(oleddev.devid,OLED_CNT);
/* 2.注销类和设备 */
device_destroy(oleddev.class,oleddev.devid);
class_destroy(oleddev.class);
return 0;
}
/* 无设备树时的匹配方式 - ID列表 */
static const struct i2c_device_id oled_id[] =
{
{"oled_test",0},
{},
};
/* 设备树下的匹配方式 - 匹配列表 */
static const struct of_device_id oled_of_match[] =
{
{.compatible = "oled_test"},
{},
};
/* i2c 驱动结构体 */
static struct i2c_driver oled_driver =
{
.probe = oled_probe,
.remove = oled_remove,
.driver =
{
.owner = THIS_MODULE,
.name = "oled",
.of_match_table = oled_of_match,
},
.id_table = oled_id,
};
/**
* @description: 驱动入口函数
*/
static int __init oled_module_init(void)
{
return i2c_add_driver(&oled_driver);
}
/**
* @description: 驱动出口函数
*/
static void __exit oled_module_exit(void)
{
i2c_del_driver(&oled_driver);
}
module_init(oled_module_init);
module_exit(oled_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("kaneki");
原文地址:https://blog.csdn.net/kaneki_lh/article/details/143832683
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!