linux下通过IIC总线读写EEPROM

2019独角兽企业重金招聘Python工程师标准>>> linux下通过IIC总线读写EEPROM
文章图片

by 韩大卫@吉林师范大学
handawei@jusontech.com
转载请务必表明出处。
我的上篇文章《linux下i2c与E2PROM通信》给出了通过IIC总线,如何读写EEPROM相应位置的内容。
但是有一些功能没有实现:

比如:只能单独操作一个寄存器地址,不能一次性写入大量内容;
只能读一个寄存器的数值,不能可选择性地一次读出大量内容;
这是由于为了做到通用化,我们的i2c没有一次性大量读写的功能。 在本程序中针对EEPROM做了一些改进,详细说明可以在help_info() 中找到。
FOR EXAMPLE:

eep -r0x08Display the contents of EEPROM from 0x00 to 0x08

eep -ro 0x08Display the contents of EEPROM from 0x08

eep -r0x02 0x80Display the contents of EEPROM from address 0x20 to x080

eep -s0x04 "hello world!"Write "hello world!" to EEPROM from 0x04

eep -d /dev/i2c-1 -s0x04 "hello world!"Write "hello world!" to EEPROM from 0x04 with path"/dev/i2c-1"

*************************************************************
以下是具体代码: main.c
********************** *******************************
#include "i2c.h"

#define TIMEOUT4
#define RETRY2
#define READ_ONLY1

static int fd ;
static int addr = 0x57;
static int offset;
static int offset_end;

inline int read_data(u16 addr, u8 offset, u8 *val){
int ret;

ret = i2c_read_data(addr,offset,val);
if(ret < 0){
printf("%s error!\n",__FUNCTION__);
exit(-1);
}
return 0;
}

inline int write_data(u16 addr, u8 offset, u8 val){
int ret;

ret = i2c_write_data(addr,offset,val);
if(ret < 0){
printf("%s:error = %s\n",__FUNCTION__,strerror(errno));
exit(-1);
}
usleep(10000);
return 0;
}

int eep_write(u16 addr,u8 offset,char* argv){
//u8 data = https://www.it610.com/article/(u8)strtoul(argv,0,16);

int i,j,len= 0;
char* data= https://www.it610.com/article/argv;

while( *data++ ){
len++;
}
data = https://www.it610.com/article/argv;

printf("len = %d\n",len);

for( i = offset ,j = 0; i < offset + len ; i++,j++ ){
write_data(addr,i,data[j]);
}
printf("write success,data = https://www.it610.com/article/%s/n",argv);
return 0;
}

