登录站点

用户名

密码

利用I2C总线读写EEPROM模块

4已有 1122 次阅读  2011-03-08 17:09   标签菲利普  数据线  高电平  接收器  信号线 

I2C总线是菲利普公司推出的一种串行总线,具备多主机系统所需总线裁决和高低速期间同步的高性能总线。
I2C总线具有两个双向传输的信号线,一根是数据线SDA,一根是时间线SCL。

每个接到I2C总线上的器件都有唯一的地址。主机与其它器件间的数据传送可以是由主机发送数据到其它器件,这时主机即为发送器。由总线上接收数据的器件则为接收器。

I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

/*
** 一下为80C51为例,说明通过I2C总线控制EEPROM的存取。
*/
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int

sbit sda=P2^0;
sbit scl=P2^1;

void delay() {;;}
void init();
void i2c_start();
void i2c_stop();

void snd_byte(uchar dat)
void write(uchar addr, uchar info);
void ack();
uchar read(uchar addr);
uchar rec_byte();


/*
** 驱动主程序
*/
void main() { ...}

/*
** 初始化
*/
void init()
{
 scl=1;
 delay();
 sda=1;
 delay();
}

/*
** SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号。
*/
void i2c_start()
{
 sda=1
 delay();
 scl=1;
 delay();
 sda=0;
}

/*
** SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号
*/
void i2c_stop()
{
 sda=0
 delay();
 scl=1;
 delay();
 sda=1;
}

/*
** 写EEPROM,时序流程为发送设备地址,并告诉从机要写数据(0为写入,
** 1为读出)。从设备响应后发送写入地址,从设备响应后发送写入数据
** 从设备响应后停止,具体见下图:
*/

 
void write(uchar addr, uchar info)
{
 i2c_start();
 snd_byte(0xa0); //发送设备地址
 ack();   //设备响应
    snd_byte(addr); //写入地址
 ack();   //设备响应
 snd_byte(info); //发送数据
 ack();   //设备响应
 i2c_stop(); 
}

/*
** 向EEPROM写一字节数据,以串行方式从高位(MSB)开始按位发送。
*/
void snd_byte(uchar dat)
{
 uchar temp,i;
 i=0;
 temp=dat;
 while(i++<8)
 {
  temp=temp<<1;
  scl=0;
  delay();
  sda=CY;  //CY是PSW溢出位寄存器
  delay();
  scl=1;
  delay();
 }
 /*
 ** 拉高SDA,释放总线
 */
 scl=0;
 delay();
 sda=1;
 delay();
}
/*
** EEPROM从设备响应信号。
*/
void ack()
{
 uchar i;
 i=0;
 scl=1;
 delay();
 /*
 ** 若从设备sda不发生跳变并且没有发送完LSB,
 ** 则持续轮询sda
 */
 while((sda==1)&&(i++<255));
 scl=0;
 delay();
}

/*
** 从EEPROM读取数据,时序为主设备寻找设备,从设备响应,
** 主设备寻址,从设备响应。重新启动I2C总线,发送设备地址,
** 并设置读/位为读,从设备响应后发送数据,停止总线
** 时序如下图:
*/


void read(uchar addr)
{
 uchar info;
 i2c_start();
 write(0xa0); //寻找设备,设置为写模式
 ack();
 write(addr); //设备寻址
 ack();
 i2c_start(); //重新启动I2C总线
 write(0xa1); //寻找设备,设置为读模式
 ack();
 info=rec_byte();
 i2c_stop;
 return
}

/*
** 从EEPROM读一字节数据,以串行方式从高位(MSB)开始按位发送。
*/
uchar rec_byte()
{
 int i;
 uchar j,k;

 scl=0;
 delay();
 sda=1;
 for(i=0;i<8;i++) // 一字节有八位,循环八次依次读取数据
 {
  scl=1;   // 在一个时钟周期内读取sda总线数据
  delay();
  j=sda;
  k=(k<<1)|j;  // 移位存储从EEPROM读回的数据
  scl=0;
  delay();
 }
 return k;
}

上一篇: [视频转播]Mathcad在电子工程中的应用 没有了

分享 举报

发表评论 评论 (2 个评论)

涂鸦板