资讯详情

HI3861学习笔记(15)——I2C接口使用

一、简介

1.1 I2C

飞利浦是一种总线 Philip 公司开发的串行总线。它是由一条数据线串行的两条总线(SDA)和一根 时钟线(SDL)组成。两条线都需要上拉电阻。I2C 多个可以在总线上连接 I2C 每个设备都有一个唯一的地址识别。同时只有一个主设备,另一个是从设备。通常 MCU 外设作为主设备控制的设备。

1.2 GPIO复用功能

HI3861V100 芯片有 15 个 GPIO,引脚分布如下: 其中 I2C 设备有 2 个,其中 GPIO 可复用成 I2C 设备如下:

Pin 管脚名称 复用信号
2 GPIO_00 I2C1_SDA
3 GPIO_01 I2C1_SCL
5 GPIO_03 I2C1_SDA
6 GPIO_04 I2C1_SCL
27 GPIO_09 I2C0_SCL
28 GPIO_10 I2C0_SDA
31 GPIO_13 I2C0_SDA
32 GPIO_14 I2C0_SCL

二、API说明

以下 GPIO 接口位于

2.1 GpioInit

功能 初始化GPIO外设
函数定义 unsigned int GpioInit(void)
参数
返回 错误码

以下扩展 GPIO 接口位于

2.2 IoSetFunc

功能 设置GPIO引脚功能
函数定义 unsigned int IoSetFunc(WifiIotIoName id, unsigned char val)
参数 id:表示GPIO引脚号val:表示IO复用功能
返回 错误码

以下 I2C 接口位于

业务BUILD.gn中包含路径

include_dirs = [         "//utils/native/lite/include",         "//kernel/liteos_m/components/cmsis/2.0",         "//base/iot_hardware/interfaces/kits/wifiiot_lite",     ] 

2.3 I2cInit

功能 初始化指定频率I2C设备
函数定义 unsigned int I2cInit(WifiIotI2cIdx id, unsigned int baudrate)
参数 id:I2C设备IDbaudrate:I2C频率
返回 错误码

2.4 I2cWrite

功能 将数据写入I2C设备
函数定义 unsigned int I2cWrite(WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData *i2cData)
参数 id:I2C设备IDdeviceAddr:I2C设备地址i2cData:表示写入的数据
返回 错误码

2.5 I2cRead

功能 从I2C设备读取数据。读取的数据将保存到i2cData指定的地址
函数定义 unsigned int I2cRead(WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData *i2cData)
参数 id:I2C设备IDdeviceAddr:I2C设备地址i2cData:指的是要读取的数据
返回 错误码

以下扩展 I2C 接口位于

2.6 I2cSetBaurate

功能 为I2C设备设置频率
函数定义 unsigned int I2cSetBaudrate(WifiIotI2cIdx id, unsigned int baudrate)
参数 id:I2C设备IDbaudrate:I2C频率
返回 错误码

三、作为主机与BH1750光照强度传感器通信

编译时在业务BUILD.gn中包含路径

include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/interfaces/kits/wifiiot_lite",
    ]

BH1750芯片使用的是I2C协议,I2C_SCL与GPIO_0相连接,I2C_SDA与GPIO_1相连接,所以需要编写软件使用GPIO_0和GPIO_1产生I2C信号去控制BH1750芯片

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifiiot_errno.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_i2c.h"
#include "wifiiot_i2c_ex.h"

#define I2C_TASK_STACK_SIZE 1024 * 8
#define I2C_TASK_PRIO 25

#define WRITE_BIT 0x00
#define READ_BIT 0x01

#define BH1750_SLAVE_ADDR 0x23 // 从机地址
#define BH1750_PWR_DOWN 0x00 // 关闭模块
#define BH1750_PWR_ON 0x01 // 打开模块等待测量指令
#define BH1750_RST 0x07 // 重置数据寄存器值在PowerOn模式下有效
#define BH1750_CON_H 0x10 // 连续高分辨率模式,1lx,120ms
#define BH1750_CON_H2 0x11 // 连续高分辨率模式,0.5lx,120ms
#define BH1750_CON_L 0x13 // 连续低分辨率模式,4lx,16ms
#define BH1750_ONE_H 0x20 // 一次高分辨率模式,1lx,120ms,测量后模块转到PowerDown模式
#define BH1750_ONE_H2 0x21 // 一次高分辨率模式,0.5lx,120ms,测量后模块转到PowerDown模式
#define BH1750_ONE_L 0x23 // 一次低分辨率模式,4lx,16ms,测量后模块转到PowerDown模式

