专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

51单片机读写AT24C02源代码(详细注释)

作者:寒竹子   来源:本站原创   点击数:  更新时间:2014年03月23日   【字体:

在P1口上接八个led灯,结果就显示在这八个灯上面。AT24C02的接线方式见程序的顶部的定义。以下是源代码:

#include <reg52.h>//包含头文件
typedef unsigned char uchar;
typedef unsigned int uint;
#define write_c02 0xa0
#define read_c02 0xa1
sbit sda = P2^0;
sbit scl = P2^1;
void delay()
{ //delay:5us
 ;;
}
//i2c:init
void i2c_init()
{
 sda = 1;
 delay();
 scl = 1;
 delay();
}
//delayms:
void delayms(uint xms)
{
 uchar x, y;
 for(x = xms; x > 0; x--)
   for(y = 110; y > 0; y--);
}
//start:
void start() //启动i2c
{
 sda = 1;
 scl = 1;
 delay();//延时必须大于4.7us,此约为五微秒
 sda = 0; //在scl为高电平时,sda一个下降沿为启动信号
 delay();
}
//stop:
void stop() //停止i2c
{
 sda = 0;
 scl = 1;
 delay();
 sda = 1; //在scl为高电平时,sdasda一个上升沿为停止信号
 delay();
}
//ack:
void ack() //应答信号0
{
 uchar i = 0; //等待变量
 scl = 1;//在scl为高电平期间等待应答
 delay();
 while((sda == 1) && i < 250)//若为应答0即退出,从机向主机发送应答信号
 i++;//等待一段时间
 scl = 0; //应答之后将scl拉低
 delay();
}
//nack:
void nack() //非应答
{
 scl = 1;//在scl为高电平期间,由主机向从机发送一个1,非应答信号
 delay();
 sda = 1;
 scl = 0; //应答之后将scl拉低
 delay();
}
//send byte:
void send_byte(uchar date)//写一个字节
{
 uchar i, temp;
 temp = date; //存入要写入的数据,即要发送到sda上的数据
 for(i = 0; i < 8; i++)
 { //发送8位
  temp <<= 1; //to CY 将数据的最高位移入到PSW中的CY位中
  scl = 0;//只有在scl为低电平时,才允许sda上的数据变化
  delay();
  sda = CY; //将CY里的数据发送到sda数据线上
  delay(); //可以延时
  scl = 1; //在scl为高电平时,不允许sda上的数据变化,使数据稳定
  delay();
  scl = 0;//允许sda数据线的数据变化,等待下一个数据的传输
  delay();
 }
 //wait ack:发送完一个字节数据后要主机要等待从机的应答,第九位
 scl = 0;//允许sda变化
 delay();
 sda = 1;//wait:ack,sda拉高等待应答,当sda=0时,表示从机的应答
 delay();
}
//read: byte
uchar read_byte() //读一个字节数据
{
 uchar i, j, k;
 scl = 0; //读之前先允许sda变化
 delay(); //等待数据
 for(i = 0; i < 8; i++)
 {
  scl = 1; //不允许sda变化
  delay(); //使sda数据稳定后开始读数据
  j = sda; //读出sda上的数据
  k = (k << 1)| j; //将数据通过|运算存入k中
  scl = 0;//允许sda变化等待下一位数据的到来
  delay();
 }
 //delay();//可不用延时
 return k;//返回读出的数据
}
//write:at24c02  在at24c02中的指定地址写入数据
void write_at24c02(uchar address, uchar date)
{
 start(); //启动i2c
 send_byte(write_c02);//写入期间地址和写操作
 ack(); //从机应答0
 send_byte(address); //写入写数据的单元地址
 ack(); //ack0
 send_byte(date); //在指定地址中写入数据
 ack(); //从机应答0
 stop();    //停止i2c
}
//read: at24c02   在at24c02的指定地址中读出写入的数据
uchar read_at24c02(address)
{
 uchar dat;//用来存储读出的数据
 start(); //启动i2c
 send_byte(write_c02); //写入at24c02器件地址和写操作
 ack(); //从机应答0
 send_byte(address); //写入要读取AT24C02的数据的单元地址
 ack(); //从机应答0
 start();  //再次启动i2c
 send_byte(read_c02); //写入AT24C02器件地址和读操作
 ack();//从机应答‘0’
 dat = read_byte();//读出指定地址中的数据
 nack(); //主机发出非应答‘1’
 stop();  //停止i2c
 return dat;    //返回读出的数据
}
//main:
void main()
{
 uchar i;
 i2c_init();
 start();
 while(1)
 {
  for(i = 0x00; i < 0xff; i++)
  {
   write_at24c02(10, i);
   delayms(10);//需等待十毫秒
   P1 = read_at24c02(10);//1010 1010
   delayms(2000);
  }
 }
}

关闭窗口

相关文章