没买板子之前,用protues画过电路图,实现了通过i2c总线向EEPROM中写入和读出数据。

今天,在自己买的板子上面写关于i2c总线的程序,有个地方忘了延时,调程序的时候很蛋疼。下面说说我对I2c总线的理解

i2c总线共有两根线,一根是时钟信号线,一根是数据线。这里我只实现了,指定EEPROM片内地址,并向其中写入一个字节。从EEPROM中指定地址读出一个字节。

写入过程

1.需要发一个启动信号

2.发送EEPROM设备地址

3.发送EEPROM片内地址

4.发送你要写入的数据

5.发送结束信号

读出过程:

1.发送启动信号

2.发送设备地址(注意这里是伪写  和写入过程前两个步骤一样  注意仔细看EEPROM文档)

3.发送EEPROM片内地址

4.发送启动信号(读数据需要启动两次)

5.发送设备地址(这里和读过程不同的是r/w位  前面是低电平  这里是高电平)

6.读取数据

7.发送结束信号

6.发送结束信号

当然单片机向总线写数据完成后,要注意检测应答信号,读取数据后,单片机应向设备发送,非应答信号或者叫应答非信号。

  1 /*=================================================================================
  2     功能:通过i2c总线向EEPROM中写入数据 并读回数据 验证I2C总线通信 实现记录开机次数
  3     电路图:P2.0接SCL
  4             P2.1接SDA
  5             P1口接led发光二极管
  6             P2.3接 数码管位选信号
  7             P2.2接段选信号
  8             P0口接数码管
  9     注意理解设备发出的应答
 10         和单片机发出的非应答或者叫应答非
 11         两者使得通信完整 只不过方向不一样
 12 ====================================================================================*/
 13 #include <reg51.h>
 14 #include <intrins.h>
 15 #define uchar unsigned char
 16 #define uint unsigned int
 17 #define TIME_SET 50000            /* 一次定时时间 */
 18
 19 sbit scl = P2^0;
 20 sbit sda = P2^1;
 21
 22 bit ack;
 23
 24 uchar code table[] = {
 25     0x3F,0x06,0x5b,0x4f,0x66,0x6d,
 26     0x7d,0x07,0x7f,0x6f,0x77,0x7c,
 27     0x39,0x5e,0x79,0x71,0x00
 28 }; //led亮的数字
 29
 30 sbit wela = P2^3;//位选信号
 31 sbit dula = P2^2;//段选
 32 uchar times;
 33
 34 void start();                    /* 开始信号 */
 35 void stop();                    /* 结束信号 */
 36 void write(uchar byte);            /* 向EEPROM中写入一个字节 */
 37 void delay(uchar time_delay);    /* 延时函数 */
 38 void write_address(uchar byte, uchar address);         /* 根据地址向EEPROM中写入数据 */
 39 uchar read_address(uchar address);                    /* 从指定地址读出数据 */
 40 void no_ack();                    /* 发送一个非应答信号 */
 41 void display(uchar num_display);                    /* 显示开机次数 */
 42 void init();
 43
 44 void main()
 45 {
 46     init();
 47     times = read_address(0x50);
 48     times += 1;
 49     write_address(times, 0x50);
 50     display(times);
 51     while(1);
 52 }
 53 /*==========================
 54     功能:发送启动信号
 55     输入:无
 56     输出:启动信号 SDA负跳变
 57 ============================*/
 58 void start()
 59 {
 60     sda = 1;
 61 //    _nop_();                            /* ? */
 62     scl = 1;
 63     delay(1);
 64     sda = 0;
 65     delay(1);
 66     scl = 0;                               /* scl为什么要拉低 */
 67     delay(1);                            /* ? */
 68 }
 69 /*==========================
 70     功能:发送结束信号
 71     输入:无
 72     输出:启动信号 SDA正跳变
 73 ============================*/
 74 void stop()
 75 {
 76     sda = 0;
 77     _nop_();
 78     scl = 1;
 79     delay(5);
 80     sda = 1;
 81     delay(5);
 82 }
 83 /*==============================================
 84     功能:延时函数 time_delay = 10 延时大约0.5MS
 85     输入:延时时间
 86     输出:延时
 87 ================================================*/
 88 void delay(uchar time_delay)
 89 {
 90     uchar i,j;
 91     for(i = time_delay; i > 0; i--)
 92         for(j = time_delay; j > 0; j --)
 93         {}
 94 }
 95 /*=====================================
 96     功能:向数据线上写一个字节 先写高位
 97     输入:待写字节
 98     输出:写到数据总线上
 99 =======================================*/
