2023/10/12 FM24C128A驱动IO模拟

#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 */

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值