【STM32F1例程8】EEPROM读写实验

引言

    好的,紧接着就又是一个新的实验,我也是想抓紧给大家分享完这几个基础实验之后,继续给大家介绍一些完整的项目,以及其他领域的项目。

    那么这个实验呢是关于EEPROM 的读写实验,STM32的EEPROM实验是指在STM32微控制器上使用内部的EEPROM(Electrically Erasable Programmable Read-Only Memory,电可擦除可编程只读存储器)进行实验。EEPROM是一种非易失性存储器,可以存储数据并在需要时进行读取和写入操作,而且数据在掉电情况下也能够保持。

实验准备

    仍然是不需要接线,下载程序,全速运行,在 Keil5 环境下全速运行,能看到 EEPROM 的 0 地址 EEDATA 这个变量值就是初始化时候写进 EEPROM 0 地址的值,说明 EEPROM 读写正常。

老样子,直接上代码!!!

24C08.C

#include "sys.h"  
#include "delay.h"

#define AT24C08_READ_ADDR  0xA1//读数据时的地址
#define AT24C08_WRITE_ADDR 0xA0//写数据时的地址
//IIC2初始化
void IIC_Init(void)
{
	
	I2C_InitTypeDef  I2C_InitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2|RCC_APB2Periph_AFIO,ENABLE);
	
	I2C_DeInit(I2C2);//使用I2C2
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStructure.I2C_OwnAddress1 = 0x30;//主机的I2C地址,随便写的
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_InitStructure.I2C_ClockSpeed = 100000;//100K
	I2C_Init(I2C2, &I2C_InitStructure);
	I2C_Cmd(I2C2,ENABLE);
}
/*
函数功能: 发送起始信号
当时钟线为高电平的时候,数据线由高电平变为低电平的过程
*/
void IIC_SendStart(void)
{
	I2C_GenerateSTART(I2C2,ENABLE);
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
  {  
		//可以加入超时退出机制		
  }
}
/*
函数功能: 停止信号
当时钟线为高电平的时候,数据线由低电平变为高电平的过程
*/
void IIC_SendStop(void)
{
	I2C_GenerateSTOP(I2C2,ENABLE);
	delay_ms(5);
}



void IIC_SendAddr(u8 addr)
{
	I2C_SendData(I2C2,addr);//发送数据(地址)
  while(!I2C_CheckEvent(I2C2, I2C_FLAG_ADDR&0xFFFFFF))//等待地址发送完成
  {  
		//可以加入超时退出机制		
  }
}
/*
函数功能: 发送数据
*/
void IIC_SendOneByte(u8 addr)
{
	I2C_SendData(I2C2,addr);//发送数据
  while(!I2C_CheckEvent(I2C2, I2C_FLAG_BTF&0xFFFFFF))//等待发送完成
  {  
		//可以加入超时退出机制		
  }

}
/*
函数功能: 接收一个字节数据
*/
u8 IIC_RecvOneByte(void)
{
	u8 data=0;
	I2C_AcknowledgeConfig(I2C2,ENABLE);//使能应答
	  while(!I2C_CheckEvent(I2C2, I2C_FLAG_RXNE&0xFFFFFF))//等待数据
  {  
		//可以加入超时退出机制		
  }
	data=I2C_ReceiveData(I2C2);//接收数据	
	I2C_AcknowledgeConfig(I2C2,DISABLE);//关闭应答使能
	return data;
}