100 void write(uchar byte)
101 {
102     uchar i = 0;
103
104     for(; i < 8; i ++)
105     {
106         if((byte << i) & 0x80)
107             sda=1;
108         else
109             sda = 0;
110         delay(1);                    /* 为啥要延时 */
111         scl = 1;
112         delay(1);
113         scl = 0;
114     }
115     delay(1);
116
117     sda = 1;
118     delay(1);
119     scl = 1;
120     delay(1);
121     if(sda == 0)
122         ack = 0;
123     else
124         ack = 1;
125
126     scl = 0;
127 }
128
129 /*=========================================
130     功能:向指定地址写入一个字节数据
131     输入:address写入地址,byte写入字节数据
132     输出:无
133 ===========================================*/
134 void write_address(uchar byte, uchar address)
135 {
136     start();
137     delay(5);
138     write(0xae);        /* 写入设备地址 */
139     delay(5);
140     write(address);
141     delay(5);
142     write(byte);
143
144     delay(5);
145
146     stop();
147     delay(200);      /* 延时很重要!!??? */
148 }
149 /*==========================
150     功能:从指定地址读出数据
151     输入:数据地址
152     输出:指定地址的数据
153 ============================*/
154 uchar read_address(uchar address)
155 {
156     uchar i;
157     uchar result = 0;
158     start();
159
160     write(0xae);    /* 写入设备地址 */
161
162     write(address);
163
164     start();        /* 第二次设置开始信号 */
165
166     write(0xaf);
167
168     sda = 1;
169
170     for(i = 0; i < 8; i ++)            /* 读出数据 */
171     {
172         scl = 0;
173         delay(1);
174         scl = 1;
175         delay(1);
176         result <<= 1;        /* result <<= 1? */
177         if(sda == 1)
178             result = result + 1;
179
180          delay(1);
181     }
182     scl = 0;                    /* 为啥要拉低 */
183     delay(1);
184
185     no_ack();                    /* 发送非应答信号 */
186
187     stop();
188     return result;
189 }
190 /*=======================
191     功能:初始化变量
192     输入:无
193     输出:初始化后的变量
194 ========================*/
195 void init()
196 {
197     ack = 1;
198     scl = 1;
199     sda = 1;
200
201     times = 0;
202     EA = 1;
203     ET0 = 1;
204     TH0 = (65536 - TIME_SET) / 256;
205     TL0 = (65536 - TIME_SET) % 256;
206     TR0 = 1;
207 }
208 /*==========================
209     功能:发送一个非应答信号
210     输入:无
211     输出:非应答信号
212 ============================*/
213 void no_ack()
214 {
215     sda = 1;
216     delay(5);
217     scl = 1;
218     delay(5);
219     scl= 0;
220     delay(5);
221 }
222 /*======================
223     功能:定时器中断函数
224     输入:定时器0中断
225     输出:刷新数码管显示
226 ========================*/
227 void timer0() interrupt 1
228 {
229     TH0 = (65536 - TIME_SET) / 256;
230     TL0 = (65536 - TIME_SET) % 256;
231     display(times);
232 }
233 /*==========================
234     功能:数码管显示开机次数
235     输入:开机次数
236     输出:数码管显示开机次数
237 ============================*/
238 void display(uchar num_display)
239 {
240     uchar ge,shi;//个位和十位
241
242     ge = num_display % 10;
243     shi = num_display / 10;
244     //消影
245     P0 = 0xff;
246     wela = 1;
247     wela = 0;
248     P0 = 0;
249     dula = 1;
250     dula = 0;
251
252
253     //显示十位数字
254     P0 = 0xfe;
255     wela = 1;
256     wela = 0;
257     P0 = table[shi];
258     dula = 1;
259     dula = 0;
260     delay(15);
261
262     //消影
263     P0 = 0xff;
264     wela = 1;
265     wela = 0;
266     P0 = 0;
267     dula = 1;
268     dula = 0;
269
270     //显示个位数字
271     P0 = 0xfd;
272     wela = 1;
273     wela = 0;
274     P0 = table[ge];
275     dula = 1;
276     dula = 0;
277     delay(15);
278 }

转载于:https://www.cnblogs.com/huifeidewoniu/p/3451110.html

