目录
说明
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的分享