详解AT24CXX驱动开发(linux platform tree - i2c应用)

news2025/1/11 16:56:48

目录

概述

1 认识AT24Cxx

1.1 AT24CXX的特性

1.2 AT24CXX描述

1.2.1 引脚

1.2.2 容量描述

1.2.3 设备地址

1.3 操作时序

1.3.1 写单个字节时序

1.3.2 写page字节时序

1.3.3 读取当前数据时序

1.3.4 随机读取数据

1.3.5 连续读取多个数据

2 驱动开发

2.1 硬件接口

2.2 代码实现

2.2.1 查看设备信息

2.2.2 编写代码

2.2.3 编写Makefile 

2.3 编译代码

3 测试

4 逻辑分析仪查看波形

4.1 写数据波形

4.2 读数据波形


概述

        本文以AT24C02为例,对该类型芯片做全面剖析,详细介绍该芯片的硬件特性和软件设计方面的方法和技巧,其中包括单字节的读和写,连续字节的读写方法、以I2C波形分析。并且在linux平台上,使用I2C接口,编写一个实用案例,实现该芯片的驱动程序。并使用逻辑分析仪工具,详尽解析其工作的波形。

1 认识AT24Cxx

1.1 AT24CXX特性

AT24CXX是一款可进行多次擦除和写数据的串行EEPROM,采用标准的I2C驱动方式,非常方便电路设计和软件程序的设计。总结其特点如下:

1)宽电压:该芯片的工作电压范围为 1.8V ~ 5.5V。可以满足不同MCU平台的设计要求。

2)写保护功能:AT24CXX提供一个引脚WP用于enable或者disable写数据功能,防止由于操作不当,导致存储数据被改写。

3)其可同时支持100K bit/s 和 400K bit/s.

使用时注意: 100 kHz (1.8V, 2.5V, 2.7V) , 400 kHz (5V)

4)使用寿命很长: 擦写次数可达到100 0000 次, 数据保存可达100年

1.2 AT24CXX硬件描述

1.2.1 引脚

          AT24CXX有很多类型,例如: AT24C02A/04A/08A/16A/32A 等待,单其封装形式,基本上一致。标准引脚如下表:

1)WP 为写保护引脚,当WP为低电平是,读写功能被enable;当WP为高电平时, 写数据功能被disable, 这时,只能进行读操作。

2)A0 ~ A2为 地址引脚,对于AT24C02,其可表达的地址空间为:000 ~ 111

AT24CXX芯片封装形式如下图:

1.2.2 容量描述

下面以 AT24C02A/04A/08A 为例,描述其存储空间

芯片型号容量空间( bit)页数( byte)
AT24C02A2048256
AT24C04A4096512
AT24C08A81921024

1.2.3 设备地址

参看设备地址表,可知不同型号的芯片,其可使用的地址空间是不一样的。

1) AT24C02: A0A1A2三个地址引脚都可以使用,其可表达的地址范围为: 000 ~ 111

2) AT24C04: A2A1可用, 其可表达的地址范围为: 00 ~ 11

3) AT24C04: A2可用, 其可表达的地址范围为: 0 ~ 1

4) bit: R/W

(R/W)bit 位的值含义
1读数据
0写数据

1.3 操作时序

1.3.1 写单个字节时序

下图为写一个字节的波形图形:

剖析操作步骤如下:

step - 1: Master SDA发起start信号

step - 2: Master 发送设备地址信息, 最低位 bit0 置位为 bit0=0,表示可进行写操作。

step - 3: AT24CXX 响应ACK

step - 4: Master 发送写数据的地址位

Step - 5: AT24CXX 响应ACK

Step - 6: Master 发送写数据

Step - 7: AT24CXX 响应ACK

step - 8: Master SDA发起stop信号

1.3.2 写page字节时序

下图为写一个page的波形图形:

剖析操作步骤如下:

step - 1: Master SDA发起start信号

step - 2: Master 发送设备地址信息, 最低位 bit0 置位为 bit0=0,表示可进行写操作。

step - 3: AT24CXX 响应ACK

step - 4: Master 发送写数据的起始地址

Step - 5: 连续发送数据

for( i = 0; i < n; i++)

{

      Master_send_data();

      Slave_response_ack();

}

step - 6: Master SDA发起stop信号

1.3.3 读取当前数据时序

下图为读当前地址的波形图形:

剖析操作步骤如下:

step - 1: Master SDA发起start信号

step - 2: Master 发送设备地址信息, 最低位 bit0 置位为 bit0=1,表示可进行读操作。

step - 3: AT24CXX 响应ACK

step - 4: AT24CXX 发送写数据

Step - 5: Master 发送NO ACK

step - 6: Master SDA发起stop信号

1.3.4 随机读取数据

下图为随机读取数据的波形图形:

