16_AT24C02(I2C总线)

发布时间 2023-11-19 13:53:20作者: 爱吃冰激凌的黄某某

AT24C02(I2C总线)

存储器介绍

image-20231117105825624

存储器简化模型

image-20231117105857055

AT24C02介绍

image-20231117105408422

引脚及应用电路

image-20231117105955453

内部结构框图

image-20231117110020801

I2C总线介绍

image-20231117110040632

I2C电路规范

image-20231117112722856

弱上拉模式

image-20231117113126406

开漏输出模式

image-20231117113207680

I2C时序结构

image-20231117113729427

image-20231117113957153

image-20231118132221481

image-20231118132346442

I2C数据帧

image-20231118132819320

image-20231118134527785

image-20231118134844406

AT24C02数据帧

image-20231118151900348

image-20231118152336702

AT24C02数据存储

I2C.c

#include <REGX52.H>

sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;

/**
  * @brief I2C开始
  * @param 无
  * @retval 无
  */
void I2C_Start()
{
	I2C_SCL=1;
	I2C_SDA=1;
	I2C_SDA=0;
	I2C_SCL=0;
}

/**
  * @brief I2C结束
  * @param 无
  * @retval 无
  */
void I2C_Stop()
{
	I2C_SDA=0;
	I2C_SCL=1;
	I2C_SDA=1;
}

/**
  * @brief I2C发送一个字节
  * @param Byte 要发送的字节
  * @retval 无
  */
void I2C_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		I2C_SDA=Byte&(0x80>>i);
		I2C_SCL=1;
		I2C_SCL=0;
	}
}

/**
  * @brief I2C接收一个字节
  * @param 无
  * @retval 接收到的数据
  */
unsigned char I2C_ReceiveByte()
{
	unsigned char Byte=0x00,i;
	I2C_SDA=1; //接收之前,释放SDA
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;
		if(I2C_SDA)
		{
			Byte|=(0x80>>i);
		}
		I2C_SCL=0;
	}
	return Byte;
}

/**
  * @brief I2C发送应答
  * @param AckBit 应答位 0为应答 1为非应答
  * @retval 无
  */
void I2C_SendAck(bit AckBit)
{
	I2C_SDA=AckBit;
	I2C_SCL=1;
	I2C_SCL=0;
}

/**
  * @brief I2C接收应答
  * @param 无
  * @retval 接收到的应答 0为应答 1为非应答
  */
bit I2C_ReceiveAck()
{
	bit AckBit;
	I2C_SDA=1; //接收之前,释放SDA
	I2C_SCL=1;
	AckBit=I2C_SDA;
	I2C_SCL=0;
	return AckBit;
}

I2C.h

#ifndef __I2C_H__
#define __I2C_H__

void I2C_Start();
void I2C_Stop();
void I2C_SendByte(unsigned char Byte);
unsigned char I2C_ReceiveByte();
void I2C_SendAck(bit AckBit);
bit I2C_ReceiveAck();

#endif

AT24C02.c

#include <REGX52.H>
#include "I2C.h"

#define AT24C02_ADDRESS 0xA0

/**
  * @brief AT24C02写入一个字节
  * @param WordAddress 字节的地址
  * @param Data 要写入的数据
  * @retval 无
  */
void AT24C02_WriteByte(unsigned char WordAddress, Data)
{
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_SendByte(Data);
	I2C_ReceiveAck();
	I2C_Stop();
}

/**
  * @brief AT24C02读取一个字节
  * @param WordAddress 字节的地址
  * @retval 读取到的数据
  */
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
	unsigned char Data;
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS|0x01);
	I2C_ReceiveAck();
	Data=I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	return Data;
}

AT24C02.h

#ifndef __AT24C02_H__
#define __AT24C02_H__

void AT24C02_WriteByte(unsigned char WordAddress, Data);

unsigned char AT24C02_ReadByte(unsigned char WordAddress);

#endif

main.c

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "Key.h"
#include "AT24C02.h"

unsigned char KeyNum;
unsigned int Num;

void main()
{
	LCD_Init();
	LCD_ShowNum(1,1,Num,5);
	while(1)
	{
		KeyNum=Key();
		switch(KeyNum)
		{
			case 1:Num++;LCD_ShowNum(1,1,Num,5);break;
			case 2:Num--;LCD_ShowNum(1,1,Num,5);break;
			case 3:
				AT24C02_WriteByte(0,Num%256);
				Delay(5);
				AT24C02_WriteByte(1,Num/256);
				Delay(5);
				LCD_ShowString(2,1,"Write OK");
				Delay(1000);
				LCD_ShowString(2,1,"           ");
				break;
			case 4:
				Num=AT24C02_ReadByte(0);
				Num|=AT24C02_ReadByte(1)<<8;
				LCD_ShowNum(1,1,Num,5);
				LCD_ShowString(2,1,"Read OK");
				Delay(1000);
				LCD_ShowString(2,1,"           ");
				break;
		}
	}
}

显示效果

![VID_20231118_193507 (2)](H:\通讯软件\QQSave\1607442148\FileRecv\MobileFile\VID_20231118_193507 (2).gif)

