概述
在读写I2C设备时,由于I2C地址分为7bit和10bit,读写时序存在区别,因此应用程序也存在区别。
首先来看读写时序对比,这里以写为例:
可以看出从设备地址分成了两次进行传输。
于是应用程序可以这样修改。
首先是7位模式下对某设备寄存器的读写:
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/types.h>
int higher2lower(char c);
int htoi(char s[]);
#define MSB_0_7_OF_U32(DATA) ((DATA >> 24) & 0xFF)
#define MSB_8_15_OF_U32(DATA) ((DATA >> 16) & 0xFF)
#define MSB_16_23_OF_U32(DATA) ((DATA >> 8) & 0xFF)
#define MSB_24_31_OF_U32(DATA) ((DATA >> 0) & 0xFF)
#define REG_VAL_32_BIT(VAL_8_BIT_0, VAL_8_BIT_1, VAL_8_BIT_2, VAL_8_BIT_3)
((VAL_8_BIT_0 << 24) | (VAL_8_BIT_1 << 16) | (VAL_8_BIT_2 << 8) | VAL_8_BIT_3)
//this is i2c 7-bit
int main1(int argc, char *argv[])
{
int fd, i, j, ret;
char *errorinfo;
struct i2c_rdwr_ioctl_data work_queue;
unsigned int i2c_adaptor, slave_address, reg_address, byte_count, reg_val, format_cetc, reg_num, rw_flag;
unsigned char val;
// access_tran access;
i2c_adaptor = 0;
slave_address = htoi(argv[1]);
reg_address = htoi(argv[2]);
reg_val = htoi(argv[3]);
rw_flag = htoi(argv[4]);
printf("i2c_adaptor : %#xnslave_address : %#xnreg_address : %#xnreg_val : %#xnrw_flag : %#xn",
i2c_adaptor, slave_address, reg_address, reg_val, rw_flag);
fd = open("/dev/i2c-1", O_RDWR);
if(!fd)
{
printf("Error on opening the device filen");
return 0;
}
//IIC configuration
ioctl(fd, I2C_TIMEOUT, 2);
ioctl(fd, I2C_RETRIES, 1);
/*
* IIC operation
* rw_flag = 1; READ
* rw_flag = 0; WRITE
*/
if(rw_flag)
{
work_queue.nmsgs = 2;
work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));
if(!work_queue.msgs)
{
printf("memory alloc errorn");
close(fd);
return 0;
}
reg_num = 1;
format_cetc = (rw_flag << 31) | ((reg_num - 1) << 22) | (reg_address >> 2);
printf("format_cetc : %#xn", format_cetc);
(work_queue.msgs[0]).len = 4;
(work_queue.msgs[0]).addr = slave_address;
(work_queue.msgs[0]).flags = 0;//w
(work_queue.msgs[0]).buf = (unsigned char *)malloc(4);
(work_queue.msgs[0]).buf[0] = MSB_0_7_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[1] = MSB_8_15_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[2] = MSB_16_23_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[3] = MSB_24_31_OF_U32(format_cetc);
// (work_queue.msgs[0]).buf[3] = MSB_0_7_OF_U32(format_cetc);
// (work_queue.msgs[0]).buf[2] = MSB_8_15_OF_U32(format_cetc);
// (work_queue.msgs[0]).buf[1] = MSB_16_23_OF_U32(format_cetc);
// (work_queue.msgs[0]).buf[0] = MSB_24_31_OF_U32(format_cetc);
// (work_queue.msgs[0]).buf[0] = MSB_16_23_OF_U32(reg_address);
// (work_queue.msgs[0]).buf[1] = MSB_24_31_OF_U32(reg_address);
(work_queue.msgs[1]).len = 4;
(work_queue.msgs[1]).flags = I2C_M_RD;//R
(work_queue.msgs[1]).addr = slave_address;
(work_queue.msgs[1]).buf = (unsigned char *)malloc(4);
ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);
reg_val = REG_VAL_32_BIT(work_queue.msgs[1].buf[0], work_queue.msgs[1].buf[1],
work_queue.msgs[1].buf[2], work_queue.msgs[1].buf[3]);
if(ret < 0)
printf("error code : %dn", ret);
else
printf("slave_addr : %#x reg_addr : %#x reg_val : %#xn", slave_address, reg_address, reg_val);
free(work_queue.msgs);
}
else
{
work_queue.nmsgs = 1;
work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));
printf("work_queue.msgs addr* : %#xn", (unsigned int*)work_queue.msgs);
if(!work_queue.msgs)
{
printf("memory alloc errorn");
close(fd);
return 0;
}
reg_num = 1;
format_cetc = (rw_flag << 31) | ((reg_num - 1) << 22) | (reg_address >> 2);
printf("format_cetc : %#xn", format_cetc);
(work_queue.msgs[0]).len = 8;//reg_addr 4 + reg_val 4
(work_queue.msgs[0]).addr = slave_address;
(work_queue.msgs[0]).flags = 0;//w
(work_queue.msgs[0]).buf = (unsigned char *)malloc(8);
(work_queue.msgs[0]).buf[0] = MSB_0_7_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[1] = MSB_8_15_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[2] = MSB_16_23_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[3] = MSB_24_31_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[4] = MSB_0_7_OF_U32(reg_val);
(work_queue.msgs[0]).buf[5] = MSB_8_15_OF_U32(reg_val);
(work_queue.msgs[0]).buf[6] = MSB_16_23_OF_U32(reg_val);
(work_queue.msgs[0]).buf[7] = MSB_24_31_OF_U32(reg_val);
ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);
if(ret < 0)
printf("error code : %dn", ret);
free(work_queue.msgs);
}
close(fd);
return ret;
}
int higher2lower(char c)
{
if(c >= 'A' && c <= 'Z')
return c + 'a' - 'A';
else
return c;
}
int htoi(char s[])
{
int i;
int n = 0;
if(s[0] == '0' && (s[1] == 'x' || s[1] == 'x'))
i = 2;
else
i = 0;
// if((s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f')
|| (s[i] >= 'A' && s[i] <= 'F'))
// {
for(;(s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f')
|| (s[i] >= 'A' && s[i] <= 'F'); ++i)
{
if(higher2lower(s[i] > '9'))
{
n = 16 * n +(10 + higher2lower(s[i]) - 'a');
}
else
n = 16 * n + (higher2lower(s[i] - '0'));
}
// }
return n;
}
然后是10位模式下对寄存器的读写
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/types.h>
int higher2lower(char c);
int htoi(char s[]);
#define MSB_0_7_OF_U32(DATA) ((DATA >> 24) & 0xFF)
#define MSB_8_15_OF_U32(DATA) ((DATA >> 16) & 0xFF)
#define MSB_16_23_OF_U32(DATA) ((DATA >> 8) & 0xFF)
#define MSB_24_31_OF_U32(DATA) ((DATA >> 0) & 0xFF)
#define REG_VAL_32_BIT(VAL_8_BIT_0, VAL_8_BIT_1, VAL_8_BIT_2, VAL_8_BIT_3)
((VAL_8_BIT_0 << 24) | (VAL_8_BIT_1 << 16) | (VAL_8_BIT_2 << 8) | VAL_8_BIT_3)
int main(int argc, char *argv[])
{
int fd, i, j, ret;
char *errorinfo;
struct i2c_rdwr_ioctl_data work_queue;
unsigned int i2c_adaptor, slave_address, reg_address, byte_count, reg_val, format_cetc, reg_num, rw_flag;
unsigned char val;
unsigned int baseadd=0;
unsigned int value[2];
unsigned int offset[3]={0};
unsigned int num[3]={0};
// access_tran access;
i2c_adaptor = 1;
slave_address = htoi(argv[1]);
baseadd = htoi(argv[2]);
reg_val = htoi(argv[3]);
rw_flag = htoi(argv[4]);
reg_address=baseadd;
value[1]=slave_address&0xff;
value[0]=((slave_address&0x300)>>8)|0x78;
fd = open("/dev/i2c-1", O_RDWR);
if(!fd)
{
printf("Error on opening the device filen");
return 0;
}
//IIC configuration
ioctl(fd, I2C_TIMEOUT, 2);
ioctl(fd, I2C_RETRIES, 1);
/*
* IIC operation
* rw_flag = 1; READ
* rw_flag = 0; WRITE
*/
if(rw_flag)
{
work_queue.nmsgs = 2;
work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));
if(!work_queue.msgs)
{
printf("memory alloc errorn");
close(fd);
return 0;
}
reg_num = 1;
format_cetc = (rw_flag << 31) | ((reg_num - 1) << 22) | (reg_address >> 2);
(work_queue.msgs[0]).len = 5;
(work_queue.msgs[0]).addr = value[0];
(work_queue.msgs[0]).flags = 0;//w
(work_queue.msgs[0]).buf = (unsigned char *)malloc(5);
(work_queue.msgs[0]).buf[0]=value[1];
(work_queue.msgs[0]).buf[1] = MSB_0_7_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[2] = MSB_8_15_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[3] = MSB_16_23_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[4] = MSB_24_31_OF_U32(format_cetc);
(work_queue.msgs[1]).len = 4*reg_num;
(work_queue.msgs[1]).flags = I2C_M_RD;//R
(work_queue.msgs[1]).addr = value[0];
(work_queue.msgs[1]).buf = (unsigned char *)malloc(4*reg_num);
ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);
reg_val = REG_VAL_32_BIT(work_queue.msgs[1].buf[0], work_queue.msgs[1].buf[1],
work_queue.msgs[1].buf[2], work_queue.msgs[1].buf[3]);
if(ret < 0)
{
printf("error code : %dn", ret);
}
else
{
printf("slave_addr : %#x reg_addr : %#x reg_val : %#xn", slave_address, reg_address, reg_val);
}
free(work_queue.msgs);
}
else
{
work_queue.nmsgs = 1;
work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));
printf("work_queue.msgs addr* : %#xn", (unsigned int*)work_queue.msgs);
if(!work_queue.msgs)
{
printf("memory alloc errorn");
close(fd);
return 0;
}
reg_num = 1;
format_cetc = (rw_flag << 31) | ((reg_num - 1) << 22) | (reg_address >> 2);
(work_queue.msgs[0]).len = 9;//reg_addr 4 + reg_val 4
(work_queue.msgs[0]).addr = value[0];
(work_queue.msgs[0]).flags = 0;//w
(work_queue.msgs[0]).buf = (unsigned char *)malloc(9);
(work_queue.msgs[0]).buf[0]=value[1];
(work_queue.msgs[0]).buf[1] = MSB_0_7_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[2] = MSB_8_15_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[3] = MSB_16_23_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[4] = MSB_24_31_OF_U32(format_cetc);
(work_queue.msgs[0]).buf[5] = MSB_0_7_OF_U32(reg_val);
(work_queue.msgs[0]).buf[6] = MSB_8_15_OF_U32(reg_val);
(work_queue.msgs[0]).buf[7] = MSB_16_23_OF_U32(reg_val);
(work_queue.msgs[0]).buf[8] = MSB_24_31_OF_U32(reg_val);
ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);
if(ret < 0)
{
printf("error code : %dn", ret);
}
free(work_queue.msgs);
}
close(fd);
return ret;
}
int higher2lower(char c)
{
if(c >= 'A' && c <= 'Z')
return c + 'a' - 'A';
else
return c;
}
int htoi(char s[])
{
int i;
int n = 0;
if(s[0] == '0' && (s[1] == 'x' || s[1] == 'x'))
i = 2;
else
i = 0;
// if((s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f')
|| (s[i] >= 'A' && s[i] <= 'F'))
// {
for(;(s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f')
|| (s[i] >= 'A' && s[i] <= 'F'); ++i)
{
if(higher2lower(s[i] > '9'))
{
n = 16 * n +(10 + higher2lower(s[i]) - 'a');
}
else
n = 16 * n + (higher2lower(s[i] - '0'));
}
// }
return n;
}
可以看出10位模式下要比7位模式多发送一个字节,10位模式是把slave addr的低8位放在了数据字段中进行发送。
最后
以上就是傻傻哈密瓜为你收集整理的Zynq-Linux移植学习笔记之43-linux下应用读写I2C设备的全部内容,希望文章能够帮你解决Zynq-Linux移植学习笔记之43-linux下应用读写I2C设备所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复