通过I2C总线向EEPROM中写入数据,记录开机次数相关推荐

  1. Arduino与Proteus仿真实例-I2C总线多个M24C01设备数据储存仿真

    I2C总线多个M24C01设备数据储存仿真 I2C 总线是一种非常流行且功能强大的总线,用于主机(或多个主机)与单个或多个从设备之间的通信. 下图说明了有多少不同的外设可以共享仅通过 2 条线连接到处 ...

  2. linux下的iic驱动程序,实战经验吐血推荐:怎样在Linux环境下轻松实现基于I2C总线的EEPROM驱动程序...

    4开发实例本文引用地址:http://www.eepw.com.cn/article/279351.htm Linux内核已经提供了I2C驱动中所需要的基本模块.i2c-core.i2c-dev和i2 ...

  3. 【Proteus仿真8086】往8086 内存中写入数据

    这部分内容参考这个博主 https://blog.csdn.net/TTTSEP9TH2244/article/details/122584312 微机原理与接口技术--Proteus仿真软件的使用方 ...

  4. vc++向txt文件中写入数据,追加数据

    例子: #include<iostream> #include<stdio.h> using namespace std; int main() { //将矩阵写在文件上 fl ...

  5. python填写excel-Python向excel中写入数据的方法

    最近做了一项工作需要把处理的数据写入到Excel表格中进行保存,所以在此就简单介绍使用Python如何把数据保存到excel表格中. 数据导入之前需要安装 xlwt依赖包,安装的方法就很简单,直接 p ...

  6. python字符串写入excel-Python向excel中写入数据的方法

    最近做了一项工作需要把处理的数据写入到Excel表格中进行保存,所以在此就简单介绍使用Python如何把数据保存到excel表格中. 数据导入之前需要安装 xlwt依赖包,安装的方法就很简单,直接 p ...

  7. python把数据写入excel_Python向excel中写入数据的方法

    Python向excel中写入数据的方法 最近做了一项工作需要把处理的数据写入到Excel表格中进行保存,所以在此就简单介绍使用Python如何把数据保存到excel表格中. 数据导入之前需要安装 x ...

  8. python向excel写数据_Python向excel中写入数据的方法

    最近做了一项工作需要把处理的数据写入到Excel表格中进行保存,所以在此就简单介绍使用Python如何把数据保存到excel表格中. 数据导入之前需要安装 xlwt依赖包,安装的方法就很简单,直接 p ...

  9. 【Proteus仿真】在AT24C04的连续地址中写入数据并循环读取

    [Proteus仿真]在AT24C04的连续地址中写入数据并循环读取 Proteus仿真 实验说明 在AT24C04的地址0-9中分别写入数据,然后在while循环里面循环从AT24C04的地址0-9 ...

  10. EEPROM中存储数据的字节序

    背景: 最近在做仪表的时候,发现仪表EEPROM中存放的指针式输入输出校验表的数据有问题,和软件中的校验表信息存在差别,就打算去改下,因为之前有老前辈已经教过怎么去改了.但是当时没明白为什么这么去改, ...

最新文章

  1. 为什么安装Android SDK后无法安装flatform?
  2. filezilla 设置服务器_java项目部署到linux服务器,微信小程序后台springboot项目部署到腾讯云服务器(图文详解)...
  3. 【老王来了】之相爱相杀三层交换与链路聚合
  4. python编程狮电脑版_w3cschool编程狮PC版-编程狮电脑版下载 v3.3.10--PC6电脑版
  5. 1g的树莓派4b能做什么_树莓派4B系统安装及配置
  6. visio一分二的箭头_Microsoft Office Visio绘画双箭头直线的具体步骤介绍
  7. 数据库系统概论第五版_第二章:关系数据库
  8. 武汉好地科技为您解析CMMI3和CMMI5的区别
  9. 移动端html5广告的优势,移动端H5广告的互动类型探析
  10. 架构问题--削峰填谷
  11. 挨踢人生路 记我的10年18家工作经历
  12. python 使用while循环输出*组成的菱形_python实现while循环打印星星的四种形状
  13. 结合python使用ffmpeg将批量ts文件合成mp4。
  14. 渗透测试-微信刷票漏洞(IP伪造)
  15. 计算机图文混合排版教学设计,《WORD图文混排》教学设计
  16. 分享一款将中文网站源代码直接生成英文网站的工具
  17. windows服务程序一
  18. 如何利用视频监控系统遏制考试作弊行为?
  19. 【图像隐藏】基于小波变换+SURF、RANSAC、LT码、CRC(循环冗余检验)码多种算法实现图像隐藏(抗多种攻击)matlab源码
  20. 桥梁通服务器物理连接成功,ZStack 实践汇|OSPF搭建与物理网络通信的“桥梁”

热门文章

  1. ImportError: IProgress not found. Please update jupyter and ipywidgets.
  2. 调用sklearn库--分类学习
  3. VLFeat工具包在matlab使用方法
  4. 贝尔英才学院计算机,特稿 | 从高三的二模倒数第一到考取南京邮电大学贝尔英才学院,他仅用了半年!...
  5. 提示框几秒消失比较好_移动设计提示框介绍-《产品日常笔记》
  6. fastreport实现动态列_excel中如何实现聚光灯效果?
  7. Docker教程小白实操入门(11)--如何构建私有Registry
  8. 微信测试环境下不能用window.open()
  9. java configuration类_使用@Configuration编写自定义配置类
  10. oracle将列名进行拼接,请教关于用拼接的字符串作为表的列名进行操作的问题