对I2C总线上挂接多个AT24C02的读写操作


#include <reg51.h>         //  包含51单片机寄存器定义的头文件
#include <intrins.h>       //包含_nop_()函数定义的头文件
#define    OP_READ1    0xa1        // 器件1地址以及读取操作,0xa1即为1010 0001B
#define    OP_WRITE1 0xa0        // 器件1地址以及写入操作,0xa1即为1010 0000B
#define    OP_READ2    0xaf        // 器件2地址以及读取操作,0xa1即为1010 1111B
#define    OP_WRITE2 0xae        // 器件2地址以及写入操作,0xa1即为1010 1110B
sbit SDA=P3^4;             //将串行数据总线SDA位定义在为P3.4引脚
sbit SCL=P3^3;             //将串行时钟总线SDA位定义在为P3.3引脚
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒
***************************************************/
void delay1ms()
{
   unsigned char i,j;    
     for(i=0;i<10;i++)
      for(j=0;j<33;j++)
       ;         
 }
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
 void delaynms(unsigned char n)
 {
   unsigned char i;
    for(i=0;i<n;i++)
       delay1ms();
 }
/***************************************************
函数功能:开始数据传送
***************************************************/
void start()
// 开始位
{
    SDA = 1;    //SDA初始化为高电平“1”
    SCL = 1;    //开始数据传送时,要求SCL为高电平“1”
    _nop_();    //等待一个机器周期
    _nop_();    //等待一个机器周期
    SDA = 0;    //SDA的下降沿被认为是开始信号
    _nop_();    //等待一个机器周期
    _nop_();    //等待一个机器周期
    _nop_();    //等待一个机器周期
    _nop_();    //等待一个机器周期
    SCL = 0;    //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)
    _nop_();    //等待一个机器周期
}
/***************************************************
函数功能:结束数据传送
***************************************************/
void stop()
// 停止位
{
    SDA = 0;     //SDA初始化为低电平“0”
    _nop_();     //等待一个机器周期
    _nop_();     //等待一个机器周期
    SCL = 1;     //结束数据传送时,要求SCL为高电平“1”
    _nop_();     //等待一个机器周期
    _nop_();     //等待一个机器周期
    _nop_();     //等待一个机器周期
    _nop_();     //等待一个机器周期
    _nop_();     //等待一个机器周期
    _nop_();     //等待一个机器周期
    SDA = 1;    //SDA的上升沿被认为是结束信号    
}
/***************************************************
函数功能:从AT24Cxx读取数据
出口参数:x
***************************************************/
unsigned char ReadData()
// 从AT24Cxx移入数据到MCU
{
    unsigned char i;
    unsigned char x;           //储存从AT24Cxx中读出的数据
    for(i = 0; i < 8; i++)
    {
        SCL = 1;                //SCL置为高电平
        x<<=1;                  //将x中的各二进位向左移一位
        x|=(unsigned char)SDA;  //将SDA上的数据通过按位“或“运算存入x中
        SCL = 0;               //在SCL的下降沿读出数据
    }
    return(x);                //将读取的数据返回
}
/***************************************************
函数功能:向AT24Cxx的当前地址写入数据
入口参数:y (储存待写入的数据)
***************************************************/
//在调用此数据写入函数前需首先调用开始函数start(),所以SCL=0
bit WriteCurrent(unsigned char y)
{
    unsigned char i;
    bit ack_bit;               //储存应答位
    for(i = 0; i < 8; i++)        // 循环移入8个位
    {
        SDA = (bit)(y&0x80);   //通过按位“与”运算将最高位数据送到S
                              //因为传送时高位在前,低位在后
        _nop_();              //等待一个机器周期   
       SCL = 1;              //在SCL的上升沿将数据写入AT24Cxx      
       _nop_();              //等待一个机器周期 
      _nop_();               //等待一个机器周期       
        
          SCL = 0;              //将SCL重新置为低电平,以在SCL线形成传送数据所需的8个脉冲
        y <<= 1;              //将y中的各二进位向左移一位
    }
    SDA = 1;              // 发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)释放SDA线,
                    //以让SDA线转由接收设备(AT24Cxx)控制
    _nop_();        //等待一个机器周期 
    _nop_();        //等待一个机器周期 
    SCL = 1;       //根据上述规定,SCL应为高电平
    _nop_();       //等待一个机器周期 
    _nop_();       //等待一个机器周期 
    _nop_();       //等待一个机器周期 
    _nop_();       //等待一个机器周期 
    ack_bit = SDA; //接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个字节
                   //若送高电平,表示没有接收到,传送异常
    SCL = 0;       //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)
    return  ack_bit;// 返回AT24Cxx应答位
}
/***************************************************
函数功能:向第一个AT24Cxx中的指定地址写入数据
入口参数:add (储存指定的地址);dat(储存待写入的数据)
***************************************************/
void WriteSet1(unsigned char add, unsigned char dat)
// 在指定地址addr处写入数据WriteCurrent
{
    start();                  //开始数据传递
    WriteCurrent(OP_WRITE1);  //选择要操作的第一个AT24Cxx芯片,并告知要对其写入数据
    WriteCurrent(add);        //写入指定地址
    WriteCurrent(dat);        //向当前地址(上面指定的地址)写入数据
    stop();                   //停止数据传递
    delaynms(4);               //1个字节的写入周期为1ms, 最好延时1ms以上
}
/***************************************************
函数功能:向第二个AT24Cxx中的指定地址写入数据
入口参数:add (储存指定的地址);dat(储存待写入的数据)
***************************************************/
void WriteSet2(unsigned char add, unsigned char dat)
// 在指定地址addr处写入数据WriteCurrent
{
    start();                  //开始数据传递
    WriteCurrent(OP_WRITE2);  //选择要操作的AT24Cxx芯片,并告知要对其写入数据
    WriteCurrent(add);        //写入指定地址
    WriteCurrent(dat);        //向当前地址(上面指定的地址)写入数据
    stop();                   //停止数据传递
    delaynms(4);               //1个字节的写入周期为1ms, 最好延时1ms以上
}
/***************************************************
函数功能:从第一个AT24Cxx中的当前地址读取数据
出口参数:x (储存读出的数据) 
***************************************************/
unsigned char ReadCurrent1()
{
    unsigned char x;
    start();                   //开始数据传递
    WriteCurrent(OP_READ1);   //选择要操作的第一个AT24Cxx芯片,并告知要读其数据
    x=ReadData();             //将读取的数据存入x
    stop();                   //停止数据传递
    return x;                 //返回读取的数据
}

