查看: 763|回复: 0
打印 上一主题 下一主题

用模拟I2C将其消灭,公布代码

[复制链接]
跳转到指定楼层
沙发
发表于 2016-5-17 18:39:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这个模拟I2C的代码也是在本站下载的,原来是访问EEPROM的。

我使用STM32来访问I2C接口的铁电存储器,FM24CL16,2K字节,比访问EEPROM要方便一点,所以简单修改了一下,比原来少很多。

感谢ground网友提供的原始代码! FM24CL16的手册由于文件服务器问题,暂时传不上来。等阿莫弄好了再传吧。


代码就不打包了,直接贴上来了
=================================
I2C的引脚配置:

/* Configure I2C1 pins: SCL and SDA */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
=================================
/*******************************************************************************
* File Name          : i2c_fram.h
* Author             : MCD Application Team
* Version            : V2.0.1
* Date               : 06/13/2008
* Description        : Header for i2c_ee.c module
*******************************************************************************/
/* Define to prevent recursive inclusion ------------------------------------ */
#ifndef __I2C_FRAM_H
#define __I2C_FRAM_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/


/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */


bool I2C_FRAM_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite);
bool I2C_FRAM_BufferRead(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead);

#endif /* __I2C_FRAM_H */

=================================
/*******************************************************************************
* File Name          : i2c_fram.c
* Author             : Appcat
* Version            : V0.0.1
* Date               : 07/11/2009
* Description        : This file provides a set of functions needed to manage the
*                      communication between I2C peripheral and I2C FM24CL16 FRAM.
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "i2c_fram.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define I2C_Speed              100000
#define I2C1_SLAVE_ADDRESS7    0xA0
#define I2C_PageSize           256

#define SCL_H         GPIOB->BSRR = GPIO_Pin_6
#define SCL_L         GPIOB->BRR  = GPIO_Pin_6
   
#define SDA_H         GPIOB->BSRR = GPIO_Pin_7
#define SDA_L         GPIOB->BRR  = GPIO_Pin_7

#define SCL_read      GPIOB->IDR  & GPIO_Pin_6
#define SDA_read      GPIOB->IDR  & GPIO_Pin_7


/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
vu8 FRAM_ADDRESS;

/* Private function prototypes -----------------------------------------------*/

/**/
void I2C_delay(void)
{        
   u8 i=150; //这里可以优化速度        ,经测试最低到5还能写入
   while(i)
   {
     i--;
   }
}

bool I2C_Start(void)
{
        SDA_H;
        SCL_H;
        I2C_delay();
        if(!SDA_read)return FALSE;        //SDA线为低电平则总线忙,退出
        SDA_L;
        I2C_delay();
        if(SDA_read) return FALSE;        //SDA线为高电平则总线出错,退出
        SDA_L;
        I2C_delay();
        return TRUE;
}

void I2C_Stop(void)
{
        SCL_L;
        I2C_delay();
        SDA_L;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SDA_H;
        I2C_delay();
}

void I2C_Ack(void)
{        
        SCL_L;
        I2C_delay();
        SDA_L;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SCL_L;
        I2C_delay();
}

void I2C_NoAck(void)
{        
        SCL_L;
        I2C_delay();
        SDA_H;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SCL_L;
        I2C_delay();
}

bool I2C_WaitAck(void)          //返回为:=1有ACK,=0无ACK
{
        SCL_L;
        I2C_delay();
        SDA_H;                        
        I2C_delay();
        SCL_H;
        I2C_delay();
        if(SDA_read)
        {
      SCL_L;
      return FALSE;
        }
        SCL_L;
        return TRUE;
}

void I2C_SendByte(u8 SendByte) //数据从高位到低位//
{
    u8 i=8;
    while(i--)
    {
        SCL_L;
        I2C_delay();
      if(SendByte&0x80)
        SDA_H;  
      else
        SDA_L;   
        SendByte<<=1;
        I2C_delay();
                SCL_H;
        I2C_delay();
    }
    SCL_L;
}

u8 I2C_ReceiveByte(void)  //数据从高位到低位//
{
    u8 i=8;
    u8 ReceiveByte=0;

    SDA_H;                                
    while(i--)
    {
      ReceiveByte<<=1;      
      SCL_L;
      I2C_delay();
          SCL_H;
      I2C_delay();        
      if(SDA_read)
      {
        ReceiveByte|=0x01;
      }
    }
    SCL_L;
    return ReceiveByte;
}

bool I2C_FRAM_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite)
{
        u8 Addr = 0, count = 0;

        Addr = WriteAddr / I2C_PageSize;

        count = WriteAddr % I2C_PageSize;

        Addr = Addr << 1;

        Addr = Addr & 0x0F;  

        FRAM_ADDRESS = I2C1_SLAVE_ADDRESS7 | Addr;

    if (!I2C_Start()) return FALSE;
    I2C_SendByte(FRAM_ADDRESS);//设置器件地址+段地址
    if (!I2C_WaitAck())
        {
                I2C_Stop();
                return FALSE;
        }
    I2C_SendByte(count);   //设置段内地址      
        I2C_WaitAck();        
         
        while(NumByteToWrite--)
        {
          I2C_SendByte(* pBuffer);
          I2C_WaitAck();
      pBuffer++;
        }
        I2C_Stop();
          //注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)
          //Systick_Delay_1ms(10);
        return TRUE;
}


//读出1串数据         
bool I2C_FRAM_BufferRead(u8* pBuffer, u16 WriteAddr, u16 NumByteToRead)
{               
        u8 Addr = 0, count = 0;

    Addr = WriteAddr / I2C_PageSize;

        count = WriteAddr % I2C_PageSize;

        Addr = Addr << 1;

        Addr = Addr & 0x0F;  

        FRAM_ADDRESS = I2C1_SLAVE_ADDRESS7 | Addr;
        
        if (!I2C_Start()) return FALSE;

    I2C_SendByte(FRAM_ADDRESS);//设置器件地址+段地址

    if (!I2C_WaitAck())
        {
                I2C_Stop();
                return FALSE;
        }

    I2C_SendByte(count);   //设置低起始地址      
    I2C_WaitAck();
    I2C_Start();
    I2C_SendByte(FRAM_ADDRESS | 0x01);
    I2C_WaitAck();
    while(NumByteToRead)
    {
      *pBuffer = I2C_ReceiveByte();
      if(NumByteToRead == 1)I2C_NoAck();
      else I2C_Ack();
      pBuffer++;
      NumByteToRead--;
    }
    I2C_Stop();
    return TRUE;
}

=================================
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表