(RK3566驱动开发 - 2).IIC驱动

目录

一.OLED

1.设备树

(1).流程图

(2).设备树代码

2.驱动代码部分

(1).流程图

(2).驱动代码

二.BMP280气压计

1.设备树

(1).流程图

(2).设备树代码

2.驱动代码部分

(1).流程图

(2).驱动代码

(3).应用代码

3.Makefile

三.MPU6050

1.设备树

(1).流程图

(2).设备树代码

2.驱动代码部分

(1).流程图

(2).驱动代码

(3).应用程序代码

3.Makefile

4.实验现象


一.OLED

1.设备树

(1).流程图

(2).设备树代码

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 驱动结构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值