当前位置: 首页 > 编程日记 > 正文

51单片机实现对24C02进行页写、顺序读取并显示验证

源:51单片机实现对24C02进行页写、顺序读取并显示验证

//*************************************************************************************
//**程序名称:51单片机实现对24C02进行页写、顺序读取并显示验证
//**编写人:**** 
//**修改人:****
//**程序目的:熟悉I2C总线协议,实现51模拟I2C时序和24C02通信
//**功能描述:51单片机将8个字节数据写入24C02的一页中,然后顺序读出,每隔1秒送P0口LED显示
//**其他说明:本程序是采用某51开发板,若在其他地方验证可更改相关端口及延时程序等。
//** 程序编写前曾参考过多个教程,最终自己编程通过,并详加注释。
//** 可供初学者参考,并不对程序的可靠性等作保证。
//**开发工具:keil 7.50 (C51) 
//**日期:
//*************************************************************************************
#include <REGX51.H>
#include <intrins.h>    //因为用到_nop_();
typedef unsigned char uchar;
sbit SCL = P3^3;        //注意P1、P2、P3口有内部上拉电阻,可直接连SDA和SCL,若想用P0需外接上拉电阻,否则连上无法输出高电平!
sbit SDA = P3^4;
uchar j;                //用于计数50ms的个数的全局变量
uchar code ToSDAdataBuffer[8] = {0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00}; //写入24C02的一组数据,8个字节对应24C02的一页(共32页),这里把这些要验证的常数放到程序存储区
uchar ReceivedData[8];    //用于存储接收的8个字节数据(1页)的数组//本例51为单主机,24C02为从机,不需要总线裁决
//延时5us子程序
void delay5us(void)
{_nop_(); //时序图要求开始建立时间tSU.STA大于4.7us,开始保持时间tHD.STA大于4us。51中每个_nop_();延时1个CPU cycle,即1us。_nop_(); //如考虑不同CPU频率不同,可用带参数的延时,参数在前面宏定义。
    _nop_();_nop_();_nop_();
}//50ms定时器0中断函数
void timer0() interrupt 1         //j是个全局变量,不是返回值,所以这里还是void。
{TH0 = (65536-46080)/256;    //11.0592MHz时每50ms一次定时器中断TL0 = (65536-46080)%256;j++;                         //也可以把判断j到20,并给P0口送显示数据的程序放在中断里处理
}//延时1秒的子程序,用于将读取的数据每隔一秒显示在LED上
void delay1s(void)
{j = 0;TMOD = 0x01;                 //方式1的16位计数器TH0 = (65536-46080)/256;TL0 = (65536-46080)%256;EA = 1;ET0 = 1;TR0 = 1;                     //启动定时器0工作while(j < 20)                //j达到20之前空操作,达到20时说明已到1s,下面关中断和定时器0
    ;EA = 0;ET0 = 0;TR0 = 0;
}//约2ms的延时
void delay(uchar t)
{uchar x,y;for(x=0;x<t;x++)for(y=0;y<250;y++);
}//I2C初始化
void InitI2C(void)
{SDA = 1;                     //总线空闲时,因各设备都是集电极或漏极开路,上拉电阻使SDA和SCL线都保持高电平。SCL = 1;delay5us();
}//产生I2C开始信号
void StartI2C(void)
{SDA = 1;         //SDA在SCL为高期间由高变低表示开始,所以先要高SCL = 1;delay5us();     //时序图要求tSU.STA(Start Set-up Time)大于4.7usSDA = 0;         //注意SDA拉低前后都要维持5us以上!delay5us();     //tHD.STA(Start Hold Time)大于4usSCL = 0;         //拉低SCL,准备发送或接收数据(这两句也可在写或读字节的程序中先将SCL置0,延时)
    delay5us();
}//产生I2C结束信号
void StopI2C(void)
{SDA = 0;         //SDA在SCL为高期间由低变高,说明结束SCL = 1;delay5us();SDA = 1;delay5us();
}//发送方在发完一个字节后检测接收方有没有应答。返回应答成功否。
bit ChkAck(void)
{bit SDAtemp;SDA = 1;         //释放SDA(置1),然后等待接收方应答将它拉低。确切的说,应是24C02发送字节最后一位的第8个时钟周期下降沿后经tAA//(SCL变低到SDA OUT有效的时间)约0.1-4.5us后拉低SDA,并随第9个时钟后结束。所以24C02正常时,SDA为1并不体现//(第8脉冲后马上被拉低了),但若器件坏了,就需要靠这个置1后不变来判断!(若不置1而上次发的数据最后一位为0就不好判断了)//从24C02的Block Diagram看,它只能在SDA为1时通过控制内部的Dout来把SDA拉低,但不能在SDA为0时将其置高!故主机要常将SDA置1,而SCl置0。SCL = 1;         //WriteI2CByte中写完一字节后又将SCL拉低,这里拉高产生第9个时钟上升沿,然后在SCL为高期间对SDA进行检测
    delay5us();SDAtemp = SDA;    //如果不用暂存变量,直接return SDA,就不会执行后面的SCL = 0,检测期间的第9个时钟就不完整了SCL = 0;delay5us();return SDAtemp;
}//51作为主机时,如果接收数据,模拟产生应答时序。形参Ack为0,则应答0,为1不应答。
void AckAsMaster(bit Ack)
{if(!Ack)SDA = 0;elseSDA = 1;delay5us();SCL = 1;         //主机控制SCL时序。关键是保证在SCL脉冲上升沿之前SDA数据已稳定即可。
    delay5us();SCL = 0;delay5us();
}void WriteI2CByte(uchar);
uchar ReadI2CByte();//页写。输入两参数,一个为首字地址,另一个是指向待写入数据数组的指针(括号内第二个参数也可写作uchar ToSDAdataBuffer[],即数组名代表首地址)。
bit PageWrite(uchar WordAddress,uchar *ToSDAdataBuffer)
{//下面的程序我用的if嵌套,网上有些程序是顺序结构,但因为遇到return就返回主程序不再往下执行,所以效果是一样的。
    uchar i;StartI2C();WriteI2CByte(0xa0);//之所以没设DeviceAddress这个参数,是因为最后一位不属于地址。E2PROM一般前四位为1010,这里A2~A0接地,为0,最后一位0表示写if(!ChkAck()){ //检查应答函数返回0说明从机应答0成功。WriteI2CByte(WordAddress); //写8-bit data word address,即写到哪个存储单元(24C02有2kbits,所以数据字有2048/8=256个,故地址线有8位)if(!ChkAck()){for(i = 0; i < 8; i++){WriteI2CByte(ToSDAdataBuffer[i]);if(ChkAck()){//这里可添加错误处理代码。如用几个LED的亮灭组合表示此I2C器件有问题,类似主板错误提示。return 1;//一般返回1表示异常,且遇到return就退出整个子程序。
                }}StopI2C(); //写完发送结束信号。return 0; //一般返回0表示程序正常
        }else{return 1; //之前可添加错误处理代码。
        }}else{return 1;}
}//不能用Current Address Read,因为那是24C02数据字地址计数器上次操作后加1的值;而SEQUENTIAL_READ如果不给一个要读取的开始地址,会从头输出,
//所以需要Random Read的开始部分,但不要停止信号。
bit SequentialRead(uchar WordAddress)
{uchar i;StartI2C();WriteI2CByte(0xa0);if (!ChkAck()){WriteI2CByte(WordAddress);if (!ChkAck()){StartI2C();             //the microcontroller must generate another start conditionWriteI2CByte(0xa1);     //Device Address后紧跟的那一位R/W^是1说明是读,24C02内部就是根据最后这位来判断是从SDA上读数,还是往SDA上送数//之所以设为1是读,是因为根据WriteI2CByte子程序,最后给SDA赋1,P3^4就维持1,这样24C02内部Dout为高就将SDA拉低;//如果最后一位是0,24C02没能力拉高!if (!ChkAck()){for(i = 0;i < 8;i++){ReceivedData[i] = ReadI2CByte();AckAsMaster(0); //51此时接收数据,调用应答的函数(置SDA为0)
                }AckAsMaster(1);     //NO ACK.The microcontroller does not respond with a zero but does
                generate a following stop condition.StopI2C();return 0;}else{return 1;             //之前可添加错误处理代码。
            }}else{return 1;}}else{return 1;}
}int main(void)
{uchar i;P0 = 0xff;InitI2C();//注意在24C02中用到的页写和顺序读的地址是同一个,且必须是8的整数倍,即每页的首地址才行,如0x08,0x20等。因为24C02页写时后三位地址自动加1,//When the word address,internally generated, reaches the page boundary, the following byte is placed at the beginning of the same page.//而顺序读时只有在达到整个存储区边界时才会roll over。所以,如读写都用0x32这个地址,由于不是8的整数倍,只有前6个数显示是正确的,最后两个数//虽然又从头写在了该页的前面,但SequentialRead确读到了该页之外的两个存储单元,造成错误。if (PageWrite(0x08,ToSDAdataBuffer) == 0) { //先执行页写操作,设从地址00开始,没问题就延迟一下再从同一地址读回来。delay(100); //等待24C02页写操作完毕if(SequentialRead(0x08) == 0){ //如果顺序读操作成功,则每隔1秒送P0口显示一个字节for(i = 0; i < 8; i++){P0 = ReceivedData[i];delay1s();}}}while(1);return 0;
}//往I2C总线写一个字节的数据(即将一个字节的数据发送到SDA上)
void WriteI2CByte(uchar ByteData)
{uchar i,temp;temp = ByteData;// (StartI2C()最后已经先将SCL变0了):for(i=0;i<8;i++){temp <<= 1;     //左移一位,I2C要求由MSB最高位开始,移出的CY即要发送到SDA上的数据。下面考虑时序:SDA = CY;       //此时SCL已为低,每次移一位送出去(下次进循环后SDA还保持着上次发出去的数据)delay5us();     //SDA IN数据变化中点SCL上升沿中点的一段时间是tSU.DAT,即数据建立时间Data In Setup Time,需大于200ns,多延无所谓SCL = 1;delay5us();     //tHIGH即Clock Pulse Width High,最小4usSCL = 0;delay5us();     //tLOW即Clock Pulse Width Low,最小4.7us
    }
}//读取I2C总线一个字节的数据
uchar ReadI2CByte()      //串行总线,51一位位接收从机发送到SDA上的数据,这里只考虑数据已在SDA上时如何存下来这几位,组成一个字节
{uchar i,ByteData;SDA = 1;             //SCL在ChkAck中已经置0了。注意SCL时序仍然由主机控制!24C02只能将SDA由高拉低,象橡皮筋松手又恢复高,而下面只是读SDA,没赋值//其实程序中多处给SDA置1都可省,因为检查应答时为0就正常,无所谓,写字节时也无所谓,就是在读之前要保证SDA为1!//因之前有WriteI2CByte(0xa1); 其实这句也可省略。delay5us();      //24C02作为发送方在第9个时钟的negative edge clocks data out of each device,所以现在SDA上为新数据for(i=0;i<8;i++){SCL = 1;         //置时钟线为高使数据线上数据有效
        delay5us();ByteData = (ByteData<<1)|SDA; //SDA上已是新数据了,读之。data不管以前多少,左移后最右边为0,和SDA“按位或”后MLB就是SDASCL = 0;delay5us();}return ByteData;
}

