蓝桥杯I2C使用EEPROM教程(内附初始值设定)

蓝桥杯I2C使用EEPROM教程(内附初始值设定)

  • 前言
    • I2C介绍
    • I2C初始化
    • 主函数实现

前言

	第一次写博客,请多指教。在经过一年多的STM32单片机的学习,
我决定参加蓝桥杯嵌入式赛,因为平时练手的使用的是STM32F103RCT6,
蓝桥杯的板子是RBT6的,所以差别不大,故选择参加了嵌入式赛,
前几天搞明白I2C,所以和大家分享一下。

I2C介绍

IIC(Inter-Integrated Circuit)总线是一种由 PHILIPS 公司开发的两线式串行总线,用于连接
微控制器及其外围设备。它是由数据线 SDA 和时钟 SCL 构成的串行总线,可发送和接收数据。
在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送,高速 IIC 总线一般可达 400kbps 以上。
I2C 总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答
信号。
开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,
表示已收到数据。CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU 接
收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为
受控单元出现故障。
这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。IIC 总线时序图如下图 所示:
蓝桥杯I2C使用EEPROM教程(内附初始值设定)_第1张图片

I2C初始化

void _24c02_write(u8 adress,u8 data)		//向EEPROM中写一个字节的数据
{
     
	I2CStart();
	
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(adress);
	I2CWaitAck();
	I2CSendByte(data);
	I2CWaitAck();
	
	I2CStop();
	
}

u8 _24c02_read(u8 adress)					//从EEPROM中读一个字节的数据存放在temp变量中
{
     
	u8 temp;
	
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(adress);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	temp=I2CReceiveByte();
	I2CWaitAck();
	I2CStop();
	
	return temp;
	
}

主函数实现

这里我们模拟一个简单的存取场景,我们任找一个地址如:0x11作为存储数据的地址,然后从0开始,每次我们按下开发板的复位键后都自加1,来实现I2C模拟EEPROM掉电保存数据的情形。
出现了一个问题:往往在存储数据的地址中一开始就有一个值,比如在烧录程序之前,可能0x11地址中的值为12,那么我们开始就只能从12开始加1,这样不符合我们的要求;而如果我们在程序的开头加上_24c02_Write(0x11,0);,那么这样相信大家也知道,每次启动程序,值都会变为0,这就查看不了我们的EEPROM的变化。所以我们引进另一个地址来进行解决

int main(void)
{
     
	uint8_t temp;
	uint8_t string[20];
	uint8_t str[20];
	
	//LCD工作模式配置
	STM3210B_LCD_Init();
	LCD_Clear(White);
	LCD_SetTextColor(White);
	LCD_SetBackColor(Blue);
   
	LCD_DisplayStringLine(Line1,"I2C DEMO    ");
	LCD_DisplayStringLine(Line3,"AT24C02 R/W ");

    SysTick_Config(SystemCoreClock/1000);  //1ms中断一次

	i2c_init();	
	if(_24c02_read(0x21)!=4)			//使用另一个地址作为第一次烧录的判断,
	{
     									//第一次执行这个条件,以后都不执行
		_24c02_write(0x21,4);
		Delay_Ms(2);
		_24c02_write(0x11,0);
		Delay_Ms(2);
	}
	temp = _24c02_read(0x11);
	Delay_Ms(2);
	_24c02_write(0x11,++temp);
	Delay_Ms(2);
	LCD_DisplayStringLine(Line6,"ADDR: 0x11");
	sprintf(string,"%s%d","VAL: ",temp); //写入缓冲区
	LCD_DisplayStringLine(Line7,string); //显示缓冲区
    while(1){
     }

这样我们的0x11就可以从0开始自加了。这个可以解决蓝桥杯比赛中的一个非常重要的问题:
我们在比赛的时候可能在现场的板子上已经设定的特别好,但是当评委组拿到你的.axf文件烧录时,他们不管你怎么设定,可能只会看第一次烧录后的结果,而如果那时你从I2C中读出的初始值是不确定的一个数,那么无论你设计的多好,这一块也会酌情扣分的。
这个问题确实困扰我很久,昨天解决了,所以想和大家分享一下。
第一次写博客,表达不是很流畅,欢迎大家批评指正。
如果觉得写得不错的话,点个关注哈。

本人还写了今年蓝桥杯嵌入式赛省赛模拟题链接:
第11届蓝桥杯嵌入式省赛模拟题代码
亲测有效!

你可能感兴趣的:(蓝桥杯,嵌入式,stm32,单片机,编程语言)