单片机练习 - I2C总线协议

本文介绍了一种使用单片机通过软件模拟I2C总线协议的方法,并详细展示了如何对AT24C02 EEPROM进行读写操作的具体代码实现。
这次利用单片机通过软件模拟I2C总线协议, 并对基于I2C协议的AT24C02 EEPROM进行读写操作, 具体说明与功能见代码注释.

AT24C02与单片机的连接电路图如下:


单片机利用P2.0模拟SDA, P2.1模拟SCL.

程序代码:
ContractedBlock.gifExpandedBlockStart.gifI2C总线协议
  1None.gif//用软件方法模拟I2C总线协议来读写AT24C02 EEPROM
  2None.gif//每次上电后, 继续按照上次的计数结果计数, 每半秒计数一次
  3None.gif#include <reg52.H>
  4None.gif#include <intrins.H>
  5None.gif
  6None.gif#define uchar unsigned char
  7None.gifsbit SDA = P2^0;
  8None.gifsbit SCL = P2^1;
  9None.gif
 10None.gif//仿真延时5.43us
 11None.gifvoid delay5us()
 12ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 13InBlock.gif    _nop_();
 14ExpandedBlockEnd.gif}

 15None.gif
 16None.gif//延时10ms, 仿真约11ms
 17None.gif//实际测试中, 对于写一个字节, 只须2ms
 18None.gifvoid delay10Ms()
 19ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 20InBlock.gif    uchar a,b;
 21InBlock.gif    for(a=50;a>0;a--)
 22InBlock.gif     for(b=100;b>0;b--);
 23ExpandedBlockEnd.gif}

 24None.gif
 25None.gif//延时2ms
 26None.gifvoid delay2Ms()
 27ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 28InBlock.gif    uchar a,b;
 29InBlock.gif    for(a=10;a>0;a--)
 30InBlock.gif     for(b=100;b>0;b--);
 31ExpandedBlockEnd.gif}

 32None.gif
 33ExpandedBlockStart.gifContractedBlock.gif/**//***************************** I2C总线协议 ************************************/
 34None.gif//起始信号
 35None.gifvoid start()
 36ExpandedBlockStart.gifContractedBlock.gifdot.gif
 37InBlock.gif    SDA = 1;  //启动I2C总线
 38InBlock.gif    SCL = 1;
 39InBlock.gif    delay5us();    //延时
 40InBlock.gif    SDA = 0;    //起始信号
 41InBlock.gif    delay5us();    //SDA拉低时间至少4us后, 才能拉低SCL
 42InBlock.gif    SCL = 0;    
 43ExpandedBlockEnd.gif}

 44None.gif
 45None.gif//终止信号
 46None.gifvoid stop()
 47ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 48InBlock.gif    SDA = 0
 49InBlock.gif    SCL = 1;    //SCL拉高至少4us后, 才能拉高SDA, 产生终止信号
 50InBlock.gif    delay5us();
 51InBlock.gif    SDA = 1;
 52InBlock.gif    delay5us();    //保持SDA拉高4.7us以上 
 53InBlock.gif    //终止后, 总线处于空闲状态
 54ExpandedBlockEnd.gif}

 55None.gif
 56None.gif//发送应答
 57None.gifvoid ack()
 58ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 59InBlock.gif    SDA = 0;
 60InBlock.gif    SCL = 1;
 61InBlock.gif    delay5us();
 62InBlock.gif    SCL = 0;
 63InBlock.gif    SDA = 1;
 64ExpandedBlockEnd.gif}

 65None.gif
 66None.gif//发送非应答
 67None.gifvoid nack()
 68ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 69InBlock.gif    SDA = 1;
 70InBlock.gif    SCL = 1;
 71InBlock.gif    delay5us();
 72InBlock.gif    SCL = 0;
 73ExpandedBlockEnd.gif}

 74None.gif
 75None.gif//获取应答, 有应答返回0, 非应答返回1
 76None.gifbit getAck()
 77ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 78InBlock.gif    bit flag;
 79InBlock.gif    SDA = 1;
 80InBlock.gif    SCL = 1;
 81InBlock.gif    flag = SDA;
 82InBlock.gif    SCL = 0;
 83InBlock.gif    return flag;
 84ExpandedBlockEnd.gif}

 85None.gif
 86None.gif//发送一字节数据, 有应答返回0, 非应答返回1
 87None.gifbit sendByte(uchar dat)
 88ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 89InBlock.gif    uchar i;
 90InBlock.gif    for(i = 0; i < 8; i++)
 91ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 92InBlock.gif        dat = dat << 1//左移, 最高位将移到CY中
 93InBlock.gif        SDA = CY;
 94InBlock.gif        SCL = 1;
 95InBlock.gif        delay5us();
 96InBlock.gif        SCL = 0;
 97ExpandedSubBlockEnd.gif    }

 98InBlock.gif    return getAck();
 99ExpandedBlockEnd.gif}