相关文章:

配置MySQL主从复制

MySQL支持单向、异步复制&#xff0c;复制过程中一个服务器充当主服务器&#xff0c;而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件&#xff0c;并维护日志文件的一个索引以跟踪日志循环。当一个从服务器连接到主服务器时&#xff0c;它通知主服务器从…

PHP 单元测试

本文首发于 https://jaychen.cc/article/34作者 Jaychen朋友&#xff0c;你听说过安。。。不是&#xff0c;写过单元测试吗。 单元测试是开发过程中必不可少的一环&#xff0c;一个项目有良好的单元测试代码&#xff0c;重构的勇气都大很多。这次写一篇小文来介绍一下 PHP 的单…

CI框架如何删除地址栏的 index.php

默认 CI 框架显示地址是 http://localhost/ci/index.php/test/ 去掉index.php这样会更好些。1.修改Http.conf的 LoadModule rewrite_module modules/mod_rewrite.so 去掉注释2.ci根目录增加.htaccess文件 <IfModule mod_rewrite.c>RewriteEngine OnRewriteBase /ci#Remov…

网站安全配置(Nginx)防止网站被攻击(包括使用了CDN加速之后的配置)

2019独角兽企业重金招聘Python工程师标准>>> 网站被攻击是一个永恒不变的话题&#xff0c;网站攻击的方式也是一个永恒不变的老套路。找几百个电脑&#xff08;肉鸡&#xff09;&#xff0c;控制这些电脑同时访问你的网站&#xff0c;超过你网站的最大承载能力&…

