C51IO口模拟I2C总线驱动AT24C16 (EEPROM部分)

发布者:科技探险者最新更新时间:2018-07-21 来源: eefocus关键字:C51  IO口  模拟I2C  总线驱动  AT24C16  EEPROM 手机看文章 扫描二维码
随时随地手机看文章

/* 

名称:C51IO口模拟I2C总线驱动AT24C16 

说明:关于EEPROM,即这里的AT24C16是一个特殊形式的FLASH存储器,不过其容量一般较少。比较适合于存储少量的数据。


AT24C16的通信接口是标准的I2C通信,即我们需要根据I2C通信协议来操纵EEPROM设备。 关于AT24C16的的各种操作,这里就不细讲了,简单介绍一下。


(1)、主机向AT24C16写一个字节:首先需要发送设备地址,然后发送需要访问的存储器地址。然后在发送要写入的数据。这里省略了开始、结束和确认等信号的产生。


(2)、指定页写入n个字节:和(1)的基本操作很类似。不同的是可以连续写入n个数据。这里要小注意一点的就是,写入的数据如果到达页边界(即n超过16字节)就会产生回滚,也就是重新从页的开始处写入,这样的话可能会覆盖到原来的数据。 本程序的指定页的实现是从页开始处写入的,当然也可以从任何地址开始写入数据,不过还是要注意页边界的问题。


(3)、主机随机从AT24C16读一个字节:这里的操作步骤先是主机向AT24C16写入设备地址和要访问的存储器地址(这个也叫作哑写操作:为了AT24C16装载随机的地址)。然后重新发起读操作,最后从主机接收AT24C16传送的指定地址上的数据


(4)、指定地址顺序读n个字节:这里的操作和(3)中也是差不多,不同的是再读出的时候可以同时读出n个数据。


在这里需要注意一点:在本人的实验中,连续读出n个数据并不会产生到达页边界就会回滚的现象,这里的n可以大于页大小。也就是说,连续读操作地址会自动跨越页边界。但是如果到达地址的边界,应该就会重新回滚了。(关于这点我也并不是很确定,一般的资料上显示的是到达页边界也就产生回滚了,但是我的实验在连续读时确实是没有产生回滚)。


最后这里说一点,AT24C16存储器是128页(页面数)*16字节(页大小)。所以其设备地址结构中1-3位也作为页面地址的高3位,然后存储器地址的高4位作为页面地址的低4位,合起来正好7位,可以访问128个页面。然后存储器地址的低4位作为页偏移,可以访问16个字节的内容。 

*/


//AT24C16写一个字节(keil中int是2个字节,在这里只有11位有效数据位)

int AT24C16_ByteWrite(unsigned int addr,uchar _data)

{

    bit ret_val = 0;

    uchar high_addr = (uchar)(addr>>8);     //高8位地址

    uchar low_addr =(uchar)addr;                //低8位地址


    uchar dev_addr = 0xA0 | ((high_addr&0x0F)<<1);      //组成设备地址,其中包括4-6位是页面地址,


    if(addr > ADDRMAX)

    {

        return OutOfAddr;

    }


    //开启I2C通信

    Start_I2C();


    //发送设备地址

     ret_val = SendByte_I2C(dev_addr);


    if(ret_val != 0)

        return AckError;


        //发送要访问的地址

    ret_val = SendByte_I2C(low_addr);


    if(ret_val != 0)

        return AckError;


        //发送要访问的地址

    ret_val = SendByte_I2C(_data);


    if(ret_val != 0)

        return AckError;


    //停止总线

    Stop_I2C();


    delay_ms(10);           //延时一段时间,等待写操作完成


    return Send_OK;


}




//指定页写入n个字节数据(n<16)

 int AT24C16_PageWrite(uchar page,uchar* p,uchar n)

{

    uchar dev_addr; //设备地址

    uchar low_addr;

    uchar high_addr;

    uchar tmp = 0;

    bit ret_val;


    if((n > 16)|(page > 128)) //根据读写的设备而变更为适合的页数和每页字节数

    {

        return  OutOfRang ;

    }


    high_addr = (page) >> 4; //得出页首地址


    low_addr = ((page & 0x0F)<<4) ;     //得出后四位页地址,组成存储地址的高四位


    dev_addr = 0xa0 | ((high_addr & 0x0F) << 1);


    //开启I2C通信

    Start_I2C();


    //发送设备地址

     ret_val = SendByte_I2C(dev_addr);


     if(ret_val != 0)

            return AckError;


        //发送存储地址,从页首开始

     ret_val = SendByte_I2C(low_addr);

     if(ret_val != 0)

            return AckError;


        delay_ms(10);           //延时一段时间,等待写操作完成


    while(n--)

    {

         ret_val = SendByte_I2C(*p);

         p++;

        if(ret_val != 0)

             return AckError;


        delay_ms(10);           //延时一段时间,等待写操作完成

    }


    //停止I2C通信

     Stop_I2C();

     delay_ms(10);          //延时一段时间,等待写操作完成


    return Send_OK;


}





