EDN首页   博客首页

日志档案

发表于 2008-8-27 9:54:25

13

标签: STM32  I2C  EEPROM  

基于STM32的I2C EEPROM驱动程序

        我发现写博客还是很有好处的,前天我的LCD没显示了我以为是程序的哪里被我改错了,我就这改改那改改,也没弄好,倒是把程序弄得心里没底了,没办法把博客里的程序下回去,烧到片子里,发现还是没有反应,才确定是硬件问题,因为我传到博客里的程序都是调好的。

        这两天调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;
}

完整的工程点击下载,里面没有包含固件库,用的是2.02版固件库。

系统分类: ARM   |   用户分类: STM32F   |   来源: 原创   |   【推荐给朋友】   |   【添加到收藏夹】

    阅读(547)    回复(2)  

投一票您将和博主都有获奖机会!

  • lm41851

    2008-8-28 12:58:16

    用STM32与AT24系列通信,同样的程序,为什么有的AT24能通过,有的却不能?还有,STM32 I2C的TRISE寄存器无法设置,总是复位值?这是什么原因?多谢赐教.

  • sunke9

    2008-8-28 15:15:01

    不好意思,我回答不上来你的问题,我对I2C没有很深的研究,只是在网上找来的程序拼装的.