剖析操作步骤如下:

step - 1: Master SDA发起start信号

step - 2: Master 发送设备地址信息, 最低位 bit0 置位为 bit0=1,表示可进行读操作。

step - 3: AT24CXX 响应ACK

step - 4: Master 发送读字节地址

Step - 5: AT24Cxx 响应ACK

Step - 6: AT24Cxx 发送数据

Step - 7: Master收到数据后,发送NO ACK

step - 8: Master SDA发起stop信号

1.3.5 连续读取多个数据

下图为连续读取多个数据的波形图形:

操作逻辑如下:

step - 1: Master SDA发起start信号

step - 2: Master 发送设备地址信息, 最低位 bit0 置位为 bit0=1,表示可进行读操作。

step - 3: AT24CXX 响应ACK

Step - 4: AT24Cxx 发送数据

for( i = 0; i < n; i++)

{

         at24cxx_send_data();

         master_response_ack();

}

Step - 5: Master发送NO ACK

step - 6: Master SDA发起stop信号

2 驱动开发

2.1 硬件接口

在板卡ATK-DL6Y2C上,I2C2的对应接口:

        pinctrl_i2c2: i2c2grp {
            fsl,pins = <
                MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
                MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
            >;
        };

硬件实物图:

AT24CXX硬件工作电路

2.2 代码实现

       本程序主要应用Linux platform 驱动下的I2C接口,在用户层调用read 和write 函数直接操作芯片。linux内核已经实现I2C相关的驱动程序。用户只需在.dts中配置参数即可。

2.2.1 查看设备信息

使用i2c-tools 查看系统的i2信息,然后在/proc/device-tree目录下查看板卡i2c device tree,使用如下命令:

cd /sys/bus/i2c/devices
ls

可以看见: AT24C02挂载I2C-1总线下,其地址位0x50

查看地址下设备名称

cat 1-0050/name

2.2.2 编写代码

 创建drv_15_at24cxx.c,并在该文件中编写驱动程序

