#include "main.h"
#include "fm24c128a.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#define FM24C128A_CLK RCU_GPIOD
#define FM24C128A_SCL_GPIO_Port GPIOD
#define FM24C128A_SCL_Pin GPIO_PIN_0
#define FM24C128A_SDA_GPIO_Port GPIOD
#define FM24C128A_SDA_Pin GPIO_PIN_1
#define SCL_L gpio_bit_reset(FM24C128A_SCL_GPIO_Port, FM24C128A_SCL_Pin)
#define SCL_H gpio_bit_set(FM24C128A_SCL_GPIO_Port, FM24C128A_SCL_Pin)
#define SDA_L gpio_bit_reset(FM24C128A_SDA_GPIO_Port, FM24C128A_SDA_Pin)
#define SDA_H gpio_bit_set(FM24C128A_SDA_GPIO_Port, FM24C128A_SDA_Pin)
#define SDA_IN gpio_mode_set(FM24C128A_SDA_GPIO_Port, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, FM24C128A_SDA_Pin)
#define SDA_OUT gpio_mode_set(FM24C128A_SDA_GPIO_Port, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, FM24C128A_SDA_Pin)
#define SDA_READ gpio_input_bit_get(FM24C128A_SDA_GPIO_Port,FM24C128A_SDA_Pin)
//FM24C128C organized as 256 pages of 64-bytes each
#define PAGE_SIZE 64
void fm24c128a_config(void)
{
rcu_periph_clock_enable(FM24C128A_CLK);
/*sdl*/
gpio_mode_set(FM24C128A_SCL_GPIO_Port, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, FM24C128A_SCL_Pin);
gpio_output_options_set(FM24C128A_SCL_GPIO_Port, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,FM24C128A_SCL_Pin);
/*sda*/
gpio_mode_set(FM24C128A_SDA_GPIO_Port, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, FM24C128A_SDA_Pin);
gpio_output_options_set(FM24C128A_SDA_GPIO_Port, GPIO_OTYPE_OD, GPIO_OSPEED_200MHZ,FM24C128A_SDA_Pin);
SCL_H;
SDA_H;
}
// SDA
/***********************iic**************************/
static void delay_nop(void)
{
unsigned int i;
for(i=0;i<50;i++)
__nop();
}
//产生IIC起始信号
static void IIC_Start(void)
{
SDA_OUT;//sda线输出
SDA_H;
SCL_H;
delay_nop();
SDA_L;//START:when CLK is high,DATA change form high to low
delay_nop();
SCL_L;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
static void IIC_Stop(void)
{
SDA_L;
SDA_OUT;//sda线输出
SCL_L;
delay_nop();
SCL_H;
delay_nop();
SDA_H;//发送I2C总线结束信号
delay_nop();
}
//等待应答信号到来
//返回值:
// 1,接收应答失败
// 0,接收应答成功
static uint8_t IIC_Wait_Ack(void)
{
uint8_t flag;
SDA_IN; //SDA设置为输入
SDA_H;
delay_nop();
SCL_H;
delay_nop();
if(SDA_READ)
flag=1;
else
flag=0;
SCL_L; //时钟输出0
return flag;
}
//产生ACK应答
static void IIC_Ack(void)
{
SCL_L;
SDA_OUT;
SDA_L;
delay_nop();
SCL_H;
delay_nop();
SCL_L;
}
//不产生ACK应答
static void IIC_NAck(void)
{
SCL_L;
SDA_OUT;
SDA_H;
delay_nop();
SCL_H;
delay_nop();
SCL_L;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
static void IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
SDA_OUT;
SCL_L;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
if((txd&0x80)>>7)
SDA_H;
else SDA_L;
txd<<=1;
delay_nop();
SCL_H;
delay_nop();
SCL_L;
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
static uint8_t IIC_Read_Byte(uint8_t ack)
{
uint8_t i,receive=0;
SDA_IN;
for(i=0;i<8;i++ )
{
SCL_L;
delay_nop();
SCL_H;
delay_nop();
receive<<=1;
if(SDA_READ)
receive++;
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
/***********************iic**************************/
//在FM24CXX指定地址读出一个数据
//ReadAddr:开始读数的地址
//返回值 :读到的数据
static uint8_t FM24CXX_ReadOneByte(uint32_t ReadAddr)
{
uint8_t temp;
uint8_t addrH,addrL;
addrH=ReadAddr>>8;
addrL=ReadAddr&0xff;
IIC_Start();
IIC_Send_Byte(0xa0);
IIC_Wait_Ack();
IIC_Send_Byte(addrH); //发送高地址
IIC_Wait_Ack();
IIC_Send_Byte(addrL); //发送低地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0xa1); //进入接收模式
IIC_Wait_Ack();
temp= IIC_Read_Byte(0);
IIC_Stop();//产生一个停止条件
return temp;
}
//在FM24CXX指定地址写入一个数据
//WriteAddr :写入数据的目的地址
//DataToWrite:要写入的数据
static void FM24CXX_WriteOneByte(uint32_t WriteAddr,uint8_t DataToWrite)
{
uint8_t addrH,addrL;
addrH=WriteAddr>>8;
addrL=WriteAddr&0xff;
IIC_Start();
IIC_Send_Byte(0xa0);
IIC_Wait_Ack();
IIC_Send_Byte(addrH); //发送高地址
IIC_Wait_Ack();
IIC_Send_Byte(addrL); //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite); //发送字节
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
}
//在FM24CXX里面的指定地址开始读出指定个数的数据
//ReadAddr :开始读出的地址 对24c02为0~255
//pBuffer :数据数组首地址
//NumToRead:要读出数据的个数
void FM24CXX_Read(uint32_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead)
{
uint8_t addrH,addrL;
if(NumToRead==0)
return;
addrH=ReadAddr>>8;
addrL=ReadAddr&0xff;
IIC_Start();
IIC_Send_Byte(0xa0);//写
IIC_Wait_Ack();
IIC_Send_Byte(addrH); //发送高地址
IIC_Wait_Ack();
IIC_Send_Byte(addrL); //发送低地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0xa1); //读 //进入接收模式
IIC_Wait_Ack();
NumToRead--;
while(NumToRead)
{
*pBuffer=IIC_Read_Byte(1);
pBuffer++;
ReadAddr++;
NumToRead--;
}
*pBuffer=IIC_Read_Byte(0);
IIC_Stop();//产生一个停止条件
}
//在FM24CXX里面的指定地址开始写入指定个数的数据
//WriteAddr :开始写入的地址 对24c02为0~255
//pBuffer :数据数组首地址
//NumToWrite:要写入数据的个数
//每64bytes为一个page,写操作不能跨页
void FM24CXX_Write(uint32_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite)
{
uint8_t addrH,addrL;
uint16_t lentmp,lentow,lens;
uint8_t tmp;
if(NumToWrite==0)
return;
lentmp=NumToWrite;
while(lentmp)
{
tmp=WriteAddr%PAGE_SIZE;
tmp=PAGE_SIZE-tmp;
if(tmp>=lentmp)//当页剩余空间大于要写入的长度
{
lentow=lentmp;
}
else
{
lentow=tmp;//写入长度只能是剩余空间长度
}
lentmp=lentmp-lentow;//计算要在下一页写入的长度
lens=lentow;
addrH=WriteAddr>>8;
addrL=WriteAddr&0xff;
IIC_Start();
IIC_Send_Byte(0xa0);
IIC_Wait_Ack();
IIC_Send_Byte(addrH); //发送高地址
IIC_Wait_Ack();
IIC_Send_Byte(addrL); //发送低地址
IIC_Wait_Ack();
while(lentow--)
{
IIC_Send_Byte(*pBuffer);
IIC_Wait_Ack();
pBuffer++;
}
IIC_Stop();//产生一个停止条件
WriteAddr=WriteAddr+lens;//下一页的地址
}
}
void FM24CXX_clr(uint32_t WriteAddr,uint32_t NumToWrite)
{
uint8_t addrH,addrL;
uint16_t lentmp,lentow,lens;
uint8_t tmp;
lentmp=NumToWrite;
while(lentmp)
{
tmp=WriteAddr%PAGE_SIZE;
tmp=PAGE_SIZE-tmp;
if(tmp>=lentmp)
{
lentow=lentmp;
}
else
{
lentow=tmp;
}
lentmp=lentmp-lentow;
lens=lentow;
addrH=WriteAddr>>8;
addrL=WriteAddr&0xff;
IIC_Start();
IIC_Send_Byte(0xa0);
IIC_Wait_Ack();
IIC_Send_Byte(addrH); //发送高地址
IIC_Wait_Ack();
IIC_Send_Byte(addrL); //发送低地址
IIC_Wait_Ack();
while(lentow--)
{
IIC_Send_Byte(0xff);
IIC_Wait_Ack();
}
IIC_Stop();//产生一个停止条件
WriteAddr=WriteAddr+lens;
}
}
头文件
#ifndef __fm24c128a_H
#define __fm24c128a_H
#ifdef __cplusplus extern "C" {
#endif /* Includes ------------------------------------------------------------------*/
#include "main.h"
void FM24CXX_Write(uint32_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite);
void FM24CXX_Read(uint32_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead);
void fm24c128a_config(void); #ifdef __cplusplus }
#endif
#endif /*__ spi_H */