这个模拟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;
}
=================================
|