软件:
a. Keil uVision3.0;
b. Easy 51Pro v2.0;
实验电路原理图:

从原理图可看出,这次实验在原51最小系统上扩展,通过引脚P0^0,P0^1分别控制AT24C01的两引脚SCL,SDA。图左边加个4路拨码开关可以动态改变AT24C01器件地址和写保护WP状态。
实验以路拨码开关打开,即A0,A1,A3,WP都为0为例.
测试成功源代码:
文件1: Delay.c
#include "Delay.h"
//晶振11.0592
//延时函数
void Delay()
{}
//延时1ms
void Delay1MS(uchar n)
{
uchar i=110;
while(n--)
{
while(i--);
}
}
文件2: Delay.h
#ifndef _DELAY_H_
#define _DELAY_H_
#ifndef uchar
#define uchar unsigned char
#endif
#pragma SAVE
#pragma REGPARMS
void Delay(); //延时函数
void Delay1MS(uchar); //延时1MS函数
#pragma RESTORE
#endif
文件3:I2C.c
#include <reg51.h>
#include "Delay.h"
#include "I2C.h"
//init
void I2C_Init()
{
SDA=1;
SCL=1;
}
//start condition
void I2C_Start()
{
SDA=1;
Delay();
SCL=1;
Delay();
SDA=0;
Delay();
}
//stop condition
void I2C_Stop()
{
SCL=0;
Delay();
SDA=0;
Delay();
SCL=1;
Delay();
SDA=1;
Delay();
}
//response
bit I2C_ACK()
{
uchar i=10;
SCL=0;
Delay();
SDA=1; //准备读
Delay();
SCL=1;
Delay();
while(SDA && i--)
{
Delay();
}
return SDA;
}
//write byte
void I2C_WriteByte(uchar n)
{
uchar i=8;
while(i--)
{
n=n<<1;
SCL=0; //数据变换
Delay();
SDA=CY;
Delay();
SCL=1; //写数据
Delay();
}
}
//read byte
uchar I2C_ReadByte()
{
uchar n=0;
uchar i=8;
SDA=1;
Delay();
while(i--)
{
SCL=0; //数据变换
Delay();
n=(n<<1)|SDA;
P2 = n;
Delay();
SCL=1; //写数据
Delay();
}
return n;
}
文件4:I2C.h
#ifndef _I2C_H_
#define _I2C_H_
#ifndef uchar
#define uchar unsigned char
#endif
sbit SDA=P0^1; //SDA
sbit SCL=P0^0; //SCL
#pragma SAVE
#pragma REGPARMS
void I2C_Init(void); //init
void I2C_Start(void); //start condition
void I2C_Stop(void); //stop condition
bit I2C_ACK(void); //response
void I2C_WriteByte(uchar); //write byte
bit I2C_ReadBit(void); //read bit
uchar I2C_ReadByte(void); //read byte
#pragma RESTORE
#endif
文件5:I2Cmain.c
#include <reg51.h>
#include "Delay.h"
#include "I2C.h"
void main()
{
Delay1MS(250);
I2C_Init();
I2C_Start();
I2C_WriteByte(0xa0); //Write device address
I2C_ACK();
I2C_WriteByte(1); //write address
I2C_ACK();
I2C_WriteByte(0x0a); //write data
I2C_ACK();
I2C_Stop();
Delay1MS(10);
I2C_Start();
I2C_WriteByte(0xa0); //wirte device address
I2C_ACK();
I2C_WriteByte(1); //wirte address for reading
I2C_ACK();
I2C_Stop();
Delay1MS(2);
I2C_Start();
I2C_WriteByte(0xa1); //write device
I2C_ACK();
P2=I2C_ReadByte();//read data
I2C_Stop();
Delay1MS(50);
while(1);
}