Linux驱动开发 IIC I2C驱动 编写APP访问EEPROM AT24C02

在嵌入式开发中,I2C (Inter-Integrated Circuit)是一种常用的串行通信协议,广泛应用于与外设(如 EEPROM、传感器、显示屏等)进行数据交换。AT24C02 是一种常见的 I2C EEPROM 存储器,它提供 2Kbit 的存储空间,适合存储少量数据,如配置参数或校准数据等。通过编写 I2C 驱动程序和应用程序(APP),我们可以方便地与 AT24C02 EEPROM 进行读写操作。

本指南将介绍如何开发一个 I2C 驱动,编写应用程序来访问 AT24C02 EEPROM,并在 Ubuntu 环境下配置交叉编译工具链来开发和部署该程序。

目录

AT24C02访问方法

在Ubuntu设置交叉编译工具链

[使用I2C app代码](#使用I2C app代码)

AT24C02访问方法

在编写APP之前,我们首先要知道,用哪个IIC控制器,这个IIC设备的设备地址是多少(芯片手册)如下所示就是芯片手册中的截取片段了。因为我们的A2-A0都是拉低的,位于PCB图片中可以看到,因此呢,我们的地址就是0x50了。

同时就是我们也查到了这个设备地址的内容了。

在Ubuntu设置交叉编译工具链

bash 复制代码
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export PATH=$PATH:/home/book/imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin
bash 复制代码
export ARCH=arm
export CROSS_COMPILE=arm-buildroot-linux-gnueabihf-
export PATH=$PATH:/home/book/stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin

使用I2C app代码

相关代码如下:

cpp 复制代码
#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 "xxxxx"
 * ./at24c02 <i2c_bus_number> r
 */

int main(int argc, char **argv)
{
	unsigned char dev_addr = 0x50;
	unsigned char mem_addr = 0;
	unsigned char buf[32];

	int file;
	char filename[20];
	unsigned char *str;

	int ret;

	struct timespec req;
	
	if (argc != 3 && argc != 4)
	{
		printf("Usage:\n");
		printf("write eeprom: %s <i2c_bus_number> w string\n", argv[0]);
		printf("read  eeprom: %s <i2c_bus_number> r\n", argv[0]);
		return -1;
	}

	file = open_i2c_dev(argv[1][0]-'0', filename, sizeof(filename), 0);
	if (file < 0)
	{
		printf("can't open %s\n", filename);
		return -1;
	}

	if (set_slave_addr(file, dev_addr, 1))
	{
		printf("can't set_slave_addr\n");
		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++
			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
		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_bus_number>: 目标设备所在的 I2C 总线号。
  • 操作类型:w 表示写数据,r 表示读数据。
  • 如果是写操作,传入一个要写入 EEPROM 的字符串。

open_i2c_dev 是一个自定义函数,用于打开 I2C 设备文件(例如 /dev/i2c-1)。它根据参数指定的 I2C 总线号来选择设备文件。

set_slave_addr 是另一个自定义函数,用于设置 I2C 从设备的地址。在这里,dev_addr = 0x50 是 AT24C02 EEPROM 的默认设备地址。

如果第二个参数是 w,程序会将字符串写入 EEPROM。

nanosleep(&req, NULL) 在每次写入后暂停 20 毫秒,确保数据能够稳定写入 EEPROM。

最终写入一个 0 字符表示字符串结束。

如果第二个参数是 r,程序会从 EEPROM 中读取数据。

读取的数据存储在 buf 数组中,最后会打印出来。

例子如下所示:

bash 复制代码
./at24c02 1 w "xxxxx"

这会将字符串 "xxxxx" 写入 EEPROM。

如果你要读取 EEPROM 中存储的数据,可以使用以下命令:

bash 复制代码
./at24c02 1 r

这会从 EEPROM 中读取数据并打印出来。

如下为Makefile的相关命令:

cpp 复制代码
all:
	$(CROSS_COMPILE)gcc -I ./include -o at24c02_test at24c02_test.c i2cbusses.c smbus.c
	
相关推荐
沐欣工作室_lvyiyi6 分钟前
基于单片机的蓄电池内阻检测系统设计(论文+源码)
stm32·单片机·嵌入式硬件·物联网·智能家居
电子绿洲8 分钟前
三极管恒流源电路
stm32·单片机·嵌入式硬件·硬件工程·信息与通信·智能硬件
新手嵌入式学习10 分钟前
单片机理论基础
单片机·嵌入式硬件
柘木木12 分钟前
STM32使用UART发送字符串与printf输出重定向
stm32·单片机·嵌入式硬件
Thmos_vader21 分钟前
【minicom】Linux串口调试工具 - minicom的安装及使用
linux·测试工具·minicom·串口调试工具
C囧囧30 分钟前
Ubuntu 22.04.5 修改IP
linux·ip配置·netplan
学Linux的语莫1 小时前
linux中,redis分布式集群搭建
linux·redis·分布式·mysql
ppo_wu1 小时前
Ubuntu 24.04.1 LTS 配置静态固定IP地址
linux·tcp/ip·ubuntu·运维开发
真想骂*2 小时前
如何在Linux上配置SSH密钥以实现免密登录
linux·运维·ssh
国产化嵌入式平台解决方案2 小时前
【服务器主板】定制化:基于Intel至强平台的全新解决方案
嵌入式硬件·intel·服务器主板·至强处理器·定制化