【STM32】STM32硬件IIC读写FT24C256(EEPROM设备)

目录

说明

 代码

 百度网盘链接


说明

1,FT24C256的寄存器地址范围

FT24C256的命名方式FT24C代表系列,256代表容量256Kb

256*1024bit=256*126Byte,一个Byte(字节)使用一个地址,所以FT24C256的寄存器地址范围是0 - 256*128-1(虽然15位二进制数就足以表示,但是实际使用的寄存器地址是16位,最高一位始终为0)

2,IIC通信中一般寄存器地址都是8位的,IIC只需要发送一次,而FT24C256的寄存器地址是16位的,我们需要发两次,第一次发地址的高八位,然后发地址的低八位

下面是IIC读写FT24C256的帧数据格式

3,FT24C256的从设备地址

FT24C256的设备地址为8位,前四位(1010)是固定的,A2,A1,A0与外部电路有关,接高电平时为1,低电平为0,最后一位R/W是读写位读操作时为0,写操作时为1.

4,EEPROM第一次的读/写之后,需要判断从设备自己的时序是否完成,否则EEPROM会卡死在第二次的读/写的EV6应答(野火对这点讲的比较清楚P51集49分钟)

我是直接进行了5ms的延时,也是可以第二次的读写操作的https://www.bilibili.com/video/BV1yW411Y7Gw?vd_source=373bb93339d994997b138e94de186abb

 代码

FT24C256.c

#include "stm32f10x.h"                  // Device header
#include "FT24C256.h"
#define FT24C256_ADDRESS		0xA0		//AT24C256的I2C从机地址

/**
  * 函    数:FT24C256等待事件
  * 参    数:同I2C_CheckEvent
  * 返 回 值:无
  */
void FT24C256_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
	uint32_t Timeout;
	Timeout = 10000;									//给定超时计数时间
	while (I2C_CheckEvent(I2Cx, I2C_EVENT) != SUCCESS)	//循环等待指定事件,ST有自己的ACK响应函数
	{
		Timeout --;										//等待时,计数值自减
		if (Timeout == 0)								//自减到0后,等待超时
		{
			/*超时的错误处理代码,可以添加到此处*/
			break;										//跳出等待,不等了
		}
	}
}

/**
  * 函    数:写AT24C256寄存器
  * 参    数:RegAddress 寄存器地址,范围:0-(32768-1)
  * 参    数:Data 要写入寄存器的数据,范围:0x00~0xFF
  * 返 回 值:无
  */
void FT24C256_WriteReg(uint16_t RegAddress, uint8_t Data)
{
	I2C_GenerateSTART(I2C2, ENABLE);										//硬件I2C生成起始条件
	
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);					//等待EV5

	I2C_Send7bitAddress(I2C2, FT24C256_ADDRESS, I2C_Direction_Transmitter);	//硬件I2C发送从机地址,方向为发送
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);	//等待EV6

	I2C_SendData(I2C2, (uint8_t)(RegAddress>>8));											//硬件I2C发送寄存器地址
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);			//等待EV8

	I2C_SendData(I2C2, (uint8_t)(RegAddress));											//硬件I2C发送寄存器地址
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);			//等待EV8
	
	I2C_SendData(I2C2, Data);												//硬件I2C发送数据
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);				//等待EV8_2
	
	I2C_GenerateSTOP(I2C2, ENABLE);											//硬件I2C生成终止条件
}

/**
  * 函    数:读AT24C256寄存器
  * 参    数:RegAddress 寄存器地址,范围:0-(32768-1)
  * 返 回 值:读取寄存器的数据,范围:0x00~0xFF
  */