100None.gif
101None.gif//接收一字节数据
102None.gifuchar recvByte()
103ExpandedBlockStart.gifContractedBlock.gifdot.gif{
104InBlock.gif    uchar i, tmp, dat;
105InBlock.gif    for(i = 0; i < 8; i++)
106ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
107InBlock.gif        SCL = 1;
108InBlock.gif        delay5us();
109InBlock.gif        if(SDA == 1)
110ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
111InBlock.gif            tmp = 1;
112ExpandedSubBlockEnd.gif        }

113InBlock.gif        else 
114InBlock.gif            tmp = 0;
115InBlock.gif        dat = (dat << 1| tmp;
116InBlock.gif        SCL = 0;
117InBlock.gif        delay5us();
118ExpandedSubBlockEnd.gif    }

119InBlock.gif    return dat;
120ExpandedBlockEnd.gif}

121None.gif
122ExpandedBlockStart.gifContractedBlock.gif/**//***************************** I2C总线协议 ************************************/
123None.gif
124None.gif
125ExpandedBlockStart.gifContractedBlock.gif/**//***************************** AT24C02 EEPROM的读写操作 ************************************/
126None.gif//AT24C02 EEPROM 在TX1-B实验板上的地址是 1010 000B
127None.gif
128None.gif//向EEPROM指定地址写一字节数据
129None.gifvoid writeByte(uchar dat, uchar add)
130ExpandedBlockStart.gifContractedBlock.gifdot.gif{
131InBlock.gif    start();
132InBlock.gif    sendByte(0xa0);    //找出EEPROM芯片, 写数据
133InBlock.gif    sendByte(add); //先写地址
134InBlock.gif    sendByte(dat); //读数据
135InBlock.gif    stop(); //释放总线
136InBlock.gif    delay2Ms(); //发送完写数据, stop()后, 需要延时10ms让芯片完成内部写周期
137InBlock.gif    //实际测试中, 写一字节, 只须2ms
138ExpandedBlockEnd.gif}

139None.gif
140None.gif//连续写指定长度的字节流(Page Write)
141None.gifvoid writeBytes(uchar * dats, uchar length, uchar add)
142ExpandedBlockStart.gifContractedBlock.gifdot.gif{
143InBlock.gif    uchar i;
144InBlock.gif    start();
145InBlock.gif    sendByte(0xa0);
146InBlock.gif    sendByte(add);
147InBlock.gif    for(i = 0; i < length; i++)
148ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
149InBlock.gif        sendByte(dats[i]);
150ExpandedSubBlockEnd.gif    }

151InBlock.gif    stop();
152InBlock.gif    delay10Ms();
153ExpandedBlockEnd.gif}

154None.gif
155None.gif//读取EEPROM指定地址的一字节数据(Random Read)
156None.gifuchar readByte(uchar add)
157ExpandedBlockStart.gifContractedBlock.gifdot.gif{
158InBlock.gif    uchar dat;
159InBlock.gif    start();
160InBlock.gif    sendByte(0xa0);    //找出EEPROM芯片, 写数据
161InBlock.gif    sendByte(add); //先写地址
162InBlock.gif    start();
163InBlock.gif    sendByte(0xa1); //读数据
164InBlock.gif    dat = recvByte();
165InBlock.gif    nack(); //非响应
166InBlock.gif    stop(); //释放总线
167InBlock.gif    return dat;
168ExpandedBlockEnd.gif}

