文章目录
- 介绍
- 读芯片手册
- 代码
- 编译运行
阅读博文:LinuxI2C应用编程——I2C-Tools的使用
介绍
EEPROM (Electrically Erasable Programmable read only memory),指带电可擦可编程只读存储器。是一种掉电后数据不丢失的存储芯片。
读芯片手册
首先按如图所示的方式接好拓展版和EEPROM。
由原理图可知,它的地址为0x50,借助i2cdecect工具可以查看E2PROOM所在插槽对应芯片的哪一个I2C控制器。输入:i2cdetect -y -a 1
,地址0x50在I2C控制器1上。
查阅芯片手册,本实验的E2PROOM,型号为AT24C02,其对应的存储空间为(256*8)位
指定地址写的时序图:
当前地址读:
指定地址读:
指定地址连续读:
由于执行写一个字节后会进入内部的写循环,在这段时间,所有的输入被禁止,循环时间是10ms,需要利用定时器延时毫秒,使用nanosleep
函数,设置时间结构体,最小单位是纳秒。
代码
内核提供了驱动程序 drivers/i2c/i2c-dev.c,编写应用后通过它可以直接使用下面的 I2C 控制器驱动程序来访问 EEPROM设备
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <i2c/smbus.h>
#include "i2cbusses.h"
#include <time.h>
//要达到以下目标
/* ./at24c02 <i2c_bus_number> w "100ask.taobao.com"
* ./at24c02 <i2c_bus_number> r
*/
int main(int argc,char **argv)
{
unsigned char dev_addr = 0x50; //设置设备地址
unsigned char mem_addr = 0; //设置存储空间的地址,从0开始读
unsigned char buf[32]; //只读32个字节
int file;
char filename[20];
int* str;
if(argc != 3 && argc != 4)/*当输入的参数个数不是3或者4的时候,也就是不符合要求*/
{
printf("Usage:\n");
printf("write eeprom: %s /dev/i2c-0|1|2 w string\n",argv[0]);//命令格式的提示信息
printf("read eeprom: %s /dev/i2c-0|1|2 r \n",argv[0]);
return -1;
}
file = open_i2c_dev(argv[1][0]-'0', filename, sizeof(filename), 0); //打开iic设备
//open_i2c_dev的第一个参数需要是i2c控制器的编号:整数
//argv[1] 是字符串,需要取出第0个字符
if(file < 0)
{
printf("can't open %s\n",filename);
return -1;
}
//设置地址
if(set_slave_addr(file, dev_addr, 1)) //设为1是强制设置
{
printf("can't set_slave_addr %s\n",filename);
return -1;
}
if (argv[2][0] == 'w')
{
// write str: argv[3]
str = argv[3];
req.tv_sec = 0;
req.tv_nsec = 20000000; /* 20ms */
while (*str)
{
// mem_addr, *str
// mem_addr++, str++
//使用SMBus协议写一个字节
ret = i2c_smbus_write_byte_data(file, mem_addr, *str);
//写入设备错误
if (ret)
{
printf("i2c_smbus_write_byte_data err\n");
return -1;
}
// wait tWR(10ms)
nanosleep(&req, NULL);
mem_addr++;
str++;
}
ret = i2c_smbus_write_byte_data(file, mem_addr, 0); // string end char
if (ret)
{
printf("i2c_smbus_write_byte_data err\n");
return -1;
}
}
else
{
// read
//使用I2c协议连续读多个字节
ret = i2c_smbus_read_i2c_block_data(file, mem_addr, sizeof(buf), buf);
//读取设备错误
if (ret < 0)
{
printf("i2c_smbus_read_i2c_block_data err\n");
return -1;
}
buf[31] = '\0';
printf("get data: %s\n", buf);
}
return 0;
}
编译运行
由于源码内部用到了i2c协议和smbus协议,将两个协议的头文件和.c文件拷贝到代码目录下,编写Makefile进行交叉编译,目录结构如图所示:
Makefile内容:
all:
$(CROSS_COMPILE)gcc -I ./include -o at24c02_test at24c02_test.c i2cbusses.c smbus.c
在这里引入CROSS_COMPILE变量,指定交叉编译。