[原创]发一个我的最新作品,stm32f的eeprom驱动程序

发布: 2008-8-27 10:23 | 作者: sunke9 | 来源: StmFans思蜕盟 OPELC 自由电子联盟

基于STM32的I2C EEPROM驱动程序
这两天调EEPROM驱动才发现ST给的例子在万利的开发板上根本调不通,于是到网上找了一圈,软I2C的硬I2C的就是没有一个能拿过来就用的。经过我东拼西凑终于凑出了一个能调通的程序,已经在AT24C02、AT24C04上验证通过。

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

/* Private define ------------------------------------------------------------*/
#define I2C_Speed              100000
#define I2C1_SLAVE_ADDRESS7    0xA0
#define I2C_PageSize           16
/* I2C START mask */
#define CR1_START_Set           ((u16)0x0100)
#define CR1_START_Reset         ((u16)0xFEFF)

/* I2C STOP mask */
#define CR1_STOP_Set            ((u16)0x0200)
#define CR1_STOP_Reset          ((u16)0xFDFF)

/* I2C ACK mask */
#define CR1_ACK_Set             ((u16)0x0400)
#define CR1_ACK_Reset           ((u16)0xFBFF)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

u16 EEPROM_ADDRESS ;
/* Private function prototypes -----------------------------------------------*/
void GPIO_Configuration(void);
void I2C_Configuration(void);
void I2C_AcknowledgePolling(void);
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : Configure the used I/O ports pin
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

  /* 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_AF_OD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/*******************************************************************************
* Function Name  : I2C_Configuration
* Description    : I2C Configuration
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_Configuration(void)
{
  I2C_InitTypeDef  I2C_InitStructure;

  /* I2C configuration */
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
  I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;
  
  /* I2C Peripheral Enable */
  I2C_Cmd(I2C1, ENABLE);
  /* Apply I2C configuration after enabling it */
  I2C_Init(I2C1, &I2C_InitStructure);
}

/*******************************************************************************
* Function Name  : I2C_EE_Init
* Description    : Initializes peripherals used by the I2C EEPROM driver.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_Init()
{
  /* GPIO configuration */
  GPIO_Configuration();

  /* I2C configuration */
  I2C_Configuration();

  /* depending on the EEPROM Address selected in the i2c_ee.h file */
#ifdef EEPROM_Block0_ADDRESS
  /* Select the EEPROM Block0 to write on */
  EEPROM_ADDRESS = EEPROM_Block0_ADDRESS;
#endif
#ifdef EEPROM_Block1_ADDRESS
  /* Select the EEPROM Block1 to write on */
  EEPROM_ADDRESS = EEPROM_Block1_ADDRESS;
#endif
#ifdef EEPROM_Block2_ADDRESS
  /* Select the EEPROM Block2 to write on */
  EEPROM_ADDRESS = EEPROM_Block2_ADDRESS;
#endif
#ifdef EEPROM_Block3_ADDRESS
  /* Select the EEPROM Block3 to write on */
  EEPROM_ADDRESS = EEPROM_Block3_ADDRESS;
#endif
}

void I2C_AcknowledgePolling(void)
{
    do{
        I2C_GenerateSTART(I2C1,ENABLE);
        I2C_ReadRegister(I2C1,I2C_Register_SR1);//清除ADDR位

        I2C_Send7bitAddress(I2C1,0xa0,I2C_Direction_Transmitter);
    }while(!(I2C_ReadRegister(I2C1,I2C_Register_SR1)&0x0002));
  
    I2C_ClearFlag(I2C1,I2C_FLAG_AF);
}

void I2C_24CXX_Read(u8 EEPROM_ADDRESS,u8 ReadAddr,u8 *pBuffer,u8 NumByteToRead)
{
    u8 i;

    I2C_AcknowledgePolling();
   
    I2C1->CR1 |= CR1_START_Set;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));  
   
    I2C1->DR = EEPROM_ADDRESS;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    I2C1->DR = ReadAddr;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
               
    I2C1->CR1 |= CR1_START_Set;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));  

    I2C1->DR = EEPROM_ADDRESS+1;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));   
    I2C1->CR1 |= CR1_ACK_Set;

    if(NumByteToRead>1){
        for(i=0;i<NumByteToRead-1;i++)
     {
            while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED));
            *pBuffer ++= I2C1->DR;
            
            I2C1->CR1 |= CR1_ACK_Set;
        }
    }
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED));
    *pBuffer = I2C1->DR;
    I2C1->CR1 &= CR1_ACK_Reset;
   
    I2C1->CR1 |= CR1_STOP_Set;
}


void I2C_24CXX_Write(u8 EEPROM_ADDRESS,u8 WriteAddr,u8* pBuffer,u8 NumByteToWrite)
{
    u8 wLen,addr;
   
    wLen="NumByteToWrite";
    addr="WriteAddr";
    ScrollPage:I2C_AcknowledgePolling();
   
               I2C1->CR1 |= CR1_START_Set;
               while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));  
  
               I2C1->DR = EEPROM_ADDRESS;
               while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

               I2C1->DR = addr;
               while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
                              
               I2C1->DR = *pBuffer++;
               while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
               
               addr++;
               wLen--;
        
    while(wLen){
        if((addr%8)!=0)
     {
            I2C1->DR = *pBuffer++;
            while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
            
            addr++;
            wLen--;
        }
        else{
            I2C1->CR1 |= CR1_STOP_Set;
            goto ScrollPage;
        }
    }
    I2C1->CR1 |= CR1_STOP_Set;
}
nomoneyiv (2008-8-27 10:25:13)
先顶一下!

回来再验证!
jasonjee (2008-8-27 10:40:20)
太棒了,加分,加分
binglin (2008-8-27 10:41:02)
谢谢,请  sunke9 说说为什么ST给的例子为什么在万利的板子上调不通,问题出在那?解决方案是怎样?

晕呀,把 sunke9  小可哥当成 nomoneyiv 。   立即改正

sunke9  小可哥,不好意思呀。
long18751813 (2008-8-27 14:08:47)
期待 不错
nomoneyiv (2008-8-27 15:02:38)
I2C的程序,我还没验证过,炳哥,不好意思!要迟些才能发表看法!
sunke9 (2008-8-28 13:21:13)
我用的是万利EK-STM32F开发板,用ST的例子程序总是走到
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
就在这死循环了
03024003 (2009-9-19 09:47:59)
我测试了例程也是死在while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
目前原因不明
simonqian (2009-9-19 16:26:47)
据说STM32的IIC部分有BUG,所以我目前也都直接避开IIC接口,当然,直接用IO口模拟式没有问题的。
最近也要抽空在偶的Versaloon上加上IIC接口的支持,正准备研究一下这个问题呢。