动态数码管显示秒表,使用AT24C02进行存储,定时器进行延时,不阻塞主函数

Key.c

#include <REGX52.H>
#include "Delay.h"

unsigned char Key_KeyNumber;

unsigned char Key()
{
	unsigned char Temp;
	Temp=Key_KeyNumber;
	Key_KeyNumber=0;
	return Temp;
}

unsigned char Key_GetState()
{
	unsigned char KeyNumber=0;
	if(P3_1==0){KeyNumber=1;}
	if(P3_0==0){KeyNumber=2;}
	if(P3_2==0){KeyNumber=3;}
	if(P3_3==0){KeyNumber=4;}
	return KeyNumber;
}

void Key_Loop()
{
	static unsigned char NowState,LastState;
	LastState=NowState;
	NowState=Key_GetState();
	
	if(NowState==0)
	{
		switch(LastState) //按下后松手
		{
			case 1:Key_KeyNumber=1;break;
			case 2:Key_KeyNumber=2;break;
			case 3:Key_KeyNumber=3;break;
			case 4:Key_KeyNumber=4;break;
		}
	}
}

Key.h

#ifndef __KEY_H__
#define __KEY_H__


unsigned char Key();
unsigned char Key_GetState();
void Key_Loop();

#endif

Nixie.c

#include <REGX52.H>
#include "Delay.h"

unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40};

unsigned char Nixie_Buf[9]={0,10,10,10,10,10,10,10,10};

void Nixie_SetBuf(unsigned char Location,Number)
{
	Nixie_Buf[Location]=Number;
}

void Nixie_Scan(unsigned char Location,Number)
{
	P0=0x00; //消影
	switch(Location)
	{
		case 1:P2_4=1;P2_3=1;P2_2=1;break;
		case 2:P2_4=1;P2_3=1;P2_2=0;break;
		case 3:P2_4=1;P2_3=0;P2_2=1;break;
		case 4:P2_4=1;P2_3=0;P2_2=0;break;
		case 5:P2_4=0;P2_3=1;P2_2=1;break;
		case 6:P2_4=0;P2_3=1;P2_2=0;break;
		case 7:P2_4=0;P2_3=0;P2_2=1;break;
		case 8:P2_4=0;P2_3=0;P2_2=0;break;
	}
	P0=NixieTable[Number];
	
}

void Nixie_Loop()
{
	static unsigned char i=1;
	Nixie_Scan(i,Nixie_Buf[i]);
	i++;
	if(i>=9)
	{
		i=1;
	}
}

Nixie.h

#ifndef __NIXIE_H__
#define __NIXIE_H__

void Nixie_SetBuf(unsigned char Location,Number);
void Nixie_Scan(unsigned char Location,Number);
void Nixie_Loop();

#endif

main.c

#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include "Delay.h"
#include "Nixie.h"
#include "AT24C02.h"

unsigned char KeyNum;
unsigned char Min,Sec,MinSec;
unsigned char RunFlag;

void main()
{
	Timer0_Init();
	while(1)
	{
		KeyNum=Key();
		switch(KeyNum)
		{
			case 1:RunFlag=!RunFlag;break;
			case 2:Min=0;Sec=0;MinSec=0;break;
			case 3:
				AT24C02_WriteByte(0,Min);
				Delay(5);
				AT24C02_WriteByte(1,Sec);
				Delay(5);
				AT24C02_WriteByte(2,MinSec);
				Delay(5);
				break;
			case 4:
				Min=AT24C02_ReadByte(0);
				Sec=AT24C02_ReadByte(1);
				MinSec=AT24C02_ReadByte(2);
				break;
		}
		Nixie_SetBuf(1,Min/10);
		Nixie_SetBuf(2,Min%10);
		Nixie_SetBuf(3,11);
		Nixie_SetBuf(4,Sec/10);
		Nixie_SetBuf(5,Sec%10);
		Nixie_SetBuf(6,11);
		Nixie_SetBuf(7,MinSec/10);
		Nixie_SetBuf(8,MinSec%10);
	}
}

void Sec_Loop()
{
	if(RunFlag)
	{
		MinSec++;
		if(MinSec>=100)
		{
			MinSec=0;
			Sec++;
			if(Sec>=60)
			{
				Sec=0;
				Min++;
				if(Min>=60)
				{
					Min=0;
				}
			}
		}
	}
}

void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count1,T0Count2,T0Count3;
	TL0 = 0x18;
	TH0 = 0xFC;
	T0Count1++;
	if(T0Count1>=20)
	{
		T0Count1=0;
		Key_Loop();
	}
	T0Count2++;
	if(T0Count2>=1)
	{
		T0Count2=0;
		Nixie_Loop();
	}
	T0Count3++;
	if(T0Count3>=10)
	{
		T0Count3=0;
		Sec_Loop();
	}
}

运行效果

![VID_20231119_134042 (2)](H:\通讯软件\QQSave\1607442148\FileRecv\MobileFile\VID_20231119_134042 (2).gif)