【FFH】BearPi_Micro南向开发I2C驱动代码 原创

X丶昕雪
发布于 2022-6-5 08:56
浏览
1收藏

Micro的I2C介绍

串行时钟线SCL管脚为GPIOF14,串行数据线SDA管脚为GPIOF15.
I2C使用步骤为

  1. 打开I2C
  2. 得知从设备地址
  3. 构建使用的数据
  4. 向设备地址发送此数据
    【FFH】BearPi_Micro南向开发I2C驱动代码-鸿蒙开发者社区【FFH】BearPi_Micro南向开发I2C驱动代码-鸿蒙开发者社区

操作函数

开启、关闭I2C

#include "i2c_if.h"
static DevHandle myi2cHand = NULL;
myi2cHand = I2cOpen(1); //正确

//关闭
I2cClose(myi2cHand);
myi2cHand = NULL;

定义I2C数据结构体

typedef struct
{
    uint16_t addr;	//I2C设备地址
    uint8_t *buf;	//数据地址
    uint16_t len;	//数据长度
    uint16_t flags;	//I2C模式

} My_IIC_Msg;

I2C的16位flags的每一位定义:

位操作 使用定义 模式
0 Write flag
(0x1 << 0) I2C_FLAG_READ Read flag
(0x1 << 4) I2C_FLAG_ADDR_10BIT 10-bit addressing flag
(0x1 << 11) I2C_FLAG_READ_NO_ACK No-ACK read flag
(0x1 << 12) I2C_FLAG_IGNORE_NO_ACK Ignoring no-ACK flag
(0x1 << 14) I2C_FLAG_NO_START No START condition flag
(0x1 << 15) I2C_FLAG_STOP STOP condition flag

例如:当需要读取数据的时候,将flags的第一位设置为1,此时I2C的模式便为读取模式。

写入函数


int MyIICWrite(uint32_t addr, uint8_t *data, uint32_t len)
{
    My_IIC_Msg msg[1];
    (void)memset_s(msg, sizeof(msg), 0, sizeof(msg));
    msg[0].addr = addr;
    msg[0].buf = data;
    msg[0].len = len;
    msg[0].flags = 0;	//写入模式
//验证I2C是否开启
    if (myi2cHand == NULL)
    {
        HDF_LOGE("I2C didn't open!");
        return 11;
    }
//I2C操作函数,并验证是否成功
    if (I2cTransfer(myi2cHand, (struct I2cMsg *)msg, 1) != 1)	
    {
        HDF_LOGE("i2c write failed");
        return 12;
    }
    return 1;
}

读取函数

int MyIICRead(uint32_t addr, uint8_t *data, uint32_t len)
{
    My_IIC_Msg msg;
    msg.addr = addr;
    msg.buf = data;
    msg.len = len;
    msg.flags = 1;	//读取模式
//验证I2C是否开启
    if (myi2cHand == NULL)
    {
        HDF_LOGE("I2C didn't open!");
        return 11;
    }
//I2C操作函数,并验证是否成功
    if (I2cTransfer(myi2cHand, (struct I2cMsg *)&msg, 1) != 1)	//注意参数二是要取地址
    {
        HDF_LOGE("i2c write failed");
        return 12;
    }
    return 1;
}

同时读写

int MyIICWriteRead(uint32_t addr,uint8_t* wdata,uint32_t wlen,uint8_t* rdata,uint32_t rlen)
{
    My_IIC_Msg msg[2];
    (void)memset_s(msg, sizeof(msg), 0, sizeof(msg));
    msg[0].addr = addr;
    msg[0].buf = wdata;
    msg[0].len = wlen;
    msg[0].flags = 0;
    msg[1].addr = addr;
    msg[1].buf = rdata;
    msg[1].len = rlen;
    msg[1].flags = 1;
//I2C操作函数,并验证是否成功
    if (I2cTransfer(myi2cHand, (struct I2cMsg *)msg, 2) != 2) {
        HDF_LOGE("i2c write read err");
        return 12;
    }
    return 1;
}

以E53_IA1为样例

IO口配置 (省略)

先i2c管脚的IO口配置并初始化复位管脚,此步骤需要查询寄存器手册

#include "osal_io.h"         /* 标准IO读写接口头文件 */
#define I2C_SDA_ADDR 0x00000000 /* I2C控制器SDA管脚配置寄存器地址 */
#define I2C_CLK_ADDR 0x00000000  /* I2C控制器SCL管脚配置寄存器地址 */
#define I2C_REG 0x000             /* I2C控制器SDA及SCL管脚配置值 */
OSAL_WRITEL(I2C_REG, IO_DEVICE_ADDR(I2C_SDA_ADDR));
OSAL_WRITEL(I2C_REG, IO_DEVICE_ADDR(I2C_CLK_ADDR));

打开I2C

以下代码都为在驱动代码中添加
#include "i2c_if.h"

static DevHandle myi2cHand = NULL;
myi2cHand = I2cOpen(1); 
//为了确认是否打开I2C成功,可以有以下判断
//I2cOpen之前,判断myicHand是否为NULL,if(myi2cHand!=NULL){报错代码}
//I2cOpen之后,判断myi2cHand是否写入数据,if(myi2cHand==NULL){报错代码}

定义I2C数据结构体

定义调用I2C所用的数据结构

typedef struct
{
    uint16_t addr;	//I2C设备地址
    uint8_t *buf;	//数据地址
    uint16_t len;	//数据长度
    uint16_t flags;	//I2C模式
} My_IIC_Msg;

使用I2C读取数据

int MyIICRead(uint32_t addr, uint8_t *data, uint32_t len)
{
//构建I2C使用的数据类型
    My_IIC_Msg msg;
    msg.addr = addr;
    msg.buf = data;
    msg.len = len;
    msg.flags = 1;	//读取模式

/*可添加验证I2C是否开启,if (myi2cHand == NULL){报错} */


/*I2cTransfer函数为I2C操作函数,参数一为DevHandle类型的I2C地址,参数二为数据地址,参数三为操作次数*/
 	I2cTransfer(myi2cHand, (struct I2cMsg *)&msg, 1);

/*可添加验证I2C传输是否成功,判断I2cTransfer函数的返回值是否为参数三*/
   return 1;
} 

//使用IA1上的BH1750
uint8_t recv_data[2] = {0};
MyIICRead((0x23 << 1), recv_data, 2);

注意在使用BH1750之前需要初始化BH1750,依次向BH1750发送0x01和0x20

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-6-5 08:56:57修改
5
收藏 1
回复
举报
回复
    相关推荐