/*
函数功能: 写一个字节
函数参数:
u8 addr 数据的位置(0~1023)
u8 data 数据范围(0~255)
*/
void AT24C08_WriteOneByte(u16 addr,u8 data)
{
	u8 read_device_addr=AT24C08_READ_ADDR;
	u8 write_device_addr=AT24C08_WRITE_ADDR;
	if(addr<256*1) //第一个块
	{
	write_device_addr|=0x0<<1;
	read_device_addr|=0x0<<1;
	}
	else if(addr<256*2) //第二个块
	{
	write_device_addr|=0x1<<1;
	read_device_addr|=0x1<<1;
	}
	else if(addr<256*3) //第三个块
	{
	write_device_addr|=0x2<<1;
	read_device_addr|=0x2<<1;
	}
	else if(addr<256*4) //第四个块
	{
	write_device_addr|=0x3<<1;
	read_device_addr|=0x3<<1;
	}
	addr=addr%256; //得到地址范围
	IIC_SendStart();//起始信号
	IIC_SendAddr(write_device_addr);//发送设备地址
	IIC_SendOneByte(addr); //数据存放的地址
	IIC_SendOneByte(data); //发送将要存放的数据
	IIC_SendStop(); //停止信号
	delay_ms(10); //等待写
}
/*
函数功能: 读一个字节
函数参数:
u8 addr 数据的位置(0~1023)
返回值: 读到的数据
*/
u8 AT24C08_ReadOneByte(u16 addr)
{
	u8 data=0;
	u8 read_device_addr=AT24C08_READ_ADDR;
	u8 write_device_addr=AT24C08_WRITE_ADDR;
	if(addr<256*1) //第一个块
	{
	write_device_addr|=0x0<<1;
	read_device_addr|=0x0<<1;
	}
	else if(addr<256*2) //第二个块
	{
	write_device_addr|=0x1<<1;
	read_device_addr|=0x1<<1;
	}
	else if(addr<256*3) //第三个块
	{
	write_device_addr|=0x2<<1;
	read_device_addr|=0x2<<1;
	}
	else if(addr<256*4) //第四个块
	{
	write_device_addr|=0x3<<1;
	read_device_addr|=0x3<<1;
	}
	addr=addr%256; //得到地址范围
	IIC_SendStart();//起始信号
	IIC_SendAddr(write_device_addr);//发送设备地址
	IIC_SendOneByte(addr); //将要读取数据的地址
	IIC_SendStart();//起始信号
	IIC_SendAddr(read_device_addr);//发送设备地址
	data=IIC_RecvOneByte();//读取数据
	IIC_SendStop(); //停止信号
	return data;
}
/*
函数功能: 从指定位置读取指定长度的数据
函数参数:
u16 addr 数据的位置(0~1023)
u16 len 读取的长度
u8 *buffer 存放读取的数据
返回值: 读到的数据
*/
void AT24C08_ReadByte(u16 addr,u16 len,u8 *buffer)
{
	u16 i=0;
	IIC_SendStart();//起始信号
	IIC_SendAddr(AT24C08_WRITE_ADDR);//发送设备地址
	IIC_SendOneByte(addr); //将要读取数据的地址
	IIC_SendStart();//起始信号
	IIC_SendAddr(AT24C08_READ_ADDR);//发送设备地址
	for(i=0;i<len;i++)
	{
	buffer[i]=IIC_RecvOneByte();//读取数据
	}
	IIC_SendStop(); //停止信号
}
/*
函数功能: AT24C08页写函数
函数参数:
u16 addr 写入的位置(0~1023)
u8 len 写入的长度(每页16字节)
u8 *buffer 存放读取的数据
*/
void AT24C08_PageWrite(u16 addr,u16 len,u8 *buffer)
{
	u16 i=0;
	IIC_SendStart();//起始信号
	IIC_SendAddr(AT24C08_WRITE_ADDR);//发送设备地址
	IIC_SendOneByte(addr); //数据存放的地址
	for(i=0;i<len;i++)
	{
	IIC_SendOneByte(buffer[i]); //发送将要存放的数据
	}
	IIC_SendStop(); //停止信号
	delay_ms(10); //等待写
	
}
/*
函数功能: 从指定位置写入指定长度的数据
函数参数:
u16 addr 数据的位置(0~1023)
u16 len 写入的长度
u8 *buffer 存放即将写入的数据
返回值: 读到的数据
*/
void AT24C08_WriteByte(u16 addr,u16 len,u8 *buffer)
{
		u8 page_byte=16-addr%16; //得到当前页剩余的字节数量
		if(page_byte>len) //判断当前页剩余的字节空间是否够写
		{
		page_byte=len; //表示一次性可以写完
		}
		while(1)
		{
			AT24C08_PageWrite(addr,page_byte,buffer); //写一页
			if(page_byte==len)break; //写完了
			buffer+=page_byte; //指针偏移
			addr+=page_byte;//地址偏移
			len-=page_byte;//得到剩余没有写完的长度
			if(len>16)page_byte=16;
			else page_byte=len; //一次可以写完
		}
}

24C08.H



/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32_EVAL_I2C_EE_H
#define __STM32_EVAL_I2C_EE_H
#include "sys.h"  
#ifdef __cplusplus
 extern "C" {
#endif

extern void IIC_Init(void);
extern void AT24C08_WriteOneByte(u16 addr,u8 data);
extern u8 AT24C08_ReadOneByte(u16 addr);
extern void AT24C08_WriteByte(u16 addr,u16 len,u8 *buffer);
extern void AT24C08_ReadByte(u16 addr,u16 len,u8 *buffer);


#ifdef __cplusplus
}
#endif

#endif /* __STM32_EVAL_I2C_EE_H */
/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */ 

/**
  * @}
  */

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

再给大家一个main.C

#include "delay.h"
#include "sys.h"
#include "24C08.h"


//IIC 初始化PB10,PB11
void GPIO_Config_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能端口时钟使能
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;				 //端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //AF功能
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化
}
uint8_t EEDATA;//单字节读写变量
uint8_t Sendbuff[17]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};//多字节写缓冲
uint8_t Recvbuff[17];//多字节读缓冲
//主函数,采用外部8M晶振,72M系统主频,可以在void SetSysClock(void)函数中选择主频率设置
int main(void)
 {	
	
	delay_init();	    	//延时函数初始化,通过Systick中断实现1ms延时功能  
	GPIO_Config_Init();	//初始化IIC的GPIO口PB10,PB11,开漏
	IIC_Init();//IIC初始化,配置速度为100K,I2C2
	AT24C08_WriteOneByte(0,0x33);//0地址写入0x33
	EEDATA= AT24C08_ReadOneByte(0);//从0地址读数据存到EEDATA
	//AT24C08_WriteByte(0,17,Sendbuff);多字节读写示列
	//AT24C08_ReadByte(0,17,Recvbuff);多字节读写示列
	while(1)
	{

	}
 }

代码的注释相对来说还是比较详细的,就不啰嗦的给大家介绍了!!!依旧是希望大家实验顺利哦。

  • 16
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值