169None.gif
170None.gif//连续读指定大小的字节数(Sequential Read)
171None.gifvoid readBytes(uchar * buffer, uchar size, uchar add)
172ExpandedBlockStart.gifContractedBlock.gifdot.gif{
173InBlock.gif    uchar i, count = size - 1;
174InBlock.gif    start();
175InBlock.gif    sendByte(0xa0);
176InBlock.gif    sendByte(add);
177InBlock.gif    start();
178InBlock.gif    sendByte(0xa1);
179InBlock.gif    for(i = 0; i < count; i++)
180ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
181InBlock.gif        buffer[i] = recvByte();
182InBlock.gif        ack();  //应答
183ExpandedSubBlockEnd.gif    }

184InBlock.gif    buffer[count] = recvByte();
185InBlock.gif    nack();    //非应答, 结束
186InBlock.gif    stop();
187ExpandedBlockEnd.gif}

188None.gif
189ExpandedBlockStart.gifContractedBlock.gif/**//***************************** AT24C02 EEPROM的读写操作 ************************************/
190None.gifsbit wela = P2^7;  //数码管位选
191None.gifsbit dula = P2^6;  //数码管段选
192None.gif
193None.gif//0-F数码管的编码(共阴极)
194ExpandedBlockStart.gifContractedBlock.gifunsigned char code table[]=dot.gif{0x3f,0x06,0x5b,0x4f,0x66,
195ExpandedBlockEnd.gif    0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}
;
196None.gifvoid display(uchar v) 
197ExpandedBlockStart.gifContractedBlock.gifdot.gif{
198InBlock.gif    unsigned char count;
199ExpandedSubBlockStart.gifContractedSubBlock.gif    unsigned char datas[] = dot.gif{000};
200InBlock.gif    datas[0= v / 100;
201InBlock.gif    datas[1= v % 100 / 10;
202InBlock.gif    datas[2= v % 10;
203InBlock.gif    for(count = 0; count != 3; count++)
204ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
205InBlock.gif        //关位选, 去除对上一位的影响
206InBlock.gif        P0 = 0xff
207InBlock.gif        wela = 1//打开锁存, 给它一个下降沿量
208InBlock.gif        wela = 0;
209InBlock.gif        //段选
210InBlock.gif        P0 = table[datas[count]];
211InBlock.gif        dula = 1;  //打开锁存, 给它一个下降沿量
212InBlock.gif        dula = 0;
213InBlock.gif        //位选 
214InBlock.gif        P0 = _crol_(0xfe, count); //选择第(count + 1) 个数码管
215InBlock.gif        wela = 1//打开锁存, 给它一个下降沿量
216InBlock.gif        wela = 0;
217InBlock.gif        delay2Ms();
218ExpandedSubBlockEnd.gif    }

219ExpandedBlockEnd.gif}

220None.gif
221None.gifuchar value, th, tl, tCount;
222None.gifvoid main()
223ExpandedBlockStart.gifContractedBlock.gifdot.gif{
224InBlock.gif    value = readByte(0);  //向EEPROM地址0读一字节数据
225InBlock.gif    tCount = 0;
226InBlock.gif    EA = 1;     //开中断
227InBlock.gif    ET1 = 1;    //允许T1中断
228InBlock.gif    TMOD = 0x10//工作方式1
229InBlock.gif    TH1 = th = 0x4b;//(65536 - 50000/1.085) / 256; //定时50ms
230InBlock.gif    TL1 = tl = 0xfd;//(65536 - 50000/1.085) - th * 256;
231InBlock.gif    TR1 = 1;     //T1开始计时
232InBlock.gif    while(1)
233ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
234InBlock.gif        if(tCount > 10)  //满500ms, 加1
235ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
236InBlock.gif            value++;
237InBlock.gif            writeByte(value, 0); //将当前值保存在EEPROM地址0中
238InBlock.gif            tCount = 0;
239ExpandedSubBlockEnd.gif        }

240InBlock.gif        display(value);
241ExpandedSubBlockEnd.gif    }

242ExpandedBlockEnd.gif}

243None.gif
244None.gifvoid time1() interrupt 3
245ExpandedBlockStart.gifContractedBlock.gifdot.gif{
246InBlock.gif    TH1 = th;
247InBlock.gif    TL1 = tl;
248InBlock.gif    tCount++;
249ExpandedBlockEnd.gif}


经过两个星期的单片机学习,  对单片机有了一个深层次的了解. 而这次以后, 将不会连续关注单片机, 会将重心放回Asp.net开发上....
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值