1 Star 0 Fork 1

jerry/linux_i2c

forked from hu_submodule/linux_i2c 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
i2c.c 11.49 KB
一键复制 编辑 原始数据 按行查看 历史
jerry 提交于 2021-07-14 10:58 . update i2c.c.
/**
* @file : i2c.c
* @brief : Linux平台I2C驱动代码源文件
* @author :
* @date : 2021-04-04 11:36:03
*
* @copyright : Copyright (c) 2021 胡恩荣
*
*/
#include "./i2c.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
// I2C设备名最大长度
#define I2C_DEV_NAME_MAX_LEN 30
// I2C设备最大数量
#define I2C_DEV_MAX_NUM 10
// 记录I2C设备信息
struct i2c_dev_info
{
char i2c_dev_name[I2C_DEV_NAME_MAX_LEN]; // I2C设备名
int i2c_dev_fd; // I2C设备文件描述符
pthread_mutex_t i2c_dev_mutex; // I2C设备互斥锁
};
// 记录I2C设备信息索引
static uint8_t g_i2c_dev_info_index = 0;
// 记录I2C设备信息
static struct i2c_dev_info g_i2c_dev_info[I2C_DEV_MAX_NUM];
/**
* @brief 查找指定I2C设备的信息
* @param info : 输出参数, 查找到的I2C设备信息
* @param i2c_dev_name: 输入参数, 待查找的I2C设备名
* @return 成功: 0
* 失败: -1
*/
static int find_i2c_dev_info(struct i2c_dev_info *info,
const char *i2c_dev_name)
{
int ret = -1;
for (uint8_t i = 0; i < g_i2c_dev_info_index; i++)
{
ret = memcmp(g_i2c_dev_info[i].i2c_dev_name,
i2c_dev_name, strlen(i2c_dev_name));
if (0 == ret)
{
memcpy(info, &g_i2c_dev_info[i], sizeof(struct i2c_dev_info));
return 0;
}
}
return -1;
}
/**
* @brief 打开I2C设备
* @param i2c_dev_name: 输入参数, I2C设备名(如: /dev/i2c-0)
* @return 成功: 0
* 失败: -1
*/
int i2c_open(const char *i2c_dev_name)
{
int ret = -1;
// I2C设备描述符
int fd = -1;
// I2C设备信息
struct i2c_dev_info info;
// 超过支持的I2C设备数量, 直接返回错误
if (g_i2c_dev_info_index > I2C_DEV_MAX_NUM)
{
return -1;
}
// I2C设备已打开, 直接返回成功
ret = find_i2c_dev_info(&info, i2c_dev_name);
if (0 == ret)
{
return 0;
}
// 打开I2C设备
fd = open(i2c_dev_name, O_RDWR);
if (fd < 0)
{
return -1;
}
// 记录I2C设备信息
memcpy(g_i2c_dev_info[g_i2c_dev_info_index].i2c_dev_name,
i2c_dev_name, strlen(i2c_dev_name));
g_i2c_dev_info[g_i2c_dev_info_index].i2c_dev_fd = fd;
// 初始化互斥锁
pthread_mutex_init(&g_i2c_dev_info[g_i2c_dev_info_index].i2c_dev_mutex, NULL);
g_i2c_dev_info_index++;
return 0;
}
/**
* @brief 关闭I2C设备
* @param i2c_dev_name: 输入参数, I2C设备名(如: /dev/i2c-0)
* @return 成功: 0
* 失败: -1
*/
int i2c_close(const char *i2c_dev_name)
{
int ret = -1;
for (uint8_t i = 0; i < g_i2c_dev_info_index; i++)
{
ret = memcmp(g_i2c_dev_info[i].i2c_dev_name,
i2c_dev_name, strlen(i2c_dev_name));
// 当前I2C设备已打开
if (0 == ret)
{
// 关闭I2C设备
ret = close(g_i2c_dev_info[i].i2c_dev_fd);
if (ret < 0)
{
return -1;
}
// 清空I2C设备信息
g_i2c_dev_info[i].i2c_dev_fd = -1;
memset(g_i2c_dev_info[i].i2c_dev_name, 0, I2C_DEV_NAME_MAX_LEN);
// 销毁互斥锁
pthread_mutex_destroy(&g_i2c_dev_info[i].i2c_dev_mutex);
// 将I2C设备信息放到数组最前面
memcpy(&g_i2c_dev_info[i], &g_i2c_dev_info[i + 1],
(sizeof(struct i2c_dev_info) * (I2C_DEV_MAX_NUM - i - 1)));
(g_i2c_dev_info_index > 0) ? g_i2c_dev_info_index-- : 0;
return 0;
}
}
return 0;
}
/**
* @brief 向无寄存器地址的I2C从设备发送数据/命令
* @param i2c_dev_name : 输入参数, I2C设备名(如: /dev/i2c-0)
* @param slave_addr : 输入参数, I2C从设备地址
* @param send_data : 输入参数, 待发送数据/命令
* @param send_data_len: 输入参数, 待发送数据/命令长度
* @return 成功: 0
* 失败: -1
*/
int i2c_write_data(const char *i2c_dev_name, const uint16_t slave_addr,
const uint8_t *send_data, const uint32_t send_data_len)
{
int ret = -1;
// I2C设备信息
struct i2c_dev_info info;
// I2C设备未打开, 直接返回失败
ret = find_i2c_dev_info(&info, i2c_dev_name);
if (0 != ret)
{
return -1;
}
// 加锁
pthread_mutex_lock(&info.i2c_dev_mutex);
// 设置从器件地址
// 不带寄存器地址的从设备操作前需要先设置从器件地址
ret = ioctl(info.i2c_dev_fd, I2C_SLAVE_FORCE, slave_addr);
if (0 != ret)
{
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
return -1;
}
// 向I2C从设备发送数据/命令
ret = write(info.i2c_dev_fd, send_data, send_data_len);
if (send_data_len != ret)
{
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
return -1;
}
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
return 0;
}
/**
* @brief 从无寄存器地址的I2C从设备读取数据
* @param recv_data : 输出参数, 读取到的数据
* @param i2c_dev_name : 输入参数, I2C设备名(如: /dev/i2c-0)
* @param slave_addr : 输入参数, I2C从设备地址
* @param recv_data_len: 输入参数, 待读取数据长度
* @return 成功: 0
* 失败: -1
*/
int i2c_read_data(uint8_t *recv_data, const char *i2c_dev_name,
const uint16_t slave_addr, const uint32_t recv_data_len)
{
int ret = -1;
// I2C设备信息
struct i2c_dev_info info;
// I2C设备未打开, 直接返回失败
ret = find_i2c_dev_info(&info, i2c_dev_name);
if (0 != ret)
{
return -1;
}
// 加锁
pthread_mutex_lock(&info.i2c_dev_mutex);
// 设置从器件地址
// 不带寄存器地址的从设备操作前需要先设置从器件地址
ret = ioctl(info.i2c_dev_fd, I2C_SLAVE_FORCE, slave_addr);
if (0 != ret)
{
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
return -1;
}
// 从I2C从设备读取数据
ret = read(info.i2c_dev_fd, recv_data, recv_data_len);
if (recv_data_len != ret)
{
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
return -1;
}
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
return 0;
}
/**
* @brief 向有寄存器的I2C从设备发送数据/命令(即写I2C从设备寄存器)
* @param i2c_dev_name : 输入参数, I2C设备名(如: /dev/i2c-0)
* @param slave_addr : 输入参数, I2C从设备地址
* @param reg_addr : 输入参数, I2C从设备寄存器地址
* @param write_data : 输入参数, 待发送数据/命令
* @param write_data_len: 输入参数, 待发送数据/命令长度
* @return 成功: 0
* 失败: -1
*/
int i2c_write_data_sub(const char *i2c_dev_name,
const uint16_t slave_addr, const uint8_t reg_addr,
const uint8_t *write_data, const uint32_t write_data_len)
{
int ret = -1;
struct i2c_rdwr_ioctl_data ioctl_data;
// I2C设备信息
struct i2c_dev_info info;
// I2C设备未打开, 直接返回失败
ret = find_i2c_dev_info(&info, i2c_dev_name);
if (0 != ret)
{
return -1;
}
// 加锁
pthread_mutex_lock(&info.i2c_dev_mutex);
// 消息数
memset(&ioctl_data, 0, sizeof(struct i2c_rdwr_ioctl_data));
ioctl_data.nmsgs = 1;
ioctl_data.msgs = (struct i2c_msg *)malloc(ioctl_data.nmsgs * sizeof(struct i2c_msg));
if (NULL == ioctl_data.msgs)
{
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
return -1;
}
ioctl_data.msgs[0].buf = (uint8_t *)malloc((write_data_len + 1) * sizeof(uint8_t));
if (NULL == ioctl_data.msgs[0].buf)
{
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
free(ioctl_data.msgs);
return -1;
}
// 从器件地址
ioctl_data.msgs[0].addr = slave_addr;
// 数据长度(buf的长度)
ioctl_data.msgs[0].len = (write_data_len + 1);
// 操作方式(0: write; 1: read)
ioctl_data.msgs[0].flags = 0;
// 寄存器地址
ioctl_data.msgs[0].buf[0] = reg_addr;
// 发送数据
memcpy(&(ioctl_data.msgs[0].buf[1]), write_data, write_data_len);
ret = ioctl(info.i2c_dev_fd, I2C_RDWR, (unsigned long)&ioctl_data);
if (-1 == ret)
{
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
free(ioctl_data.msgs[0].buf);
free(ioctl_data.msgs);
return -1;
}
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
return 0;
}
/**
* @brief 从有寄存器地址的I2C从设备读取数据(即读I2C从设备寄存器)
* @param recv_data : 输出参数, 读取到的数据
* @param i2c_dev_name : 输入参数, I2C设备名(如: /dev/i2c-0)
* @param slave_addr : 输入参数, I2C从设备地址
* @param reg_addr : 输入参数, I2C从设备寄存器地址
* @param recv_data_len: 输入参数, 指定读取长度
* @return 成功: 0
* 失败: -1
*/
int i2c_read_data_sub(uint8_t *recv_data,
const char *i2c_dev_name, const uint16_t slave_addr,
const uint8_t reg_addr, const uint32_t recv_data_len)
{
int ret = -1;
struct i2c_rdwr_ioctl_data ioctl_data = {0};
// I2C设备信息
struct i2c_dev_info info;
// I2C设备未打开, 直接返回失败
ret = find_i2c_dev_info(&info, i2c_dev_name);
if (0 != ret)
{
return -1;
}
// 加锁
pthread_mutex_lock(&info.i2c_dev_mutex);
// 消息数
ioctl_data.nmsgs = 2;
ioctl_data.msgs = (struct i2c_msg *)malloc(ioctl_data.nmsgs * sizeof(struct i2c_msg));
if (NULL == ioctl_data.msgs)
{
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
return -1;
}
ioctl_data.msgs[0].buf = (uint8_t *)malloc(sizeof(uint8_t));
if (NULL == ioctl_data.msgs[0].buf)
{
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
free(ioctl_data.msgs);
return -1;
}
ioctl_data.msgs[1].buf = (uint8_t *)malloc(recv_data_len * sizeof(uint8_t));
if (NULL == ioctl_data.msgs[1].buf)
{
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
free(ioctl_data.msgs[0].buf);
free(ioctl_data.msgs);
return -1;
}
// 从器件地址
ioctl_data.msgs[0].addr = slave_addr;
// 数据长度
ioctl_data.msgs[0].len = 1;
// 操作方式(0: write; 1: read)
ioctl_data.msgs[0].flags = 0;
// 寄存器地址
ioctl_data.msgs[0].buf[0] = reg_addr;
// 从器件地址
ioctl_data.msgs[1].addr = slave_addr;
// 数据长度
ioctl_data.msgs[1].len = recv_data_len;
// 操作方式(0: write; 1: read)
ioctl_data.msgs[1].flags = 1;
// 初始化
memset(ioctl_data.msgs[1].buf, 0, recv_data_len);
ret = ioctl(info.i2c_dev_fd, I2C_RDWR, (unsigned long)&ioctl_data);
if (-1 == ret)
{
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
free(ioctl_data.msgs[1].buf);
free(ioctl_data.msgs[0].buf);
free(ioctl_data.msgs);
return -1;
}
memcpy(recv_data, ioctl_data.msgs[1].buf, recv_data_len);
// 解锁
pthread_mutex_unlock(&info.i2c_dev_mutex);
return 0;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jerry_qt_admin/linux_i2c.git
[email protected]:jerry_qt_admin/linux_i2c.git
jerry_qt_admin
linux_i2c
linux_i2c
master

搜索帮助