我们可以根据设备节点来操作响应的i2c,以便应用层实现对i2c读写操作。内核态和用户态操作都可以在外设驱动指南pdf中有相应的说明。本示例可以当作一个工具使用。当然对于i2c工具很多,比如海思tools封装好的i2c_read和i2c_write,另外还有开源工具i2c-tools(busybox编译出来有这个工具)。
/**
* Copyright (C), 2016,
* All rights reserved.
*
* @file maincpp
* @brief
* @author 初创
* @date 2019.12.14
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct i2c_msg {
__u16 addr; // slave address
__u16 flags;
#define I2C_M_TEN 0x0010 //10bit地址
#define I2C_M_RD 0x0001 //读取数据标志,清零表示写
#define I2C_M_NOSTART x4000 //不发送起始位
#define I2C_M_REV_DIR_ADDR 0x2000 // 反转读写标志
#define I2C_M_IGNORE_NAK x1000 //忽略I2C器件的ack和nack信号
#define I2C_M_NO_RD_ACK 0x0800 //读操作时
#define I2C_M_RECV_LEN 0x0400 //length will be first received byte
__u16 len; // msg length
__u8 *buf; // pointer to msg data
};
/*****************************************************************************
Prototype : atoul
Description : 10进制字符串转换为无符号数字。
Input args : IN char *str 10进制字符串
不接受符号
Output args : U32* pulValue, 转换后的数字
Return value : int HI_SUCCESS 转换成功
HI_FAILURE 转换失败
Calls : isdigit
Called By :
History :
1.Date : 2005年7月10日
Author : t41030
Modification : Created function
*****************************************************************************/
int atoul( char *str, unsigned long * pulValue)
{
unsigned long ulResult=0;
while (*str)
{
if (isdigit((int)*str))
{
/*最大支持到0xFFFFFFFF(4294967295),
X * 10 + (*str)-48 <= 4294967295
所以, X = 429496729 */
if ((ulResult<429496729) || ((ulResult==429496729) && (*str<'6')))
{
ulResult = ulResult*10 + (*str)-48;
}
else
{
*pulValue = ulResult;
return -1;
}
}
else
{
*pulValue=ulResult;
return -1;
}
str++;
}
*pulValue=ulResult;
return 0;
}
/*****************************************************************************
Prototype : atoulx
Description : 16进制字符串转换为无符号数字。输入的16进制字符串不包括前缀0x
Input args : IN char *str 16进制字符串, 不包括前缀0x. 如ABCDE
Output args : U32* pulValue, 转换后的数字
Return value : int HI_SUCCESS 转换成功
HI_FAILURE 转换失败
Calls : toupper
isdigit
Called By :
History :
1.Date : 2005年7月10日
Author : t41030
Modification : Created function
*****************************************************************************/
#define ASC2NUM(ch) (ch - '0')
#define HEXASC2NUM(ch) (ch - 'A' + 10)
int atoulx(char *str, unsigned long * pulValue)
{
unsigned long ulResult=0;
unsigned char ch;
while (*str)
{
ch=toupper(*str);
if (isdigit(ch) || ((ch >= 'A') && (ch <= 'F' )))
{
if (ulResult < 0x200000000)
{
ulResult = (ulResult << 4) + ((ch<='9')?(ASC2NUM(ch)):(HEXASC2NUM(ch)));
}
else
{
*pulValue=ulResult;
return -1;
}
}
else
{
*pulValue=ulResult;
return -1;
}
str++;
}
*pulValue=ulResult;
return 0;
}
int g_fd;
int StrToNumber( char *str , unsigned long * pulValue)
{
/*判断是否16进制的字符串*/
if ( *str == '0' && (*(str+1) == 'x' || *(str+1) == 'X') )
{
if (*(str+2) == '\0')
{
return -1;
}
else
{
return atoulx(str+2,pulValue);
}
}
else
{
return atoul(str,pulValue);
}
}
int main(int argc, char *argv[])
{
char acDevFile[16] = {0};
unsigned long u8DevNum;
unsigned long u8devaddr;
unsigned long u8reg_width;
unsigned long u8reg;
unsigned long u8value;
if(argc < 4)
{
printf("\n usage: %s . sample: %s 0x1 0x36 0x01 0xf4 (0x10)\n", argv[0], argv[0]);
printf("cmd 1-4\n");
}
StrToNumber(argv[1], &u8DevNum);
StrToNumber(argv[2], &u8devaddr);
StrToNumber(argv[3], &u8reg_width);
StrToNumber(argv[4], &u8reg);
if(argc == 6)
{
StrToNumber(argv[5], &u8value);
}
snprintf(acDevFile, sizeof(acDevFile), "/dev/i2c-%u", u8DevNum);
g_fd = open(acDevFile, O_RDWR, S_IRUSR | S_IWUSR);;
if(g_fd <= 0)
{
printf("open %s failed \n", acDevFile);
return -1;
}
int ret = ioctl(g_fd, I2C_SLAVE_FORCE, (u8devaddr >> 1));
if (ret < 0) {
printf("I2C_SLAVE_FORCE error!\n");
close(g_fd);
g_fd = -1;
return ret;
}
if(argc == 6)
{
int idx = 0;
char buf[8];
/**reg 2Byte*/
if(u8reg_width == 2)
{
buf[idx] = (u8reg >> 8) & 0xff;
idx++;
buf[idx] = u8reg & 0xff;
idx++;
}
else
{
buf[idx] = u8reg & 0xff;
idx++;
}
/**value 1Byte*/
buf[idx] = u8value & 0xff;
idx++;
ret = write(g_fd, buf, 3);
if (ret < 0) {
printf("I2C_WRITE error!\n");
return -1;
}
}
else
{
#if 1
unsigned char buf[4];
struct i2c_rdwr_ioctl_data rdwr;
struct i2c_msg msg[2];
unsigned int data;
memset(buf, 0x0, 4);
msg[0].addr = u8devaddr>>1;
msg[0].flags = 0;
msg[0].buf = buf;
if(u8reg_width == 2)
{
msg[0].len = 2;
buf[0] = (u8reg >> 8) & 0xff;
buf[1] = u8reg & 0xff;
}
else
{
buf[0] = u8reg & 0xff;
msg[0].len = 1;
}
msg[1].addr = u8devaddr>>1;
msg[1].flags = 0;
msg[1].flags |= I2C_M_RD;
msg[1].len = 1;
msg[1].buf = buf;
rdwr.msgs = &msg[0];
rdwr.nmsgs = 2;
ret = ioctl(g_fd, I2C_RDWR, &rdwr);
if (ret != 2) {
printf("CMD_I2C_READ error!\n");
ret = -1;
return -1;
}
data = buf[0];
printf("0x%x: 0x%x\n", u8reg, data);
#endif
}
close(g_fd);
return 0;
}