• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

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

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

没买板子之前,用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 }

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
基于C#局域网语音聊天发布时间:2022-07-13
下一篇:
C#中的let字句应用示例发布时间:2022-07-13
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap