没买板子之前,用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. 正则表达式:元字符,量词
  2. Java字节码进制转换
  3. 【产品干货】Uber产品经理首次在中国自述产品理念:我们看中的并非只是钱
  4. Codeigniter 4.0-dev 版源码学习笔记之六——控制器
  5. iPhone 软件:xlate free 编码的好帮手!
  6. ssh非交互式远程命令
  7. 2009 managertool software download..........
  8. java获取异常信息_Python中获取异常(Exception)信息
  9. IT软件创业之 -- 小软件项目也有风险、也会失败、也会损兵折将
  10. mybatis查询返回null解决方案
  11. IRF之LACP-MAD检测
  12. 百度编辑器 UEditor 报错汇总
  13. db2 replace函数的用法_C++常用函数整理
  14. angular图片裁剪
  15. 医学成像学习笔记(一):核磁共振成像(MRI)k空间为何是图像频谱详解
  16. 硬件/操作系统/网络(九):了解常见linux服务器硬件配置
  17. 计算机系统如何禁止文件删除功能,Win7如何禁止在C盘上安装软件?|win7系统c盘哪些文件是可以删除的...
  18. 2021全国特种设备-Q2起重机司机模拟考试题库一[安考星]
  19. win7打不开计算机网络连接,win7电脑网络连接正常打不开网页怎么解决
  20. Python安装Numpy模块

热门文章

  1. SMOTE(Synthetic Minority Over-Sampling Technique ,即“人工少数类过采样法“)----Python调包简单实现
  2. 医学图像分割--U-Net: Convolutional Networks for Biomedical Image Segmentation
  3. 卷积的定义,知乎上有个很有名的段子:
  4. linux ubuntu 查看历史命令
  5. php连接mysql的方式_php连接mysql的三种方式
  6. php去除中文以外的特殊字符,php从文本中去除空格、特殊字符的4种情况
  7. multisim变压器反馈式_【鼎阳硬件智库原创|高速总线】 以太网变压器反转问题技术分析...
  8. keil4出现目标未被创建_STM32入门系列-创建寄存器模板
  9. 在已有的服务器上如何部署网站,如何在云服务器上部署网站
  10. js获取地址栏的各种信息(location)