int eep_read(u16 addr,u8 offset_start,u8 offset_end,int flags){

int i;
u8 buf[256] = {0};

if( flags ){
read_data(addr,offset_end,&buf[0]);
printf("read success,data[%d] = %c\n",offset,buf[0]);
}else{
printf("read success,data = "https://www.it610.com/article/);
for(i = offset_start ; i <= offset_end ; i++){
read_data(addr,i,&buf[i]);
printf("%c",buf[i]);
}
printf("\n");
}

return 0;
}

void error_info(void){
printf("cmd error! ");
printf("Please input --help or -hfor help information\n");
exit(-1);
}

void help_info(void){
printf("\nUsage: eep OPTIONS OFFSET [OFFSET_END] [DATA]\n");
printf("\nDisplay the contents of EEPROM ,or write DATA to EEPROM\n");
printf("\nOptions:\n");
printf("\n\t-r OFFST \t\t\t\tDisplay the contents of EEPROM from 0x00 to OFFSET\n");
printf("\n\t-r OFFSET OFFSET_END\t\t\tDisplay the contents of EEPROM from OFFSET to OFFSET_END\n");
printf("\n\t-s OFFSET DATA\t\t\t\twrite DATA to EEPROM form OFFSET\n");
printf("\n\t-h or --help\t\t\t\tshow help information\n");
printf("\nOFFSET\tFORMAT: 0xXX0xXX can change from 00 to ff\n");
printf("\nFOR EXAMPLE:\n");
printf("\n\teep -r0x08\t\t\t\tDisplay the contents of EEPROM from 0x00 to 0x08\n");
printf("\n\teep -ro 0x08\t\t\t\tDisplay the contents of EEPROM from 0x08\n");
printf("\n\teep -r0x02 0x80\t\t\tDisplay the contents of EEPROM from address 0x20 to x080\n");
printf("\n\teep -s0x04 \"hello world!\"\t\tWrite \"hello world!\" to EEPROM from 0x04\n\n");
}

int i2c_path(char * argv){

fd = i2c_open(argv,TIMEOUT,RETRY);
if( fd < 0 ){
printf("i2c_open error!\n");
exit(-1);
}
return 0;
}

int i2c_offs(char *argv){
return (u8)strtoul(argv,0,16);
}

int main(int argc,char* argv[]){

int flags;

switch(argc){
case 2 :{
if(!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help")){
help_info();
}else
error_info();
}break;
case 3 :{
if(!strcmp(argv[1],"-r" )|| !strcmp(argv[1],"-ro" )){
flags= (!strcmp(argv[1],"-ro")) ? READ_ONLY : 0 ;
i2c_path("/dev/i2c-0");
offset= i2c_offs(argv[2]);
eep_read(addr,0,offset,flags);
}else
error_info();
}break;
case 4 :{
if(!strcmp(argv[1],"-r")){
i2c_path("/dev/i2c-0");
offset= i2c_offs(argv[2]);
offset_end= i2c_offs(argv[3]);
eep_read(addr,offset,offset_end,0);
}else if(!strcmp(argv[1],"-s")){
i2c_path("/dev/i2c-0");
offset= i2c_offs(argv[2]);
eep_write(addr,offset,argv[3]);
}else
error_info();
}break;
case 5 :{
if(!strcmp(argv[1],"-d")){
i2c_path(argv[2]);
if(!strcmp(argv[3],"-r") || !strcmp(argv[3],"-ro")){
i2c_offs(argv[4]);
flags= (!strcmp(argv[3],"-ro")) ? READ_ONLY : 0 ;
offset= i2c_offs(argv[4]);
eep_read(addr,0,offset,flags);
}else
error_info();
}else
error_info();
}break;
case 6 :{
if(!strcmp(argv[1],"-d")){
i2c_path(argv[2]);
if(!strcmp(argv[3],"-r")){
offset= i2c_offs(argv[4]);
offset_end= i2c_offs(argv[5]);
eep_read(addr,offset,offset_end,0);
}else if(!strcmp(argv[3],"-s")){
offset= i2c_offs(argv[4]);
eep_write(addr,offset,argv[5]);
}else
error_info();
}else
error_info();
}break;
default:
error_info();
}

return 0;
}
*************************** ********************************
i2c.c
*********************************************************
【linux下通过IIC总线读写EEPROM】#include "i2c.h"

static int fd;


int
i2c_read_data(u16 addr, u8 offset, u8 *val)
{
int i,ret = 0;

struct i2c_rdwr_ioctl_data *data;

if ((data = https://www.it610.com/article/(struct i2c_rdwr_ioctl_data *)malloc(sizeof(struct i2c_rdwr_ioctl_data))) == NULL)
return -1;

data->nmsgs = 2;
if ((data->msgs = (struct i2c_msg *)malloc(data->nmsgs * sizeof(struct i2c_msg))) == NULL) {
ret = -1;
goto errexit3;
}
if ((data->msgs[0].buf = (unsigned char *)malloc( EEPROM_PAGE_SIZE + 1 )) == NULL) {
ret = -1;
goto errexit2;
}
if ((data->msgs[1].buf = (unsigned char *)malloc( EEPROM_PAGE_SIZE + 1 )) == NULL) {
ret = -1;
goto errexit1;
}

data->msgs[0].addr= addr;
data->msgs[0].flags= I2C_M_WR;
data->msgs[0].len= 1;
data->msgs[0].buf[0]= offset;

data->msgs[1].addr= addr;
data->msgs[1].flags= I2C_M_RD;
data->msgs[1].len= 1;
data->msgs[1].buf[0]= 0;

if ((ret = __i2c_send(fd, data)) < 0)
goto errexit0;


for(i = 0 ; i < data->msgs[1].len; i++)
val[i] = data->msgs[1].buf[i];

errexit0:
free(data->msgs[1].buf);
errexit1:
free(data->msgs[0].buf);
errexit2:
free(data->msgs);
errexit3:
free(data);

return ret;
}

int
i2c_write_data(u16 addr, u8 offset, u8 val)
{
int ret = 0;

struct i2c_rdwr_ioctl_data *data;

if ((data = https://www.it610.com/article/(struct i2c_rdwr_ioctl_data *)malloc(sizeof(struct i2c_rdwr_ioctl_data))) == NULL)
return -1;

data->nmsgs = 1;
if ((data->msgs = (struct i2c_msg *)malloc(data->nmsgs * sizeof(struct i2c_msg))) == NULL) {
ret = -1;
goto errexit2;
}
if ((data->msgs[0].buf = (unsigned char *)malloc( 2 * (EEPROM_PAGE_SIZE + 1))) == NULL) {
ret = -1;
goto errexit1;
}


data->msgs[0].addr= addr;
data->msgs[0].flags= 0;
data->msgs[0].len= 2;
data->msgs[0].buf[0]= offset;
data->msgs[0].buf[1]= val;

if ((ret = __i2c_send(fd, data)) < 0){
ret = -1;
goto errexit0;
}

errexit0:
free(data->msgs[0].buf);
errexit1:
free(data->msgs);
errexit2:
free(data);

return ret;
}

int
i2c_open(unsigned char* dev, unsigned int timeout, unsigned int retry)
{
if ((fd = open(dev, O_RDWR)) < 0)
return fd;
__i2c_set(fd, timeout, retry);

return fd;
}

static int
__i2c_send(int fd, struct i2c_rdwr_ioctl_data *data)
{
if (fd < 0)
return -1;

if (data =https://www.it610.com/article/= NULL)
return -1;

if (data->msgs == NULL || data->nmsgs == 0)
return -1;

return ioctl(fd, I2C_RDWR, (unsigned long)data) ;
}

static int
__i2c_set(int fd, unsigned int timeout, unsigned int retry)
{
if (fd == 0 )
return -1;

ioctl(fd, I2C_TIMEOUT, timeout ? timeout : I2C_DEFAULT_TIMEOUT);
ioctl(fd, I2C_RETRIES, retry ? retry : I2C_DEFAULT_RETRY);

return 0;
}

void
i2c_close(int fd)
{
if (fd < 0)
return;

close(fd);
}


unsigned bcd2bin(unsigned char val)
{
return (val & 0x0f) + (val >> 4) * 10;
}

unsigned char bin2bcd(unsigned val)
{
return ((val / 10) << 4) + val % 10;
}
******************************************************
i2c.h:
*********************************************************
#ifndef _EEPROM_IO_H
#define _EEPROM_TO_H

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define I2C_DEFAULT_TIMEOUT1
#define I2C_DEFAULT_RETRY2

#define I2C_M_WR0//定义写标志
#define MAX_MSG_NR2//根据AT24C02手册, 最大消息数为2
#define EEPROM_BLOCK_SIZE256//每个block容量256 bytes
#define EEPROM_PAGE_SIZE8//用页写,AT24C02页大小为8字节
#define I2C_MSG_SIZE(sizeof(struct i2c_msg))

typedef unsigned charu8;
typedef unsigned shortu16;
typedef unsigned intu32;
typedef unsigned long longu64;
typedef signed chars8;
typedef shorts16;
typedef ints32;
typedef long longs64;

unsigned bcd2bin(unsigned char val);

unsigned bcd2bin(unsigned char val);

static int
__i2c_send(int fd, struct i2c_rdwr_ioctl_data *data);

static int
__i2c_set(int fd, unsigned int timeout, unsigned int retry);

int
i2c_read_data(u16 addr, u8 offset, u8 *val);

int
i2c_write_data(u16 addr, u8 offset, u8 val);

int
i2c_open(unsigned char* dev, unsigned int timeout, unsigned int retry);

#endif
****************************************************************8
转载于:https://my.oschina.net/handawei/blog/68585

    推荐阅读