回复
【FFH】BearPi_Micro南向开发I2C驱动代码 原创
X丶昕雪
发布于 2022-6-5 08:56
浏览
1收藏
Micro的I2C介绍
串行时钟线SCL管脚为GPIOF14,串行数据线SDA管脚为GPIOF15.
I2C使用步骤为
- 打开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
回复
相关推荐