基于IIC协议写入AT24C02

写在前面

本次学习如何使用IIC协议操作AT24C02。

IIC概述

IIC(Inter-Integrated Circuit)其实是IICBus简称,所以中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。
I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。
为了避免总线信号的混乱,要求各设备连接到总线的输出端时必须是漏极开路(OD)输出或集电极开路(OC)输出。

IIC总线协议

IIC起始信号和终止信号
在这里插入图片描述
IIC应答信号
IIC应答信号

AT24C02概述

AT24C02是一个2K位串行CMOS E2PROM, 内部含有256个8位字节,CATALYST公司的先进CMOS技术实质上减少了器件的功耗。AT24C02有一个8字节页写缓冲器。该器件通过IIC总线接口进行操作,有一个专门的写保护功能。

AT24C02支持I2C,总线数据传送协议I2C,总线协议规定任何将数据传送到总线的器件作为发送器。任何从总线接收数据的器件为接收器。数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。主器件和从器件都可以作为发送器或接收器,但由主器件控制传送数据(发送或接收)的模式,由于A0、A1和A2可以组成000~111八种情况,即通过器件地址输入端A0、A1和A2可以实现将最多8个AT24C02器件连接到总线上,通过进行不同的配置进行选择器件。

AT24C02 器件地址
前4位默认为1010 本例中A2,A1,A0接低电平,以及最有一位读写控制位,即器件地址为0xa0 |读写控制位

在这里插入图片描述

AT24C02 字节写入方式
在这里插入图片描述

AT24C02随机读取方式
在这里插入图片描述

实验现象

本例实验 数据初始化为0,按下按键K1,AT24C02存入数据至地址1,按下按键K2,AT24C02读取地址1中的数据并显示,按下按键K3,数据加一,加至大于255时,数据清零,按键K4也为数据清零键。显示模块使用74LS138 驱动4位数码管显示。

程序代码

IIC 程序

//IIC 头文件
#ifndef _IIC_H_
#define _IIC_H_

#include "Stc15.h"
#include "intrins.h"

#define u16 unsigned int 
#define u8 unsigned char
	
#define Main_Fosc 11059200
extern void Delay_5us();

extern void IIC_Start(void);
extern void IIC_Stop(void);
extern unsigned char IIC_SendOneByte(u8 dat);
extern unsigned char IIC_ReceiveOneByte(void);

extern void AT24C02_WriteOneData(u8 addr,u8 dat);
extern unsigned char AT24C02_ReadOneData(u8 addr);


#endif

#include "IIC.h"

sbit SDA = P2^0;           //IIC EEPROM 数据线
sbit SCL = P2^1;           //IIC EEPROM 时钟线

#define AT24C02_WriteAddr  0xa0     //器件地址+写
#define AT24C02_ReadAddr   0xa1     //器件地址+读


/* **************************************
* 函数名称:Delay_5us()
* 入口参数:无
* 出口参数:无
* 函数功能: 5us延时函数
*************************************** */
void Delay_5us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	i = 11;
	while (--i);
}

/* **************************************
* 函数名称:IIC_Start(void)
* 入口参数:无
* 出口参数:无
* 函数功能: IIC起始信号
*************************************** */
void IIC_Start(void)
{
	SDA = 1;
	Delay_5us();
	SCL = 1;
	Delay_5us();
	SDA = 0 ;
	Delay_5us();
	SCL = 0;
	Delay_5us();
}
/* **************************************
* 函数名称:IIC_Stop(void)
* 入口参数:无
* 出口参数:无
* 函数功能: IIC终止信号
*************************************** */
void IIC_Stop(void)
{
	SDA = 0;
	Delay_5us();
	SCL = 1;
	Delay_5us();
	SDA = 1;	
}
/* **********************************************
* 函数名称:unsigned char IIC_SendOneByte(u8 dat)
* 入口参数:u8 dat
* 出口参数:无
* 函数功能: IIC发送一个字节及其应答信号
********************************************** */
unsigned char IIC_SendOneByte(u8 dat)
{
    unsigned char i=0;
	unsigned char uiVal;    //最大255,一个机器周期为1us,最大延时255us。		
	for(i=0;i<8;i++)        //数据移位写入
	{
		SDA=dat>>7;	 
		dat=dat<<1;
		Delay_5us();
		SCL=1;
		Delay_5us();
		SCL=0;
		Delay_5us();		
	}
	SDA=1;
	Delay_5us();
	SCL=1;
	while(SDA)           //等待应答
	{
		uiVal++;
		if(uiVal>200)	 //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
		{
			SCL=0;
			Delay_5us();
			return 0;
		}
	}
	SCL=0;
	Delay_5us();
 	return 1;		
}