除了 AI,这些技术为 IIoT 插上飞向“4.0”的翅膀

“中国制造2025、德国工业4.0、美国先进制造”——在21世纪的工业领域&#xff0c;“制造强国”开启新一轮角逐。尽管实现路径各有侧重&#xff0c;但题中之义均是通过互联网和智能技术实现企业生产和管理的降本增效。正因此&#xff0c;IIoT被视为助推智能制造转型升级的“催化…

[20171225]查看并行执行计划注意的问题.txt

[20171225]查看并行执行计划注意的问题.txt--//如果使用dbms_xplan.display_cursor查看并行执行计划注意一些问题,通过例子说明:1.环境:SCOTTbook> &r/ver1PORT_STRING VERSION BANNER------------------------------ -------------- ------…

expires与etag控制页面缓存的优先级

expires指令控制HTTP应答中的“Expires”和“Cache-Control”Header头部信息&#xff0c;启动控制页面缓存的作用time:可以使用正数或负数。“Expires”头标的值将通过当前系统时间加上设定time值来设定。time值还控制"Cache-Control"的值&#xff1a;负数表示no-cac…

API 大赛决赛名单出炉,速来围观!

创新云转型&#xff0c;智慧云服务2021年移动云API应用创新开发大赛正在火热进行中各个赛道激烈PK优秀开发者同台切磋彰显实力&#xff01;10月14日&#xff0c;2021年移动云API应用创新开发大赛复赛在中移软件园双创路演大厅圆满举办。本次复赛分为移动赛道和企业赛道分别进行…

