• 荔枝派 V3S Linux 应用层 IIC 使用OLED


    1.开始

      我想在荔枝派上驱动oled屏,但是在内核中写驱动对我来说肯定是非常麻烦的,所以我退而求其次,想在应用层中操作通用i2c接口来实现oled的驱动程序。

    我买的OLED是中景园经典款,四针IIC接口oled。首先我参考了NanoPi的Matrix库,参考他的IIC应用层函数。我发现他多include了一个i2c-dev.h 并且这个函数的内容是比我/usr/inlucde/linux/i2c-dev.h中的内容多的,他多了以下几个函数

    static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command, 
                                         int size, union i2c_smbus_data *data)
    
    
    static inline __s32 i2c_smbus_write_quick(int file, __u8 value)
    
        
    static inline __s32 i2c_smbus_read_byte(int file)
    
    
    static inline __s32 i2c_smbus_write_byte(int file, __u8 value)
    
    
    static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command)
    
    
    static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command,
                                                  __u8 value)
    
    
    static inline __s32 i2c_smbus_read_word_data(int file, __u8 command)
    
    
    static inline __s32 i2c_smbus_write_word_data(int file, __u8 command, 
                                                  __u16 value)
    
    
    static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value)
    
    
    
    /* Returns the number of read bytes */
    static inline __s32 i2c_smbus_read_block_data(int file, __u8 command, 
                                                  __u8 *values)
    
    
    static inline __s32 i2c_smbus_write_block_data(int file, __u8 command, 
                                                   __u8 length, __u8 *values)
    
    
    /* Returns the number of read bytes */
    static inline __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command,
                                                      __u8 *values)
    
    
    static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command,
                                                   __u8 length, __u8 *values)
    
    
    /* Returns the number of read bytes */
    static inline __s32 i2c_smbus_block_process_call(int file, __u8 command,
                                                     __u8 length, __u8 *values)

      我在网上查询了这些函数,这个是一种smbus协议,是对应用层i2c的进一步封装。我可以使用这个快速的对i2c数据进行读写。

    之后我就参考了别人的OLED代码,开始了移植。

    2.问题出现

      我发现我设置好了从机地址之后,进行读写一直出现No Such Device Or Addres 的错误。经过一天的寻找,我终于发现了错误所在。

    在网上的那个oled程序,都是将0x78作为从机地址。并且数据手册中也是这样写的,那么我理所当然将0x78作为从机地址。但是接下来我们看数据手册以及代码片段

    ssd1306:

       数据手册片段:

    ssd1306的读写函数片段:

    /*********************OLED写数据************************************/ 
    void OLED_WrDat(unsigned char IIC_Data)
    {
        IIC_Start();
       IIC_Send_Byte(0x78);            //D/C#=0; R/W#=0
        IIC_Wait_Ack();    
       IIC_Send_Byte(0x40);            //write data
        IIC_Wait_Ack();    
       IIC_Send_Byte(IIC_Data);
        IIC_Wait_Ack();
        IIC_Stop();
    }

    mpu6050:

    数据手册

    代码片段:

    //IIC读一个字节 
    //reg:寄存器地址 
    //返回值:读到的数据
    u8 MPU_Read_Byte(u8 reg)
    {
        u8 res;
        IIC_Start(); 
        IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令    
        IIC_Wait_Ack();        //等待应答 
        IIC_Send_Byte(reg);    //写寄存器地址
        IIC_Wait_Ack();        //等待应答
        IIC_Start();
        IIC_Send_Byte((MPU_ADDR<<1)|1);//发送器件地址+读命令    
        IIC_Wait_Ack();        //等待应答 
        res=IIC_Read_Byte(0);//读取数据,发送nACK 
        IIC_Stop();            //产生一个停止条件 
        return res;        
    }

     大家发现错误没有? 那就是对两个器件写地址的时候,oled的地址没有左移!那么问题就出现在这里,linux中设置好了从机地址后,他的发送时会自动根据读写来对地址进行左移后或上0、1的操作。

    所以我这个0x78就是他的已经左移一位了的地址,那么我给linux中设置的从机地址应该是0x78右移一位得出的0x3C!现在我就可以正常读写了。

    3.代码

      下面附上我修改的i2c代码驱动地址

  • 相关阅读:
    linux的find命令详解
    在接口中的静态方法来获取model的实例对象
    php函数decbin
    cookie的默认有效目录
    html的base标签
    mysql多位小数字段用decimal类型
    vmware在桥接模式下配置centos7网络
    iis_rewrite3突然无法使用(因为它过期啦)
    LightGBM 调参方法(具体操作)
    沪深股票的复权计算(复权因子的应用)--代码实现
  • 原文地址:https://www.cnblogs.com/ZQQH/p/8807204.html
Copyright © 2020-2023  润新知