/* **********************************************
* 函数名称:unsigned char IIC_ReceiveOneByte(void)
* 入口参数:无
* 出口参数:数据 RecByte
* 函数功能: IIC接收字节数据
********************************************** */
unsigned char IIC_ReceiveOneByte(void)
{
	u8 RecByte;
	u8 i;
	SDA = 1;
	for(i=0;i<8;i++)
	{
		SCL = 0;
		Delay_5us();
		SCL = 1;
		Delay_5us();
		RecByte<<=1;
		if(SDA)
		{
			RecByte |= 0x01;
		}
	}
	SCL = 0;
	return (RecByte);
}

/* **********************************************
* 函数名称:AT24C02_WriteOneData(u8 addr,u8 dat)
* 入口参数:u8 addr u8 dat
* 出口参数: 无
* 函数功能: AT24C02字节写入数据
********************************************** */
void AT24C02_WriteOneData(u8 addr,u8 dat)
{
	IIC_Start();
	IIC_SendOneByte(AT24C02_WriteAddr);         //器件地址+写
	
	IIC_SendOneByte(addr);
	
	IIC_SendOneByte(dat);    
    
	IIC_Stop();
}
/* **********************************************
* 函数名称:AT24C02_ReadOneData(u8 addr)
* 入口参数:u8 addr 
* 出口参数: 数据 temp
* 函数功能: AT24C02随机读取数据
********************************************** */
unsigned char AT24C02_ReadOneData(u8 addr)
{
	u8 temp;
	IIC_Start();
	IIC_SendOneByte(AT24C02_WriteAddr);              //器件地址+写
	IIC_SendOneByte(addr);               
	
	IIC_Start();
	IIC_SendOneByte(AT24C02_ReadAddr);               //器件地址+读

	temp = IIC_ReceiveOneByte();
	IIC_Stop();
	return (temp);
}

主函数及相关显示函数

#include "IIC.h"

sbit LSA = P2^2;           //74LS138控制端口
sbit LSB = P2^3;
sbit LSC = P2^4;

sbit K1 = P3^1;
sbit K2 = P3^0;
sbit K3 = P3^2;
sbit K4 = P3^3;	 //定义按键端口

char WriteDat=0;
u8 Display[4];
u8 code SmgDuan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};


/* **********************************************
* 函数名称:Delay_MS(u16 ms)
* 入口参数:u16 ms
* 出口参数:无
* 函数功能: 不精确延时
********************************************** */
void Delay_MS(u16 ms)
{
	unsigned int i;
	do{
		i = Main_Fosc/13000;
		while(--i);
	}while(--ms);
}


/*******************************************************************************
* 函数名         :KeyScan(void)
* 函数功能		 :按键扫描函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Key_Scan(void)
{
	if(K1==0)
	{
		Delay_MS(10);  //延时消抖
		if(K1==0)
		{
			AT24C02_WriteOneData(1,WriteDat);   //在地址1内写入数据WriteDat
		}
		while(!K1);
	}
	if(K2==0)
	{
		Delay_MS(10);  //延时消抖
		if(K2==0)
		{
			WriteDat=AT24C02_ReadOneData(1);	  //读取EEPROM地址1内的数据保存在WriteDat中
		}
		while(!K2);
	}
	if(K3==0)
	{
		Delay_MS(10); //延时消抖
		if(K3==0)
		{
			WriteDat++;	   //数据加1
			if(WriteDat>255)WriteDat=0;
		}
		while(!K3);
	}
	if(K4==0)
	{
		Delay_MS(10); //延时消抖
		if(K4==0)
		{
			WriteDat=0;		 //数据清零
		}
		while(!K4);
	}		
}

/*******************************************************************************
* 函数名         :DataProcess()
* 函数功能		 :数据处理函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void DataProcess()
{
	Display[0]=SmgDuan[WriteDat/1000];//千位
	Display[1]=SmgDuan[WriteDat%1000/100];//百位
	Display[2]=SmgDuan[WriteDat%1000%100/10];//个位
	Display[3]=SmgDuan[WriteDat%1000%100%10];		
}


/*******************************************************************************
* 函数名         :SmgDisplay()
* 函数功能		 :数码管显示函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void SmgDisplay()
{
	u8 i;
	for(i=0;i<4;i++)
	{
		switch(i)	 //位选,选择点亮的数码管,
		{
			case(0):
				LSA=0;LSB=0;LSC=0; break;//显示第0位
			case(1):
				LSA=1;LSB=0;LSC=0; break;//显示第1位
			case(2):
				LSA=0;LSB=1;LSC=0; break;//显示第2位
			case(3):
				LSA=1;LSB=1;LSC=0; break;//显示第3位	
		}
		P0=Display[3-i];//发送数据
		Delay_MS(2); //间隔一段时间扫描,让数据送入	
		P0=0x00;//消隐
	}		
}

/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	
	while(1)
	{
		Key_Scan();	     //按键扫描函数
		DataProcess();	 //数据处理函数
		SmgDisplay();    //数码管显示函数		
	}		
}

加油!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值