/***************************************************
函数功能:从第二个AT24Cxx中的当前地址读取数据
出口参数:x (储存读出的数据) 
***************************************************/
unsigned char ReadCurrent2()
{
    unsigned char x;
    start();                   //开始数据传递
    WriteCurrent(OP_READ2);    //选择要操作的第二个AT24Cxx芯片,并告知要读其数据
    x=ReadData();              //将读取的数据存入x
    stop();                    //停止数据传递
    return x;                  //返回读取的数据
}
/***************************************************
函数功能:从第一个AT24Cxx中的指定地址读取数据
入口参数:set_addr
出口参数:x 
***************************************************/
unsigned char ReadSet1(unsigned char set_addr)
// 在指定地址读取
{
    start();                      //开始数据传递
    WriteCurrent(OP_WRITE1);       //选择要操作的第一个AT24Cxx芯片,并告知要对其写入数据
    WriteCurrent(set_addr);       //写入指定地址
    return(ReadCurrent1());        //从第一个AT24Cxx芯片指定地址读出数据并返回
}
/***************************************************
函数功能:从第二个AT24Cxx中的指定地址读取数据
入口参数:set_addr
出口参数:x 
***************************************************/
unsigned char ReadSet2(unsigned char set_addr)
// 在指定地址读取
{
    start();                       //开始数据传递
    WriteCurrent(OP_WRITE2);       //选择要操作的第二个AT24Cxx芯片,并告知要对其写入数据
    WriteCurrent(set_addr);        //写入指定地址
    return(ReadCurrent2());        //从第二个AT24Cxx芯片指定地址读出数据并返回
}
/***************************************************
函数功能:主函数
***************************************************/
main(void)
{
   unsigned char x;
   SDA = 1;           // SDA=1,SCL=1,使主从设备处于空闲状态
    SCL = 1;             
   WriteSet1(0x36,0xaa);   //将数据"0xaa"写入第一个AT24C02的指定地址"0x36"
    x=ReadSet1(0x36);       //从第二个AT24C02中的指定地址"0x36"读出数据  
   WriteSet2(0x48,x);      //将读出的数据写入第二个AT24C02的指定地址"0x48"?
    P1=ReadSet2(0x48);      //将从第二个AT24C02的指定地址读出的数据送P1口显示验证
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构 模拟实现LinkedList单向不循环链表

目录 一、链表的简单介绍 二、链表的接口 三、链表的方法实现 &#xff08;1&#xff09;display方法 &#xff08;2&#xff09;size得到单链表的长度方法 &#xff08;3&#xff09;addFirst头插方法 &#xff08;4&#xff09;addLast尾插方法 &#xff08;5&#xf…

【深度解析C++】const成员函数

系列文章目录 &#x1f308;座右铭&#x1f308;&#xff1a;人的一生这么长、你凭什么用短短的几年去衡量自己的一生&#xff01; &#x1f495;个人主页:清灵白羽 漾情天殇_计算机底层原理,深度解析C,自顶向下看Java-CSDN博客 ❤️相关文章❤️&#xff1a;Cthis指针&#xf…

特殊权限(suid sticky acl mask)

1.suid 1. 普通用户可不可以修改密码&#xff1f; 答&#xff1a;是可以的&#xff0c;可以修改自己的密码 2. /etc/shadow 文件的作用是什么&#xff1f; 答&#xff1a;存储用户密码的文件 3. 普通用户是否可以修改/etc/shadow 文件&#xff1f; 答&#xff1a;不可以&…

CSDN - 从CSDN下载自己上传的资源要下载码, 自己无法下载

从CSDN下载自己上传的资源要下载码, 自己无法下载 概述 程序里面要用一个参数文件的加解密类, 想到自己以前上传到csdn有demo. 就去下载自己上传的demo. 无法下载, 需要下载码. 也不知道这下载码怎么获得? 按照提示去关注CSDN官方的号, 关注了之后没啥反应, 应该是以前关注过…

java中PhantomReference WeakReference SoftReference垃圾回收触发时机以及使用场景

目录 强引用 垃圾回收触发时机 使用场景 SoftReference&#xff08;软引用&#xff09; 垃圾回收触发时机 使用场景 WeakReference &#xff08;弱引用&#xff09; 垃圾回收触发时机 使用场景 PhantomReference &#xff08;虚引用、幽灵引用&#xff09; 垃圾回收…

2023-12-22 LeetCode每日一题(得到山形数组的最少删除次数)

2023-12-22每日一题 一、题目编号 1671. 得到山形数组的最少删除次数二、题目链接 点击跳转到题目位置 三、题目描述 我们定义 arr 是 山形数组 当且仅当它满足&#xff1a; arr.length > 3存在某个下标 i &#xff08;从 0 开始&#xff09; 满足 0 < i < arr.…

arkts中@Watch监听的使用

概述 Watch用于监听状态变量的变化&#xff0c;当状态变量变化时&#xff0c;Watch的回调方法将被调用。Watch在ArkUI框架内部判断数值有无更新使用的是严格相等&#xff08;&#xff09;&#xff0c;遵循严格相等规范。当在严格相等为false的情况下&#xff0c;就会触发Watch的…

软件开发新手用哪个IDE比较好?软件开发最好的IDE都在这!

目录 IDES 的优点 最佳编程 IDE 列表 Java 开发的流行集成开发环境 JetBrains 的 IntelliJ IDEA NetBeans 适用于 C/ C、C# 编程语言的最佳 IDE Visual Studio 和 Visual Studio 代码 Eclipse PHP 开发的最佳 IDE PHPStorm Sublime Text Atom JavaScript 的顶级 I…

2024年,程序员有哪些危机,有什么应对方式?

在2024年&#xff0c;程序员可能面临的危机主要包括技术更新迅速、职业竞争激烈、工作与生活平衡困难等方面。 为了应对这些危机&#xff0c;程序员可以采取以下策略&#xff1a; 技术更新迅速&#xff1a;随着技术的不断发展&#xff0c;新的编程语言和工具不断涌现&#xff…

大模型请回答2023 :A股能否突破3000点,贾跃亭何时回国?

2023年&#xff0c;国内最少已经有238个公开大模型。 但要回答关于2023年的问题&#xff0c;238个大模型还远远不够。 2023年&#xff0c;站在一个共识被打碎的十字路口。文明的黄金时代逐渐落幕&#xff0c;增长不再是全球经济的理所当然&#xff0c;每一个行业的都面临着新…

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?

2023年就要过去&#xff0c;马上要跨如2024年。祝大家在新的一年&#xff0c;有个好收成。 一直以来不是很确定&#xff1a; 同样的的模板&#xff0c;在各个cpp分别出现&#xff0c;编译器要实现几份&#xff1f; 研究一下。 用命令行的编译方法&#xff0c;参考&#xff1a…

认识计算机网络——计算机网络的组成

计算机网络是由多个计算机和网络设备组成的系统&#xff0c;通过通信协议实现数据传输和信息交换。它是现代社会信息技术的重要支撑&#xff0c;广泛应用于各个领域。本文将介绍计算机网络的主要组成部分&#xff0c;包括硬件设备、软件协议和网络服务。 一、硬件设备 计算机网…