/***************************************************************
Copyright  2024-2029. All rights reserved.
文件名     : test_15_at24cxx.c
作者       : tangmingfei2013@126.com
版本       : V1.0
描述       : 测试at24cxx驱动程序
其他       : 无
日志       : 初版V1.0 2024/02/15

***************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/types.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <linux/fs.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <time.h>

#define DEV_FILE                             "/dev/at24cxx"

#define i2c_dev                              "/dev/i2c-1"

#define AT24CXX_ADDR                         0x50


static int fd = -1;


static int at24cxx_drv_init(void)
{
    fd = open(i2c_dev, O_RDWR);
    if( fd < 0 )
    {
        close( fd );
        printf("%s %s i2c device open failure: %s\n",
         __FILE__, __FUNCTION__, strerror(errno));
        return -1;
    }

    ioctl(fd, I2C_TENBIT, 0);
    ioctl(fd, I2C_SLAVE, AT24CXX_ADDR);
    
    printf("init at24cxx!\r\n");
    return fd;
}


int read_page( unsigned char page, unsigned char *rbuff,  unsigned char length )
{
    unsigned char   tempbuff[1];
    int i = 0, ret;
    
    tempbuff[0] = page;  // address 
    ret = write(fd, tempbuff, 1);
    if( ret < 0 )
    {
       printf("%d %s %s i2c device write address fail: %s\n",
          __LINE__, __FILE__, __FUNCTION__, strerror(errno));
       close(fd);
       return -1;
    }
    
    ret = read(fd, rbuff, length);
    if( ret < 0 )
    {
        printf("%d %s %s i2c device read data fail: %s\n", 
         __LINE__ , __FILE__, __FUNCTION__, strerror(errno));
        close(fd);
        return -1;
    }
    printf(" read data to at24c02 in address = %d \r\n ", page);
    for( i=0; i< length; i++ )
    {
        printf(" %x \t ", rbuff[i]);
    }
    printf(" \r\n ");
    
    return 0;
}

int write_page(  unsigned char page,  unsigned char *buff, unsigned char len)
{
    unsigned char   tempbuff[len+1];
    int i = 0, ret;
    
    printf(" write data to at24c02 in address = %d \r\n ", page);
    // step-1: write 
    tempbuff[0] = page;
    for( i=1; i< sizeof(tempbuff); i++ )
    {
        tempbuff[i] = buff[i-1];
        printf(" %x \t ", tempbuff[i]);
    }
    printf(" \r\n ");
    
    ret = write(fd, tempbuff, sizeof(tempbuff));
    if( ret < 0 )
    {
       printf("%d %s %s i2c device write data failure: %s\n",
         __LINE__,  __FILE__, __FUNCTION__, strerror(errno));
       close(fd);
       return -1;
    }
    
    return 0;
}


int main(void)
{
    #define LEN    8
    unsigned startpage = 8;
    unsigned char buff[LEN];
    unsigned char rbuff[LEN];
    int i = 0, index = 0, j= 0;
    
    fd = at24cxx_drv_init();
    
    for( j=0; j < 5; j++ )
    {
        // write data 
        for(i = 0; i < sizeof( buff); i++ )
        {
            buff[i] = 0x20 + index;
            index++;
        }
        
        write_page( startpage, buff, sizeof( buff)); 
        printf(" \r\n \r\n ");
        startpage += 8;
        usleep(20000);   //20ms 
    }
   
    startpage = 8;
    for( j=0; j < 5; j++ )
    {
        read_page( startpage, rbuff, sizeof( rbuff));
        printf(" \r\n \r\n ");
        startpage += 8;
        usleep(20000); //20ms 
    }
    
    return 0;
}




2.2.3 编写Makefile 

创建Makefile文件,编写代码

CFLAGS= -Wall -O2
CC=/home/ctools/gcc-linaro-4.9.4-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc
STRIP=/home/ctools/gcc-linaro-4.9.4-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-strip


test_15_at24cxx: test_15_at24cxx.o
	$(CC) $(CFLAGS) -o test_15_at24cxx test_15_at24cxx.o
	$(STRIP) -s test_15_at24cxx

clean:
	rm -f test_15_at24cxx test_15_at24cxx.o

2.3 编译代码

       使用Make命令编译代码,然后将生成的执行文件copy到NFS下的共享目录中,方便在板卡中执行代码:

在板卡中可以看见:

3 测试

在板卡中运行程序后,可以看见:

4 逻辑分析仪查看波形

4.1 写数据波形

以连续写多个数据为例,分析芯片的驱动波形:

1)写地址波形

2)写数据波形

 

3)Stop 信号

4.2 读数据波形

以连续读多个数据为例,分析芯片的驱动波形:

1)写起始地址

3) 读数据byte

 4) 结束波形

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1459785.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小清新卡通人物404错误页面源码

小清新卡通人物404错误页面源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 蓝奏云&#xff1a;https://wfr.lanzout.com/i6XbU1olftde

发电机项目 2/19

MQTT 一.MQTT是什么&#xff1f; MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;&#xff0c;是一种基于发布/订阅&#xff08;publish/subscribe&#xff09;模式的“轻量级”通讯协议&#xff0c;该协议构建于TCP/IP协议…

【Python】OpenCV-图片添加水印处理

图片添加水印处理 1. 引言 图像处理中的水印添加是一种常见的操作&#xff0c;用于在图片上叠加一些信息或标识。本文将介绍如何使用OpenCV库在图片上添加水印&#xff0c;并通过详细的代码注释来解释每一步的操作。 2. 代码示例 以下是一个使用OpenCV库的简单代码示例&…

2023年全球前端大技术大会(GMTC北京站2023):核心内容与学习收获(附大会核心PPT下载)

此次峰会是一次内容丰富、有深度和广度的技术盛会。参会者不仅可以了解前端技术的最新发展和未来趋势&#xff0c;还可以与业界专家交流心得&#xff0c;提升自己的技能和能力。同时&#xff0c;此次大会也促进了全球前端社区的交流和合作&#xff0c;推动了前端技术的创新和发…

仪表板展示|DataEase看中国:历年研究生报考数据分析

背景介绍 在信息时代的浪潮中&#xff0c;研究生教育作为培养高层次专业人才的重要通道&#xff0c;不断吸引着广大毕业生和在职人士的关注。今天我们结合2018年&#xff5e;2024年的研究生报考数据&#xff0c;以数字为镜&#xff0c;深入了解近年来研究生培养态势。 本文将…

爬虫在网页抓取的过程中可能会遇到哪些问题?

在网页抓取&#xff08;爬虫&#xff09;过程中&#xff0c;开发者可能会遇到多种问题&#xff0c;以下是一些常见问题及其解决方案&#xff1a; 1. IP封锁&#xff1a; 问题&#xff1a;封IP是最常见的问题&#xff0c;抓取的目标网站会识别并封锁频繁请求的IP地址。 解决方案…

C#开发AGV地图编辑软件

C#自己开发AGV地图编辑软件&#xff1a; 1、自由添加和删除站点、停车位、小车、运行路径。 2、编辑得地图以XML文件保存。 3、导入编辑好地图的XML文件。 4、程序都是源码&#xff0c;可以直接在此基础上进行二次开发。 下载链接&#xff1a;https://download.csdn.net/d…

Linux:sed进阶(12)

Linux&#xff1a;shell脚本&#xff1a;基础使用&#xff08;5&#xff09;《正则表达式-sed工具》_linux脚本表达式s-CSDN博客https://blog.csdn.net/w14768855/article/details/132347574?ops_request_misc%257B%2522request%255Fid%2522%253A%252217084222871680019707523…

普中51单片机学习(定时器和计数器)

定时器和计数器 51单片机有两组定时器/计数器&#xff0c;因为既可以定时&#xff0c;又可以计数&#xff0c;故称之为定时器/计数器。定时器/计数器和单片机的CPU是相互独立的。定时器/计数器工作的过程是自动完成的&#xff0c;不需要CPU的参与。51单片机中的定时器/计数器是…

nginx的功能以及运用

nginx与apache的对比 nginx优点 nginx使用场景 编译安装nginx过程 1.先清空opt文件夹 2.关闭防火墙&#xff0c;关闭防护 3 安装依赖包&#xff0c;可以通过本地yum去安装 首先就是挂载&#xff0c;随后切换到配置文件中修改 4本地配置文件配置内容 5 随后安装环境包 yum -y …

【大厂AI课学习笔记】【2.2机器学习开发任务实例】(9)模型优化

模型训练后&#xff0c;就要进行模型优化了。 一般来讲&#xff0c;很简单&#xff0c;优化就是不换模型换参数&#xff0c;或者直接换模型。 换了之后来对比&#xff0c;最后选个最好的。 比如在本案例中&#xff0c;选择LinearRegression后&#xff0c;MSE从22下降到12&am…

LWM(LargeWorldModel)大世界模型-可文字可图片可视频-多模态LargeWorld-详细安装记录

说明 Large World Model&#xff08;LWM&#xff09;是一个通用的大环境多模态自回归模型&#xff0c;它利用了一个技术名为RingAttention&#xff0c;通过在大型的多样化视频和图书数据集上的训练&#xff0c;实现了对语言、图像和视频的理解与生成能力。 在github上已有4.2k…

医疗在线问诊小程序:开启数字化医疗新篇章

随着科技的飞速发展&#xff0c;医疗行业正逐步向数字化转型。其中&#xff0c;医疗在线问诊小程序作为一种新型的医疗健康服务模式&#xff0c;为人们提供了更为便捷、高效的医疗咨询服务。本文将探讨医疗在线问诊小程序的发展背景、优势及应用场景&#xff0c;以期为医疗行业…

视频生成模型:构建虚拟世界的模拟器 [译]

原文&#xff1a;Video generation models as world simulators 我们致力于在视频数据上开展生成模型的大规模训练。具体来说&#xff0c;我们针对不同时长、分辨率和宽高比的视频及图像&#xff0c;联合训练了基于文本条件的扩散模型。我们采用了一种 Transformer 架构&#…

第三百五十七回

文章目录 1. 概念介绍2. 使用方法2.1 List2.2 Map2.3 Set 3. 示例代码4. 内容总结 我们在上一章回中介绍了"convert包"相关的内容&#xff0c;本章回中将介绍collection.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章回中介绍的内容是col…

第3.2章:Doris-2.0数据导入——Compaction机制

目录 一、Compaction概述 1.1 LSM-Tree概述 1.2 Compaction概述 1.3 Rowset数据版本 1.4 Compaction优点 1.5 Compaction问题 1.5.1 Compaction速度低 1.5.2 写放大问题 1.6 Compaction调优 1.6.1 业务侧 1.6.2 运维侧 二、Compaction执行方式 2.1 Vertical Com…

【Unity】【VR开发】Unity云同步功能使用心得

【背景】 有时出差,旅行等等也带着电脑,晚上想要继续编辑项目,就需要用到云同步功能。目前实践下来,发现有些内容可以同步,有些内容则是不可以同步的,总结如下。 【如何云同步一个本地项目】 UnityHub的项目面板中有两个选项卡:项目和云端项目。 鼠标挪动到想要云同步…

Linux——信号(3)

经过前两部分的介绍&#xff0c;我们现在已经认识了信号是如何产生的&#xff0c;并且知道无 论信号是如何产生的&#xff0c;最终只能由操作系统来对特定进程发送信号&#xff0c;而发送 信号其实也就是写信号&#xff0c;往内核数据结构&#xff08;pending表&#xff09;中写…

STM32引脚重定义问题

最近在搞资源管理&#xff0c;发现有些引脚不能用 比如这个PE引脚。我想用他输出PWM&#xff0c;但是不能用&#xff0c;我也重定义了&#xff0c;还是不能用。回去翻看了技术手册。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //重映射引脚功能&#xff0c;需…

Java面试题:volatile专题

王有志,一个分享硬核Java技术的互金摸鱼侠 加入Java人的提桶跑路群:共同富裕的Java人 今天是《面霸的自我修养》第4篇文章,我们一起来看看面试中会问到哪些关于volatile的问题吧。数据来源: 大部分来自于各机构(Java之父,Java继父,某灵,某泡,某客)以及各博主整理文档…