【藍橋杯嵌入式】5_IIC&EEPROM

1、原理圖

順便指出了該器件的地址。
在這裏插入圖片描述
24C02是2Kbits容量,一共256字節,所以可尋址範圍是0x00~0xFF

2、源代碼

實驗:實現每重啓一次Data數據+1

讀代碼指令:
在這裏插入圖片描述
使用了官方提供的IO口模擬IIC時序代碼(或許我們可以利用這些代碼的初始化部分讓自己在賽場上快速初始化IO)。
main.c:

#include "HeadFile.h"

//Main Body
int main(void)
{
	u8 Str[20];
	u8 Dat = 0;
	
	
	SysTick_Config(SystemCoreClock/1000);//DelayInit
	LEDInit();
	IICInit();
	Delay_Ms(200);
	
	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	
	Dat = EERead(0x01);
	sprintf((char *)Str,"Data = %d",Dat);
	EEWrite(0x01, (++Dat));
	
	LCD_DisplayStringLine(Line5,Str);
	while(1);
}


IIC.h:

#ifndef IIC_H_
#define IIC_H_

void IICInit(void);
void delay1(unsigned int n);

void I2CStart(void);
void I2CStop(void);
void I2CSendAck(void);
void I2CSendNotAck(void);
unsigned char I2CWaitAck(void);

void I2CSendByte(unsigned char cSendByte);
unsigned char I2CReceiveByte(void);

//For EEPROM
void EEWrite(u8 Addr,u8 Dat);
u8	 EERead(u8 Addr);

#endif

IIC.c:

#include "HeadFile.h"


/** I2C 總線接口 */
#define I2C_PORT GPIOB
#define SDA_Pin	GPIO_Pin_7
#define SCL_Pin GPIO_Pin_6

#define FAILURE 0
#define SUCCESS 1

//配置SDA信號線爲輸入模式
void SDA_Input_Mode()
{
	GPIO_InitTypeDef GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Pin = SDA_Pin;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;	 

	GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}

//配置SDA信號線爲輸出模式
void SDA_Output_Mode()
{
	GPIO_InitTypeDef GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Pin = SDA_Pin;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

	GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}

//
void SDA_Output( uint16_t val )
{
	if ( val ) {
		GPIO_SetBits(I2C_PORT,SDA_Pin);
	} else {
		GPIO_ResetBits(I2C_PORT,SDA_Pin);
	}
}

//
void SCL_Output( uint16_t val )
{
	if ( val ) {
		GPIO_SetBits(I2C_PORT,SCL_Pin);
	} else {
		GPIO_ResetBits(I2C_PORT,SCL_Pin);
	}
}

//
uint8_t SDA_Input()
{
	return GPIO_ReadInputDataBit( I2C_PORT, SDA_Pin);
}

//延時程序
void delay1(unsigned int n)
{
	unsigned int i;
	for ( i=0;i<n;++i);
}

//I2C總線啓動
void I2CStart(void)
{
	SDA_Output(1);delay1(500);
	SCL_Output(1);delay1(500);
	SDA_Output(0);delay1(500);
	SCL_Output(0);delay1(500);
}

//I2C總線停止
void I2CStop(void)
{
	SCL_Output(0); delay1(500);
	SDA_Output(0); delay1(500);
	SCL_Output(1); delay1(500);
	SDA_Output(1); delay1(500);

}

//等待應答
unsigned char I2CWaitAck(void)
{
	unsigned short cErrTime = 5;
	SDA_Input_Mode(); 
	delay1(500);
	SCL_Output(1);delay1(500);
	while(SDA_Input())
	{
		cErrTime--;
		delay1(500);
		if (0 == cErrTime)
		{
			SDA_Output_Mode();
			I2CStop();
			return FAILURE;
		}
	}
	SDA_Output_Mode();
	SCL_Output(0);delay1(500); 
	return SUCCESS;
}

//發送應答位
void I2CSendAck(void)
{
	SDA_Output(0);delay1(500);
	delay1(500);
	SCL_Output(1); delay1(500);
	SCL_Output(0); delay1(500);

}

//
void I2CSendNotAck(void)
{
	SDA_Output(1);
	delay1(500);
	SCL_Output(1); delay1(500);
	SCL_Output(0); delay1(500);

}

//通過I2C總線發送一個字節數據
void I2CSendByte(unsigned char cSendByte)
{
	unsigned char  i = 8;
	while (i--)
	{
		SCL_Output(0);delay1(500); 
		SDA_Output(cSendByte & 0x80); delay1(500);
		cSendByte += cSendByte;
		delay1(500); 
		SCL_Output(1);delay1(500); 
	}
	SCL_Output(0);delay1(500); 
}

//從I2C總線接收一個字節數據
unsigned char I2CReceiveByte(void)
{
	unsigned char i = 8;
	unsigned char cR_Byte = 0;
	SDA_Input_Mode(); 
	while (i--)
	{
		cR_Byte += cR_Byte;
		SCL_Output(0);delay1(500); 
		delay1(500); 
		SCL_Output(1);delay1(500); 
		cR_Byte |=  SDA_Input(); 
	}
	SCL_Output(0);delay1(500); 
	SDA_Output_Mode();
	return cR_Byte;
}

//I2C總線初始化
void IICInit()
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

	GPIO_InitStructure.GPIO_Pin = SDA_Pin | SCL_Pin;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	 // **

  	GPIO_Init(I2C_PORT, &GPIO_InitStructure);

}

//For EEPROM

void EEWrite(u8 Addr,u8 Dat)
{
	I2CStart();
	I2CSendByte(0xA0);//器件地址
	I2CWaitAck();
	I2CSendByte(Addr);//內存地址
	I2CWaitAck();
	I2CSendByte(Dat);
	I2CWaitAck();
	I2CStop();
	
}

u8 EERead(u8 Addr)
{
	u8 temp = 0;
	
	I2CStart();
	I2CSendByte(0xA0);//器件地址
	I2CWaitAck();
	I2CSendByte(Addr);//內存地址
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xA1);//發送讀指令
	I2CWaitAck();
	temp = I2CReceiveByte();
	I2CSendNotAck();
	I2CStop();
	
	return temp;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章