将日期yyyy-MM-dd转为数字大写的形式

/*** 将日期转大写* 例如&#xff1a;2013-05-13转为 二0一三年五月十三日* param date* return */public static String getDxDate(String date){String dateArr[] date.split("-");String year dateArr[0];String month dateArr[1];String day dateArr[2];Str…

DevExpress v17.2新版亮点—WPF篇(四)

2019独角兽企业重金招聘Python工程师标准>>> DevExpress年终击穿底价&#xff0c;单套授权低至67折&#xff01;仅剩最后6天&#xff01;查看详情>>> 用户界面套包DevExpress v17.2终于正式发布&#xff0c;本站将以连载的形式为大家介绍各版本新增内容。本…

CI框架验证码CAPTCHA 辅助函数的使用

使用CAPTCHA 辅助函数很方便生成验证码&#xff0c;但是图片是存储在文件夹下&#xff0c;不是输出流&#xff0c;感觉不够完美&#xff0c;可以拿来用用。 说明&#xff1a;产生4位的随机数&#xff0c;CI根目录下建立captcha文件夹。 <?php $this->load->helper(ca…

GitLab 上市,市值高达 149 亿美元!GitHub 的头号劲敌来了

整理 | 祝涛 出品 | CSDN当地时间周四&#xff0c;知名代码和资源托管服务平台 GitLab&#xff08;股票代码GTLB&#xff09;完成了IPO&#xff08;首次公开募股&#xff09;&#xff0c;在纳斯达克成功上市。GitLab在本次 IPO 中筹集了约 6.5 亿美元。GitLab此前曾计划I…

将ubuntu系统设置静态ip及ssh

2019独角兽企业重金招聘Python工程师标准>>> sudo vim /etc/network/interfaces 输入以下&#xff1a;auto lo iface lo inet loopback auto eno1 iface eno1 inet static address 192.168.1.197 netmask 255.255.255.0 gateway 192.168.1.1 dns-nameserver 192.168…

ECMAScript 5 —— 单体内置对象之Math对象

ECMAScript 还为保存数学公式和信息提供了一个公共位置&#xff0c;即 Math 对象。与我们在 JavaScript 直接编写的计算功能相比&#xff0c;Math 对象提供的计算功能执行起来要快得多。Math 对象中还提供了辅助完成这些计算的属性和方法。 一. Math 对象的属性 Math 对象包含的…

织梦内容管理系统修改

1.如何去掉互动中心 修改根目录下templates——default——index.htm文件&#xff0c;删除以下内容 <div id"rightAD1" style:margin:10px auto"></div> <div class"usercenter">.....到</div> <!-- /usercenter --&…

斯坦福大学 AI100 报告发布:AI 发展速度惊人,但风险也正走进现实

‍‍作者 | 阳光来源 | 学术头条语言处理、计算机视觉和模式识别的巨大进步&#xff0c;意味着人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;每天都在与人们的生活进行交互&#xff0c;从帮助人们选择电影&#xff0c;到帮助人们解决医疗诊断难题方面…

linux===Ubuntu 上安装 Node.js

https://www.cnblogs.com/andfly/p/6681487.html转载于:https://www.cnblogs.com/botoo/p/8118903.html

非计算机专业的学生,从事编程工作的上升壁垒是什么?

很多同学自己的专业并不是计算机&#xff0c;但是看到如今IT行业发展的这么好&#xff0c;也想转行学习编码。但是自己非科班出身&#xff0c;又到了快毕业的年纪&#xff0c;开始学习编程来得及吗&#xff1f;这些年来&#xff0c;很多培训机构都借鉴了少儿编程培训的经验&…

HTTP头信息中的参数Etag

服务器如果是集群&#xff0c;不同服务器返回的 Http Header 中的 Etag 参数不一样。如果是图片是程序生成的&#xff0c;我们可以用 no-cache 这些 header 来控制&#xff0c;但如果这些图片是 apache 或 nginx 等呢&#xff1f;下面开始介绍 Etag&#xff1a;Etag在HTTP1.1中…

利用JS使用POST方式提交请求的方法

2019独角兽企业重金招聘Python工程师标准>>> function post(url, params) {var temp document.createElement("form");temp.action url;temp.method "post";temp.style.display "none";for (var x in params) {var opt document…

input框取消光标颜色手机端不生效

<style> input{ color:transparent; } </style> <input value"我要隐藏光标">//文字颜色可以使用text-shadow属性<style> input{ color:transparent; text-shadow:0 0 0 red; } </style> PC端没问题&#xff0c;但是手机端测试无效。…

http响应Last-Modified和ETag以及Apache和Nginx中的配置

基础知识   1) 什么是”Last-Modified”?   在浏览器第一次请求某一个URL时&#xff0c;服务器端的返回状态会是200&#xff0c;内容是你请求的资源&#xff0c;同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间&#xff0c;格式类似这样&#xff1a; …

全面分析再动手的习惯:链表的反转问题(递归和非递归方式)

定义一个方法&#xff08;函数&#xff09;&#xff0c;实现输入一个链表的头结点&#xff0c;然后可以反转这个链表的方向&#xff0c;并输出反转之后的链表的头结点。 typedef struct Node{int data;Node *next; } Node, *List; 链表类的问题&#xff0c;涉及到了很多指针的操…

Facebook 正在研究新型 AI 系统,以自我视角与世界进行交互

编译 | 禾木木出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;你是否能想象 AI 以第一人称视角来理解世界是什么样的呢&#xff1f;未来&#xff0c;以第一人称视角理解世界的 AI 可以开启沉浸式体验的新时代。增强现实&#xff08;AR&#xff09;眼镜和虚拟现实&…

docker-2-简单使用docker-ce

安装请看docker-ce安装文档 docker命令合集 参考docker --help 选项 -D 使用debug模式-l 日志级别(有debug|info|warn|error|fatal)&#xff0c;默认info-v 显示版本管理命令config 管理docker配置container 管理容器image 管理镜像network 管理网络service swarm 常用命令atta…

Apache启用mod_expires模块

mod_expires可以减少10%左右的重复请求&#xff0c;让重复的用户对指定的页面请求结果都CACHE在本地&#xff0c;根本不向服务器发出请求。 在使用之前,首先要确认一下”mod_expires”模组是否有启用.如果是自己安装Apache来架设网页主机的话,这里我们可以透过编辑Apache的”ht…

用 Pyecharts 制作炫酷的可视化大屏

作者 | 俊欣来源 | 关于数据分析与可视化前两篇Pyecharts的文章来帮我们简单的梳理了一下可以用Pyecharts来绘制哪些图表之后&#xff0c;本篇文章我们用pyecharts里面的一些组件&#xff0c;将绘制的图表都组合起来首先Grid组件首先介绍Pyecharts模块当中的Grid组件&#xff0…

compass安装使用960 Grid System

960 Grid System 是一个CSS的页面布局框架 demo: http://960.gs/demo.html 前提&#xff1a;安装Ruby 、NodeJS 步骤1&#xff1a;在命令行下安装css插件&#xff1a; gem install compass-960-plugin 步骤2&#xff1a;创建my_project项目&#xff1a; compass create -r nin…

C语言竟成TIOBE年度编程语言候选!苹果iPhone 7卖得最好!

每年这个时候&#xff0c;都是TIOBE榜单评选年度编程语言的时候。今年&#xff0c;Kotlin成为竞争的热门&#xff0c;让人意外的是&#xff0c;C语言居然也成为了候选编程语言之一。自从被Java摘走王者桂冠&#xff0c;C语言几乎是处于持续下滑状态&#xff0c;没想到2017年竟然…

奇怪吸引子---QiChen

奇怪吸引子是混沌学的重要组成理论&#xff0c;用于演化过程的终极状态&#xff0c;具有如下特征&#xff1a;终极性、稳定性、吸引性。吸引子是一个数学概念&#xff0c;描写运动的收敛类型。它是指这样的一个集合&#xff0c;当时间趋于无穷大时&#xff0c;在任何一个有界集…