AT24C02(I2C)总线

AT24C02介绍

AT24C02(I2C)总线_第1张图片

AT24C02(I2C)总线_第2张图片

AT24C02(I2C)总线_第3张图片

AT24C02(I2C)总线_第4张图片

AT24C02(I2C)总线_第5张图片

AT24C02(I2C)总线_第6张图片

AT24C02(I2C)总线_第7张图片

AT24C02(I2C)总线_第8张图片

I^C总线

I2C(Inter-Integrated Circuit)是一种串行通信总线协议,用于在集成电路之间进行通信。AT24C02是一种基于I2C总线的串行EEPROM(Electrically Erasable Programmable Read-Only Memory)存储器芯片。

AT24C02具有2K位(256字节)的容量,可以通过I2C总线与微控制器或其他设备进行通信。它可以存储数据,并且支持通过I2C总线进行读取和写入操作。AT24C02通常用于存储设备配置数据、校准值、日志数据等。

使用AT24C02芯片时,需要连接到微控制器或其他主设备的I2C总线上,并通过I2C协议进行读写操作。这种芯片在嵌入式系统和各种电子设备中广泛应用。

AT24C02(I2C)总线_第9张图片

电路规范

AT24C02(I2C)总线_第10张图片

I^c时序结构 :这个很重要后面写程序需要参考

AT24C02(I2C)总线_第11张图片

AT24C02(I2C)总线_第12张图片

AT24C02(I2C)总线_第13张图片

AT24C02(I2C)总线_第14张图片

数据帧:数据的接收和回应

AT24C02(I2C)总线_第15张图片

复合格式的数据帧

AT24C02(I2C)总线_第16张图片

AT24C02(I2C)总线_第17张图片

AT24C02(I2C)总线_第18张图片

AT24C02(I2C)总线_第19张图片

以上是相关理论知识准备:接下来使用程序对AT24C02进行程序实现

该程序使用到的c语言文件有Delay,LCD1602,AT24C02,I2C以及各自的头文件

AT24C02(I2C)总线_第20张图片
step1:延时函数头文件

AT24C02(I2C)总线_第21张图片

#ifndef __DELAY_H_
#define __DELAY_H_

// 编写函数函数声明需要的代码
void Delay(unsigned int xms);

#endif

延时函数c语言文件

AT24C02(I2C)总线_第22张图片

延时函数具体程序代码

// 实现函数的功能
void Delay(unsigned int xms){
	unsigned char i ,j;
	while(xms --){
	   i = 2;
		 j = 239;
		 do{
			 while(j --);
			}while(-- i);
	}
   
}

step2:LCD1602头文件以及程序实现代码

LCD1602头文件

AT24C02(I2C)总线_第23张图片

LCD1602头文件具体代码

#ifndef __LCD1602_H__
#define __LCD1602_H__

//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

LCD1602c语言程序

#include 
#include 
#include 

//引脚配置:
sbit LCD_RS=P3^5;
sbit LCD_RW=P3^6;
sbit LCD_EN=P3^4;
#define LCD_DataPort P0

//函数定义:
/**
  * @brief  LCD1602延时函数,12MHz调用可延时1ms
  * @param  无
  * @retval 无
  */
void LCD_Delay()
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
	LCD_SetCursor(Line,Column);
	if(Number>=0)
	{
		LCD_WriteData('+');
		Number1=Number;
	}
	else
	{
		LCD_WriteData('-');
		Number1=-Number;
	}
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i,SingleNumber;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		SingleNumber=Number/LCD_Pow(16,i-1)%16;
		if(SingleNumber<10)
		{
			LCD_WriteData(SingleNumber+'0');
		}
		else
		{
			LCD_WriteData(SingleNumber-10+'A');
		}
	}
}

/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
	}
}

独立键盘实现头文件以及代码key.h

#ifndef __KEY_H__
#define __KEY_H__

unsigned char Key();

#endif

独立键盘实现头文件以及代码key.c

#include 
#include "Delay.h"

/**
  * @brief  获取独立按键键码
  * @param  无
  * @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
  */
unsigned char Key()
{
	unsigned char KeyNumber=0;
	
	if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
	if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
	if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
	if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
	
	return KeyNumber;
}