//AT24C16随机读一个字节

uchar AT24C16_RandomRead(unsigned int addr)

{

    uchar dev_addr; //设备地址

    uchar low_addr;

    uchar high_addr;

    uchar tmp = 0;

    bit ret_val = 0;


    low_addr = (uchar)addr;

    high_addr = (uchar)(addr>>8);

    dev_addr = 0xA0 | ((high_addr&0x0F)<<1);


    if(addr > ADDRMAX)

    {

        return OutOfAddr;

    }


    //开启I2C通信

    Start_I2C();


    //发送设备地址

     ret_val = SendByte_I2C(dev_addr);

     if(ret_val != 0)

        return AckError;


        //发送存储器地址

     ret_val = SendByte_I2C(low_addr);

     if(ret_val != 0)

        return AckError;




    //重新开启I2C通信

    Start_I2C();

    dev_addr = 0xA1 | ((high_addr&0x0F)<<1);        //重新生成设备地址,这次是读操作


    //发送设备地址

     ret_val = SendByte_I2C(dev_addr);

     if(ret_val != 0)

            return AckError;



    //从I2C读取一个字节

    tmp = RecByte_I2C();


    Ack_I2C(1);             //发送非应答位


    //发送停止位

    Stop_I2C();


    return tmp;


}




//指定地址顺序读出n个字节:(注意可能会到达最终的地址边界,产生回滚)

int AT24C16_SequentialRead(unsigned int addr,int n,uchar * p)

{

        uchar dev_addr; //设备地址

        uchar low_addr;

        uchar high_addr;

        uchar tmp = 0;

        bit ret_val = 0;



    if((addr > ADDRMAX)) //根据读写的设备而变更为适合的页数和每页字节数

    {

        return  OutOfAddr ;

    }


     high_addr = (uchar)(addr>>8);      //高8位地址

     low_addr =(uchar)addr;             //低8位地址


     dev_addr = 0xA0 | ((high_addr&0x0F)<<1);       //组成设备地址,其中包括4-6位是页面地址,


     //开启I2C通信

    Start_I2C();



    //哑写操作,让存储器加载设备地址和存储地址

    //发送设备地址

     ret_val = SendByte_I2C(dev_addr);

     if(ret_val != 0)

            return AckError;


        //发送存储地址,从页首开始

     ret_val = SendByte_I2C(low_addr);

     if(ret_val != 0)

            return AckError;


    //重新开启I2C通信

    Start_I2C();

    dev_addr = 0xA1 | ((high_addr&0x0F)<<1);        //组成设备地址,其中包括4-6位是页面地址,


    //重新发送设备地址,这次的目的是读操作

    ret_val = SendByte_I2C(dev_addr);

     if(ret_val != 0)

            return AckError;



    //开始读操作

    while(n--)

{

        *p = RecByte_I2C();

        p++;


        if(n>0)

            Ack_I2C(0);             //数据没接受完,发送应答位

        else

            Ack_I2C(1);             //数据接受完,发送非应答位

    }


    Stop_I2C();


    return Rev_OK;


}


关键字:C51  IO口  模拟I2C  总线驱动  AT24C16  EEPROM 引用地址:C51IO口模拟I2C总线驱动AT24C16 (EEPROM部分)

上一篇:51单片机的延时及定时器
下一篇:C51IO口模拟I2C总线驱动AT24C16 (I2C协议部分)

推荐阅读最新更新时间:2024-03-16 16:09

