STM32——AT24C02

2020-09-23 12:00:36

簡介

AT24C02是一個2K位序列CMOS E2PROM, 內部含有256個8位元位元組,CATALYST公司的先進CMOS技術實質上減少了器件的功耗。AT24C02有一個8位元組頁寫緩衝器。該器件通過IIC匯流排介面進行操作,有一個專門的防寫功能。

特點

與 400KHz I2C 匯流排相容 。
1.8 到 6.0 伏工作電壓範圍
低功耗 CMOS 技術
防寫功能 當 WP 為高電平時進入防寫狀態
頁寫緩衝器
自定時擦寫週期
1,000,000 程式設計/擦除週期
可儲存資料 100 年
8 腳 DIP SOIC 或 TSSOP 封裝
溫度範圍 商業級 工業級和汽車級

地址意義

在這裡插入圖片描述

時序圖

寫操作
在這裡插入圖片描述
讀操作(讀之前要進行一邊寫操作才能獲取地址)
在這裡插入圖片描述

程式碼

/*
引腳說明
SCL -- PB8
SDA -- PB9

*/

#define SCL  	PBout(8)
#define SDA_IN	PBin(9)
#define SDA_OUT	PBout(9)

void Iic_Init(void) //IIC引腳設定
{
	GPIO_InitTypeDef GPIO_InitStruct;  //結構體
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);	//使能GPIO B組時鐘

	GPIO_InitStruct.GPIO_Pin	= GPIO_Pin_8|GPIO_Pin_9;     	//引腳8 9
	GPIO_InitStruct.GPIO_Mode	= GPIO_Mode_OUT;	//輸出模式
	GPIO_InitStruct.GPIO_OType	= GPIO_OType_PP;    //輸出推輓
	GPIO_InitStruct.GPIO_PuPd	= GPIO_PuPd_UP;	    //上拉
	GPIO_InitStruct.GPIO_Speed	= GPIO_Speed_50MHz; //輸出速度
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
	//匯流排空閒
	SCL = 1;
	SDA_OUT = 1;

}

//引腳模式變更
void Iic_Sda_Mode(GPIOMode_TypeDef mode)
{
	GPIO_InitTypeDef  	GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;				//第9號引腳
	GPIO_InitStructure.GPIO_Mode  = mode;					//輸入/輸出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;			//推輓輸出,增強驅動能力,引腳的輸出電流更大
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//引腳的速度最大為100MHz
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;		//沒有使用內部上拉電阻
	GPIO_Init(GPIOB, &GPIO_InitStructure);	
}

//啟動訊號
void Iic_Start(void)
{
	Iic_Sda_Mode(GPIO_Mode_OUT);
	
	//匯流排空閒
	SCL = 1;
	SDA_OUT = 1;	
	delay_us(5);
	
	//啟動訊號
	SDA_OUT = 0;
    delay_us(5);	
	SCL = 0;

}

//停止訊號
void Iic_Stop(void)
{
	Iic_Sda_Mode(GPIO_Mode_OUT);	

	SCL = 0;
	SDA_OUT = 0;
	delay_us(5);
	
	SCL = 1;
	delay_us(5);
	SDA_OUT = 1;
	
}

//引腳傳送一位資料
void Iic_Send_Ack(u8 ack)
{
	Iic_Sda_Mode(GPIO_Mode_OUT);

	SCL = 0;
	
	/*準備資料*/
	
	//發資料1
	if(ack == 1)
	{
		SDA_OUT = 1;  //引腳輸出
	}
	//發資料0
	if(ack == 0)
	{
		SDA_OUT = 0; //引腳輸出
	}	
	
	delay_us(5);
	SCL = 1;
	delay_us(5);
	SCL = 0;
}


//引腳傳送一個位元組資料
void Iic_Send_Byte(u8 data)
{
	u8 i;
	Iic_Sda_Mode(GPIO_Mode_OUT);

	SCL = 0;
	
	//0 1 1 1 1 0 0 0
	for(i=0; i<8; i++)
	{
		/*準備資料*/
		
		//發資料1
		if(data &  (1<<(7-i)))
		{
			SDA_OUT = 1;  //引腳輸出
		}
		//發資料0
		else
		{
			SDA_OUT = 0; //引腳輸出
		}	
		
		delay_us(5);
		SCL = 1;
		delay_us(5);
		SCL = 0;
	}
}

//接受一位資料
u8 Iic_Rcv_Ack(void)
{
	u8 ack;
	
	Iic_Sda_Mode(GPIO_Mode_IN);

	
	SCL = 0;
	delay_us(5);
	SCL = 1;	
	delay_us(5);
	if(SDA_IN == 1)  //引腳為電平為1
	{
		ack = 1;
	}
	
	if(SDA_IN == 0)  //引腳為電平為1
	{
		ack = 0;
	}	
	
	SCL = 0;	

	return ack;
}

//接受一個位元組資料
u8 Iic_Rcv_Byte(void)
{
	u8 i, data = 0; //0 0 0 0 0 0 0 0   比如有資料:1 1 0 0 1 0 0 0 
	Iic_Sda_Mode(GPIO_Mode_IN);
	
	SCL = 0;
	
	//0 1 1 1 1 0 0 0
	for(i=0; i<8; i++)
	{

		delay_us(5);
		SCL = 1;
		delay_us(5);
		
	    //接受資料
		if(SDA_IN == 1)  //引腳為電平為1
		{
			data |= (1<<(7-i));
		}	
		SCL = 0;
	}
	return data;
}


void AT24c02_Write(u8 addr, u8 *write_buff, u8 len)
{
	u8 ack;
	
	//啟動訊號
	Iic_Start();
	
	//傳送裝置地址
	Iic_Send_Byte(0xA0);
	ack = Iic_Rcv_Ack();
	if(ack == 1)
	{
		printf("ack failure\n");
		return ;
	}
	
	//傳送寫資料起始地址
	Iic_Send_Byte(addr);
	ack = Iic_Rcv_Ack();
	if(ack == 1)
	{
		printf("ack failure\n");
		return ;
	}	
	
	//資料:hello
	while(len--)
	{
		//傳送資料
		Iic_Send_Byte(*write_buff);
		ack = Iic_Rcv_Ack();
		if(ack == 1)
		{
			printf("ack failure\n");
			return ;
		}	
	
		write_buff++;
	}
	
	Iic_Stop();
	printf("write finish\n");
}


void AT24c02_Read(u8 addr, u8 *read_buff, u8 len)
{
	u8 ack;
	
	//啟動訊號
	Iic_Start();
	
	//傳送裝置地址
	Iic_Send_Byte(0xA0);
	ack = Iic_Rcv_Ack();
	if(ack == 1)
	{
		printf("ack failure\n");
		return ;
	}
	
	//傳送寫資料起始地址
	Iic_Send_Byte(addr);
	ack = Iic_Rcv_Ack();
	if(ack == 1)
	{
		printf("ack failure\n");
		return ;
	}	
	
	//啟動訊號
	Iic_Start();
	
	//傳送裝置地址
	Iic_Send_Byte(0xA1);
	ack = Iic_Rcv_Ack();
	if(ack == 1)
	{
		printf("ack failure\n");
		return ;
	}	
	

	
	//資料:hello   5
	while(len--)
	{
		*read_buff = Iic_Rcv_Byte();
		
		if(len > 0)
			Iic_Send_Ack(0); //傳送有效應答
	
		read_buff++;
	}
	
	Iic_Send_Ack(1);
	Iic_Stop();
	printf("read finish\n");
}