/** @brief I2C写数据函数 @param slaveAddr -[in] 从设备地址 @param regAddr -[in] 寄存器地址 @param pData -[in] 写入数据 @param dataLen -[in] 写入数据长度 @return 错误码 */
int I2C_WriteData(uint8_t slaveAddr, uint8_t regAddr, uint8_t *pData, uint16_t dataLen)
{ 
        
    int ret;
    WifiIotI2cData i2c_data = { 
        0};

    if(0 != regAddr)
    { 
        
        i2c_data.sendBuf = &regAddr;
        i2c_data.sendLen = 1;
        ret = I2cWrite(WIFI_IOT_I2C_IDX_1, (slaveAddr << 1) | WRITE_BIT, &i2c_data);
        if(ret != 0)
        { 
        
            printf("===== Error: I2C write status1 = 0x%x! =====\r\n", ret);
            return 0;
        }
    }

    i2c_data.sendBuf = pData;
    i2c_data.sendLen = dataLen;
    ret = I2cWrite(WIFI_IOT_I2C_IDX_1, (slaveAddr << 1) | WRITE_BIT, &i2c_data);
    if(ret != 0)
    { 
        
        printf("===== Error: I2C write status1 = 0x%x! =====\r\n", ret);
        return 0;
    }

    return 1;
}

/** @brief I2C读数据函数 @param slaveAddr -[in] 从设备地址 @param regAddr -[in] 寄存器地址 @param pData -[in] 读出数据 @param dataLen -[in] 读出数据长度 @return 错误码 */
int I2C_ReadData(uint8_t slaveAddr, uint8_t regAddr, uint8_t *pData, uint16_t dataLen)
{ 
        
    int ret;
    WifiIotI2cData i2c_data = { 
        0};

    if(0 != regAddr)
    { 
        
        i2c_data.sendBuf = &regAddr;
        i2c_data.sendLen = 1;
        ret = I2cWrite(WIFI_IOT_I2C_IDX_1, (slaveAddr << 1) | WRITE_BIT, &i2c_data);
        if(ret != 0)
        { 
        
            printf("===== Error: I2C write status = 0x%x! =====\r\n", ret);
            return 0;
        }
    }

    i2c_data.receiveBuf = pData;
    i2c_data.receiveLen = dataLen;
    ret = I2cRead(WIFI_IOT_I2C_IDX_1, (slaveAddr << 1) | READ_BIT, &i2c_data);
    if(ret != 0)
    { 
        
        printf("===== Error: I2C read status = 0x%x! =====\r\n", ret);
        return 0;
    }

    return 1;
}

static void I2CTask(void)
{ 
        
    int ret;
    uint8_t sensor_data[2] = { 
        0};
    uint8_t sensor_data_h, sensor_data_l;
    int cnt = 0;
    uint8_t data;

    GpioInit();

    //GPIO_0复用为I2C1_SDA
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA);

    //GPIO_1复用为I2C1_SCL
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL);

    //baudrate: 400kbps
    I2cInit(WIFI_IOT_I2C_IDX_1, 400000);

    I2cSetBaudrate(WIFI_IOT_I2C_IDX_1, 400000);

    printf("I2C Test Start\n");

    while (1)
    { 
        
        printf("test cnt: %d", cnt++);
        data = BH1750_PWR_ON;              // 发送启动命令
        I2C_WriteData(BH1750_SLAVE_ADDR, 0, &data, 1);
        data = BH1750_ONE_L;               // 设置一次低分辨率模式,测量后模块转到PowerDown模式
        I2C_WriteData(BH1750_SLAVE_ADDR, 0, &data, 1);
        usleep(30000);                     // 设置完成后要有一段延迟
        ret = I2C_ReadData(BH1750_SLAVE_ADDR, 0, sensor_data, 2);
        sensor_data_h = sensor_data[0];
        sensor_data_l = sensor_data[1];
        if(ret == 0) 
        { 
        
            printf("I2C Error");
        } 
        else if(ret == 1)
        { 
        
            printf("*******************\n");
            printf("MASTER READ SENSOR( BH1750 )\n");
            printf("*******************\n");
            printf("data_h: %02x\n", sensor_data_h);
            printf("data_l: %02x\n", sensor_data_l);
            printf("sensor val: %.02f [Lux]\n", (sensor_data_h << 8 | sensor_data_l) / 1.2);
        }

        usleep(1000000);
    }
}

static void I2CExampleEntry(void)
{ 
        
    osThreadAttr_t attr;

    attr.name = "I2CTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = I2C_TASK_STACK_SIZE;
    attr.priority = I2C_TASK_PRIO;

    if (osThreadNew((osThreadFunc_t)I2CTask, NULL, &attr) == NULL)
    { 
        
        printf("Falied to create I2CTask!\n");
    }
}

APP_FEATURE_INIT(I2CExampleEntry);

查看打印:


• 由 Leung 写于 2021 年 10 月 10 日

• 参考:【鸿蒙2.0设备开发教程】小熊派HarmonyOS 鸿蒙·季 开发教程     BearPi-HM_Nano开发板传感器驱动开发——E53_SC1读取光照强度

标签: 集成电路hi1cxd9698r集成电路

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台