Keil C51单片机集成开发环境编程与调试教程
同 VC 之类的通用 C 语言集成开发环境(IDE)一样,Keil 也采用“工程” (Project)的方式管理源代码及相关文件,这种管理方式为由多个源代码文件组 成的大型程序开发提供了方便。不管是最简单的 C51程序,还是复杂的多文件 程序都需要以下步骤: 1)先建立新的工程文件; 2)在工程中新建源代码文件,或是将已经存在的源代码文件加入工程; 3)编译; 4)调试,修正错误再编译; 5)将生成的二进制文件*.hex 烧入单片机。 本教程重点介绍上述前 4 个步骤。 二、Keil中新建工程的步骤 1. 单击菜单“Project——New uVision Project……” 出现新建工程对话框: 在此对话框中选择存
[单片机]
Keil <font color='red'>C51</font>单片机集成开发环境编程与调试教程
keil c51是如何启动c程序的
汇编是从org 0000h开始启动,那么keil c51是如何启动main()函数的?keil c51有一个启动程序startup.a51,它总是和c程序一起编译和链接。下面看看它和main()函数是如何编译的; //主函数如下; void main(void) { while (1)这是个无条件空循环。 { } } 把上面的main()函数编译后的汇编程序和反汇编代码整理后对照如下; ?C_C51STARTUPSEGMENTCODE ?PR?main?TESTMAINSEGMENT CODE ?STACKSEGMENTIDATA RSEG?STACK DS1 CSEGAT0 ?C_STARTUP:LJMPSTARTUP1 C
[单片机]
51单片机I2C总线驱动程序
SI2I2C总线是PHLIPS公司推出的一种串行总线,是具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串行总线。 I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。 一.I2C系统结构 每个接到I2C总线上的器件都有唯一的地址。主机与其它器件间的数据传送可以是由主机发送数据到其它器件,这时主机即为发送器。由总线上接收数据的器件则为接收器。 二.数据位的有效性规定 I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。 三.字节传送与应答 每一个字节必须保证是8位长度。数据传送时,
[单片机]
51单片机<font color='red'>I2C</font><font color='red'>总线</font><font color='red'>驱动</font>程序
c51单片机定时中断的精确定时编程方法大全
引 言   MCS-51单片机的中断响应延迟时间,取决于其它中断服务程序是否在进行,或取决于正在执行的是什么样的指 令。单中断系统中的中断响应时间为3~8个机器周期 。无论是哪一种原因引起的误差,在精确定时的应用场合, 必须考虑它们的影响,以确保精确的定时控制。根据定时中断的不同应用情况,应选择不同的精确定时编程方法。   文中以定时器T1工作在定时方式1为例,晶振频率为12MHz 。 1 方法1   在定时器溢出中断得到响应时,停止定时器计数,读出计数值(反映了中断响应的延迟时间),根据此计数值算 出到下一次中断时,需多长时间,由此来重装载和启动定时器。例如定时周期为1ms,则通常定时器重装载值为- 1000(0FC18H)。下
[单片机]
C51自学笔记】串口通信+RS-232C接口+ RS-422A/RS-485接口
简介: 计算机通信是指计算机与外部设备或计算机与计算机之间的信息交换。通信有并行通信和串行通信两种方式。在多微机系统以及现代测控系统中信息的交换多采用串行通信方式。 并行通信 串行通信 串行通信的异步通信 异步通信是以字符(构成的帧)为单位进行传输,字符与字符之间的间隙(时间间隔)是任意的,但每个字符中的各位是以固定的时间传送的,即字符之间不一定有“位间隔”的整数倍的关系,但同一字符内的各位之间的距离均为“位间隔”的整数倍。 串行通信的传输方向 单工是指数据传输仅能沿一个方向,不能实现反向传输。 半双工是指数据传输可以沿两个方向,但需要分时进行。 全双工是指数据可以同时进行双向传输。 串行
[单片机]
【<font color='red'>C51</font>自学笔记】串口通信+RS-232C接口+ RS-422A/RS-485接口
8031单片机I/O口使用
一、实验目的 1、掌握P3口、P1口简单使用。 2、学习延时程序的编写和使用。 二、实验内容 1、实验原理图: 2、实验内容 (1)P3.3口做输入口,外接一脉冲,每输入一个脉冲,P1口按十六进制加1。 (2)P1口做输出口,编写程序,使P1口接的8个发光二极管L1—L8按16进制加1方式点亮发光二极管。 3、实验说明 (1)P1口是准双向口,它作为输出口时与一般的双向口使用方法相同,由准双向口结构可知:当P1口作为输入口时,必须先对它置高电平,使内部MOS管截止,因内部上拉电阻是20KΩ—40KΩ,故不会对外部输入产生影响。若不先对它置高,且原来是低电平,则MOS管导通,读入的数据是不正确的。 (2)延时子程序的
[单片机]
8031单片机I/O口使用
stm32 gpio口的库函数配置
库函数的配置方法 1.例程 GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); 2.GPIO_InitTypeDef GPIO_InitS
[单片机]
PIC单片机内部EEPROM读写程序
#INCLUDE P16F877.inc W_TEMP EQU 20H ; 实际上20H、A0H、120H和1A0H STATUS_TEMP EQU 21H ;在体0中建立保护单元 PCLATH_TEMP EQU 22H ;在体0中建立保护单元 ORG 000H GOTO A1 ORG 004H;定时中断入口地址 GOTO ZD01; ORG 0CH Q1 ADDWF PCL,1 RETLW 00C0H ;0 RETLW 00F9H ;1 RETLW 00A4H ;2 RETLW 00B0H ;3 RETLW
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved