|
发表于 2014-6-11 19:33:31
|
显示全部楼层
#在这里快速回复这个模拟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; } |
|