uint8_t FT24C256_ReadReg(uint16_t RegAddress)
{
	uint8_t Data;
	
	I2C_GenerateSTART(I2C2, ENABLE);										//硬件I2C生成起始条件
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);					//等待EV5

	I2C_Send7bitAddress(I2C2, FT24C256_ADDRESS, I2C_Direction_Transmitter);	//硬件I2C发送从机地址,方向为发送
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);	//等待EV6

	I2C_SendData(I2C2, (uint8_t)(RegAddress>>8));											//硬件I2C发送从机寄存器地址
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);				//等待EV8_2
	
	I2C_SendData(I2C2, (uint8_t)(RegAddress));											//硬件I2C发送从机寄存器地址
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);				//等待EV8_2
	
	I2C_GenerateSTART(I2C2, ENABLE);										//硬件I2C生成重复起始条件
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);					//等待EV5
	
	I2C_Send7bitAddress(I2C2, FT24C256_ADDRESS, I2C_Direction_Receiver);		//硬件I2C发送从机地址,方向为接收
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);		//等待EV6
	
	I2C_AcknowledgeConfig(I2C2, DISABLE);									//在接收最后一个字节之前提前将应答失能
	
	
	FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED);				//等待EV7
	Data = I2C_ReceiveData(I2C2);											//接收数据寄存器
	
	I2C_GenerateSTOP(I2C2, ENABLE);											//在接收最后一个字节之前提前申请停止条件
	I2C_AcknowledgeConfig(I2C2, ENABLE);									//将应答恢复为使能,为了不影响后续可能产生的读取多字节操作
	
	return Data;
}

/**
  * 函    数:AT24C256初始化
  * 参    数:无
  * 返 回 值:无
  */
void FT24C256_Init(void)
{
	/*开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);		//开启I2C2的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//开启GPIOB的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);					//将PB10和PB11引脚初始化为复用开漏输出
	
	/*I2C初始化*/
	I2C_InitTypeDef I2C_InitStructure;						//定义结构体变量
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;				//模式,选择为I2C模式
	I2C_InitStructure.I2C_ClockSpeed = 50000;				//时钟速度,选择为50KHz
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;		//时钟占空比,选择Tlow/Thigh = 2
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;				//应答,选择使能
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;	//应答地址,选择7位,从机模式下才有效
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;				//自身地址,从机模式下才有效
	I2C_Init(I2C2, &I2C_InitStructure);						//将结构体变量交给I2C_Init,配置I2C2
	
	/*I2C使能*/
	I2C_Cmd(I2C2, ENABLE);									//使能I2C2,开始运行
  }
/**
  * 函    数:等待EEPROM内部写时序完成,不等待的话再次读写EEPROM的话会卡死在EV6事件中
  * 参    数:无
  * 返 回 值:无
  */
void FT24C256_WaitWriteEnd(void)
{
	do{
  I2C_GenerateSTART(I2C2, ENABLE);										//硬件I2C生成起始条件
	//FT24C256_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);					//等待EV5
  while(I2C_GetFlagStatus(I2C2,I2C_FLAG_SB)==RESET);
	I2C_Send7bitAddress(I2C2, FT24C256_ADDRESS, I2C_Direction_Transmitter);	//硬件I2C发送从机地址,方向为发送
	}while(I2C_GetFlagStatus(I2C2,I2C_FLAG_ADDR)==RESET);
	
	I2C_GenerateSTOP(I2C2, ENABLE);//内部时序完成传输
}

FT24C256.h 

#ifndef __FT24C256_H
#define __FT24C256_H

void FT24C256_WriteReg(uint16_t RegAddress, uint8_t Data);
uint8_t FT24C256_ReadReg(uint16_t RegAddress);
void FT24C256_Init(void);
void FT24C256_WaitWriteEnd(void);


#endif

 main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "usart.h"
#include "FT24C256.h"

int main(void)
{
	
	int Data=0;
	FT24C256_Init();		//AT24C256初始化
	uart_init(9600);

	printf("%d",Data);
	FT24C256_WriteReg(13,31);//往寄存器地址11(十进制)写入数据58
	printf("%d",Data);
	Delay_ms(5);
	Data = FT24C256_ReadReg(13);//读寄存器地址11的数据
	printf("%d",Data);
	
	while (1)
	{
	}
}

 百度网盘工程链接

http://链接:https://pan.baidu.com/s/1qYsV2S9rPQD_9E1AHvAB8A?pwd=1524  提取码:1524  --来自百度网盘超级会员V1的分享

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值