51单片机之EEPROM-IIC

由于 51 单片机没有硬件 IIC 接口,即使有硬件接口我们通常还是采用软件模拟 I2C。主要原因是硬件 IIC 设计的比较复杂,而且稳定性不怎么好,程序移植比较麻烦,用软件模拟 IIC,最大的好处就是移植方便,同一个代码兼容所有单片机,任何一个单片机只要有 IO 口(不需要特定 IO),都可以很快的移植过去。

一、数据位的有效性规定
IIC总线进行数据传送时,SCL信号为高电平期间,SDA上的数据必须保持稳定;只有在SCL上的信号为低电平期间,SDA上的高电平或低电平状态才允许变化。

注:IIC只有两根双向信号线,一个是数据线SDA,一个是时钟线SCL。

二、总线寻址方式
IIC 总线寻址按照从机地址位数可分为两种,一种是 7 位,另一种是 10位。本单片机中采用 7 位的寻址字节(寻址字节是起始信号后的第一个字节)的位定义如下:
在这里插入图片描述
D7~D1 位组成从机的地址。D0 位是数据传送方向位,为“ 0”时表示主机
向从机写数据,为“1”时表示主机由从机读数据。

1、编写i2c.h

#include "i2c.h"

void Delay10us()
{
	unsigned char a,b;
	for(b=1;b>0;b--)
		for(a=2;a>0;a--);

}

void I2cStart()
{
	SDA=1;
	Delay10us();
	SCL=1;
	Delay10us();
	SDA=0;
	Delay10us();
	SCL=0;			
	Delay10us();		
}

void I2cStop()
{
	SDA=0;
	Delay10us();
	SCL=1;
	Delay10us();
	SDA=1;
	Delay10us();		
}

unsigned char I2cSendByte(unsigned char dat)
{
	unsigned char a=0,b=0;	
	for(a=0;a<8;a++)
	{
		SDA=dat>>7;	 
		dat=dat<<1;
		Delay10us();
		SCL=1;
		Delay10us();
		SCL=0;
		Delay10us();
	}
	SDA=1;
	Delay10us();
	SCL=1;
	while(SDA)
	{
		b++;
		if(b>200)
		{
			SCL=0;
			Delay10us();
			return 0;
		}
	}
	SCL=0;
	Delay10us();
 	return 1;		
}

unsigned char I2cReadByte()
{
	unsigned char a=0,dat=0;
	SDA=1;
	Delay10us();
	for(a=0;a<8;a++)
	{
		SCL=1;
		Delay10us();
		dat<<=1;
		dat|=SDA;
		Delay10us();
		SCL=0;
		Delay10us();
	}
	return dat;		
}

void At24c02Write(unsigned char addr,unsigned char dat)
{
	I2cStart();
	I2cSendByte(0xa0);
	I2cSendByte(addr);
	I2cSendByte(dat);
	I2cStop();
}

unsigned char At24c02Read(unsigned char addr)
{
	unsigned char num;
	I2cStart();
	I2cSendByte(0xa0);
	I2cSendByte(addr);
	I2cStart();
	I2cSendByte(0xa1);
	num=I2cReadByte();
	I2cStop();
	return num;	
}

2、编写i2c.h文件

#ifndef _I2C_H_
#define _I2C_H_

#include 
sbit SCL=P2^1;
sbit SDA=P2^0;

void I2cStart();
void I2cStop();
unsigned char I2cSendByte(unsigned char dat);
unsigned char I2cReadByte();
void At24c02Write(unsigned char addr,unsigned char dat);
unsigned char At24c02Read(unsigned char addr);
#endif

3、编写主程序main.c

#include "reg52.h"
#include "i2c.h"
#include "intrins.h"

typedef unsigned int ui;
typedef unsigned char uc;
//#define led P2  //×¢Ò⣡£¡²»¼Ó";"
//sbit beep=P1^5;
//sbit led=P2^0;
//sbit moto=P1^0;
sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;

sbit LSA=P2^2;//×îµÍλ
sbit LSB=P2^3;//´ÎµÍλ
sbit LSC=P2^4;//¸ßλ
char num=0;
uc disp[4];
uc code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay(ui i)
{
	while(i--);
}
void Keypros()
{
	if(k1==0)
	{
		delay(1000);
		if(k1==0)
		{
			At24c02Write(1,num);
		}
		while(!k1);
	}
	if(k2==0)
	{
		delay(1000);
		if(k2==0)
		{
			num=At24c02Read(1);
		}
		while(!k2);
	}
	if(k3==0)
	{
		delay(1000);
		if(k3==0)
		{
			num++;
			if(num>255)num=0;
		}
		while(!k3);
	}
	if(k4==0)
	{
		delay(1000);
		if(k4==0)
		{
			num=0;
		}
		while(!k4);
	}
}
void Datapros()
{
	disp[0]=smgduan[num/1000];//千位
	disp[1]=smgduan[num%1000/100];//百位
	disp[2]=smgduan[num%100/10];//十位
	disp[3]=smgduan[num%10];//个位
}
void DigDisplay()
{
	ui i;
	for(i=0;i<4;i++)
	{
		switch(i)
		{
			case(0):
				LSA=1;LSB=1;LSC=1; break;//led-8
			case(1):
				LSA=0;LSB=1;LSC=1; break;//led-7
			case(2):
				LSA=1;LSB=0;LSC=1; break;//led-6
			case(3):
				LSA=0;LSB=0;LSC=1; break;//led-5
		}
		P0=disp[i];
		delay(100);
		P0=0x00;
	}
}
void main()
{
	while(1)
	{
		Keypros();
		Datapros();
		DigDisplay();
	}
}

你可能感兴趣的:(51单片机之EEPROM-IIC)