AT24C02程序头文件

#ifndef  __AT24C02_H_
#define  __AT24C02_H_
void AT24C02_WriteByte(unsigned char WordAddress,Data);
unsigned char AT24C02_ReadByte(unsigned char WordAddress);

#endif

AT24C02程序实现文件

#include 
#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 要读出字节地址
	@param  Data 要读出的数据
  @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;
}

I2C头文件代码

#ifndef  __I2C_H_
#define  __I2C_H_
void I2C_Start(void);
void I2C_Stop(void);
void I2C_SendByte(unsigned char Byte);
unsigned char I2C_ReceiveByte(void);
void I2C_SendAck(unsigned char AckBit);
unsigned char I2C_ReceiveAck(void);
#endif

I2C程序实现代码

AT24C02(I2C)总线_第24张图片

AT24C02(I2C)总线_第25张图片

AT24C02(I2C)总线_第26张图片

......

I2C的具体代码

#include 
// 单片机引脚的位定义
sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;


void I2C_Start(void){
    I2C_SDA = 1;
		I2C_SCL = 1;
	  I2C_SDA = 0;
		I2C_SCL = 0;
}
void I2C_Stop(void){
    I2C_SDA = 0;
		I2C_SCL = 1;
	  I2C_SDA = 1;
}
/*
  @brief  I2C  发送一个字节
  @param  Byte 要发送的字节
  @retval 无   没有返回值
*/
void I2C_SendByte(unsigned char Byte){
	  unsigned char i;
	  // 一个字节是8位所以需要使用for循环循环8次,每次循环按位右移一次
	  for(i = 0; i< 8; i++){
		    I2C_SDA = Byte&0x80 >> i;//10000000
				I2C_SCL = 1;
				I2C_SCL = 0;
		}

}
/*
  @brief  I2C  接收一个字节
  @param  无
  @retval 接收到一个字节的数据
*/
unsigned char I2C_ReceiveByte(void){
    unsigned char Byte = 0x00,i;
	  I2C_SDA = 1;
	  for(i = 0; i < 8; i++){
				I2C_SCL = 1;
				if(I2C_SDA){
					 Byte |= (0X80>>i);//1000 0000
				}
				I2C_SCL = 0;
		}
		return Byte;
}
/*
  @brief  I2C    发送应答
  @param  AckBit 应答位0为应答1为不应答
  @retval 无     没有返回值
*/
void I2C_SendAck(unsigned char AckBit){
    I2C_SDA = AckBit;
	  I2C_SCL = 1;
	  I2C_SCL = 0;
}
/*
  @brief  I2C    接收应答
  @param  没有参数
  @retval 接收到的应答位
*/
unsigned char I2C_ReceiveAck(void){
       unsigned char AckBit = 0;
	     I2C_SDA = 1;
	     I2C_SCL = 1;
	     if(I2C_SDA){
			    AckBit = 1 ;
			 }
			 I2C_SCL = 0;
	     return AckBit;
}






 main函数文件测试程序是否能够正确的发送和接收数据

#include 
#include "LCD1602.H"
#include "Delay.h"
#include "AT24C02.H"
unsigned char Data;


unsigned char KeyNum;
unsigned int Num;

int main(){
  LCD_Init();
  LCD_ShowNum(1,1,Num,5);
	
	
//	// 第一位指定的是地址,第二位指定的是数据
//  AT24C02_WriteByte(1,147);
//	// 每次写完需要延迟一次,不然会报错
//	Delay(5);
//	Data = AT24C02_ReadByte(1);
//	LCD_ShowNum(2,1,Data,3);
		while(1){
		   KeyNum = Key();
			 if(KeyNum == 1){
			    Num++;
				  LCD_ShowNum(1,1,Num,5);
				 
			 }
			 if(KeyNum == 2){
			    Num--;
				  LCD_ShowNum(1,1,Num,5);
				 
			 }
		   if(KeyNum == 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,"        ");
			 }
			 if(KeyNum == 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,"        ");
			 }
		 }

}

你可能感兴趣的:(单片机,嵌入式硬件)