一、简介
1.1 I2C
I2C(Inter-Integrated Circuit ,内部集成电路) 总线是一种由飞利浦 Philip 公司开发的串行总线。是两条串行的总线,它由一根数据线(SDA)和一根 时钟线(SCL)组成。两条线都需要上拉电阻。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 接口位于 base\iot_hardware\interfaces\kits\wifiiot_lite\wifiiot_gpio.h。
2.1 GpioInit
功能 | 初始化GPIO外设 |
---|---|
函数定义 | unsigned int GpioInit(void) |
参数 | 无 |
返回 | 错误码 |
以下扩展 GPIO 接口位于 base\iot_hardware\interfaces\kits\wifiiot_lite\wifiiot_gpio_ex.h。
2.2 IoSetFunc
功能 | 设置GPIO引脚功能 |
---|---|
函数定义 | unsigned int IoSetFunc(WifiIotIoName id, unsigned char val) |
参数 | id:表示GPIO引脚号 val:表示IO复用功能 |
返回 | 错误码 |
以下 I2C 接口位于 base\iot_hardware\interfaces\kits\wifiiot_lite\wifiiot_i2c.h。
业务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设备ID baudrate:I2C频率 |
返回 | 错误码 |
2.4 I2cWrite
功能 | 将数据写入I2C设备 |
---|---|
函数定义 | unsigned int I2cWrite(WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData *i2cData) |
参数 | id:I2C设备ID deviceAddr:I2C设备地址 i2cData:表示写入的数据 |
返回 | 错误码 |
2.5 I2cRead
功能 | 从I2C设备读取数据。读取的数据将保存到i2cData指定的地址 |
---|---|
函数定义 | unsigned int I2cRead(WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData *i2cData) |
参数 | id:I2C设备ID deviceAddr:I2C设备地址 i2cData:表示要读取的数据指向的指针 |
返回 | 错误码 |
以下扩展 I2C 接口位于 base\iot_hardware\interfaces\kits\wifiiot_lite\wifiiot_i2c_ex.h。
2.6 I2cSetBaudrate
功能 | 为I2C设备设置频率 |
---|---|
函数定义 | unsigned int I2cSetBaudrate(WifiIotI2cIdx id, unsigned int baudrate) |
参数 | id:I2C设备ID baudrate: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
#include
#include
#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 = ®Addr;
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 = ®Addr;
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读取光照强度