天天看點

STM32—基于模拟IIC方式讀取EEPROM 前言:

前言:

最近在調試STM32L152晶片利用IIC接口讀取EEPROM的程式,總結下STM32的 IIC接口 讀取EEPROM的使用方法。

PS:由于STM32的硬體IIC存在一些問題,本文暫時使用模拟IIC進行EEPROM的讀取。STM32的硬體IIC使用方法見另外兩篇文章:傳送門1和傳送門2。

硬體平台:STM32L152

軟體平台:keil v5+cubeMX

函數庫:HAL函數庫

1:配置iic引腳,本例對應PC2和PC3管腳,移植修改對應管腳。

#define I2C_SCL GPIO_PIN_2	  //PC2
#define I2C_SDA GPIO_PIN_3	  //PC3


#define I2C_SCL_H HAL_GPIO_WritePin(GPIOC,I2C_SCL,GPIO_PIN_SET)
#define I2C_SCL_L HAL_GPIO_WritePin(GPIOC,I2C_SCL,GPIO_PIN_RESET)

#define I2C_SDA_H HAL_GPIO_WritePin(GPIOC,I2C_SDA,GPIO_PIN_SET)
#define I2C_SDA_L HAL_GPIO_WritePin(GPIOC,I2C_SDA,GPIO_PIN_RESET)
           
void I2C_INIT()
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.Pin= I2C_SCL|I2C_SDA;
    GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Pull  =GPIO_NOPULL;
    GPIO_InitStructure.Speed  = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOC,&GPIO_InitStructure);

    I2C_SCL_H;
    I2C_SDA_H;
}
           

2: 編寫開始、停止、應答、非應答、發送、接收等信号程式;

//SDA資料輸入函數

void I2C_SDA_OUT()
{
    GPIO_InitTypeDef GPIO_InitStructure; 

    GPIO_InitStructure.Pin =I2C_SDA;
    GPIO_InitStructure.Mode =GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Pull  =GPIO_PULLUP;
    GPIO_InitStructure.Speed =GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOC,&GPIO_InitStructure);
}
           

//SDA資料輸出函數

void I2C_SDA_IN(void)
{
    GPIO_InitTypeDef GPIO_InitStructure; 

    GPIO_InitStructure.Pin   =I2C_SDA;
    GPIO_InitStructure.Mode =GPIO_MODE_INPUT;
    GPIO_InitStructure.Pull  =GPIO_NOPULL;
    GPIO_InitStructure.Speed =GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOC,&GPIO_InitStructure);
}
           

//産生IIC開始信号函數

void I2C_Start(void)
{
  I2C_SDA_OUT();

    I2C_SDA_H;
    I2C_SCL_H;
    delay_us(5);
    I2C_SDA_L;
    delay_us(6);
    I2C_SCL_L;
}
           

 //産生IIC停止信号函數

void I2C_Stop(void)
{
   I2C_SDA_OUT();


   I2C_SCL_L;
   I2C_SDA_L;
   I2C_SCL_H;
   delay_us(6);
   I2C_SDA_H;
   delay_us(6);
}
           

//IIC應答函數

void I2C_Ack(void)
{
   I2C_SCL_L;
   I2C_SDA_OUT();
   I2C_SDA_L;
   delay_us(2);
   I2C_SCL_H;
   delay_us(5);
   I2C_SCL_L;
}
           

//IIC非應答函數

void I2C_NAck(void)
{
   I2C_SCL_L;
   I2C_SDA_OUT();
   I2C_SDA_H;
   delay_us(2);
   I2C_SCL_H;
   delay_us(5);
   I2C_SCL_L;
}
           

//IIC等待應答函數

u8 I2C_Wait_Ack(void)
{
    u8 tempTime=0;

    I2C_SDA_IN();
    I2C_SDA_H;
    delay_us(1);
    I2C_SCL_H;
    delay_us(1);


    while(HAL_GPIO_ReadPin(GPIO_I2C,I2C_SDA))
    {
        tempTime++;
        if(tempTime>250)
        {
            I2C_Stop();
            return 1;
        }  
    }
    I2C_SCL_L;
    return 0;
}
           

//IIC發送一個位元組函數

void I2C_Send_Byte(u8 txd)
{
    u8 i=0;

    I2C_SDA_OUT();
    I2C_SCL_L;

    for(i=0;i<8;i++)
    {
        if((txd&0x80)>0) //0x80  1000 0000
            I2C_SDA_H;
        else
            I2C_SDA_L;

        txd<<=1;
        I2C_SCL_H;
        delay_us(2); 
        I2C_SCL_L;
        delay_us(2);
    }
}
           

//I2C 讀取一個位元組函數

u8 I2C_Read_Byte(u8 ack)
{
   u8 i=0,receive=0;

   I2C_SDA_IN();
   for(i=0;i<8;i++)
   {
        I2C_SCL_L;
        delay_us(2);
        I2C_SCL_H;
        receive<<=1;
        if(HAL_GPIO_ReadPin(GPIO_I2C,I2C_SDA))
          receive++;
        delay_us(1); 
   }
    if(ack==0)
      I2C_NAck();
    else
      I2C_Ack();
    return receive;
}
           

3:編寫寫入EEPROM AT24C02程式。

從EEPROM中讀取一位元組資料函數。

u8 AA24x_ReadOneByte(u8 addr)
{
    u8 temp=0;
    I2C_Start(); 
    I2C_Send_Byte(0xA0);//1010000
    I2C_Wait_Ack();
    I2C_Send_Byte(addr);
    I2C_Wait_Ack();
    I2C_Start();
    I2C_Send_Byte(0xA1);//10100001
    I2C_Wait_Ack();
    temp=I2C_Read_Byte(0); 
    I2C_NAck();
    I2C_Stop(); 
    return temp; 
}
           

從EEPROM中寫入一位元組資料函數。 

void AA24x_WriteOneByte(u8 addr,u8 dt)
{
    I2C_Start();
    I2C_Send_Byte(0xA0);
    I2C_Wait_Ack();
    I2C_Send_Byte(addr); 
    I2C_Wait_Ack();
    I2C_Send_Byte(dt);
    I2C_Wait_Ack();
    I2C_Stop();
    delay_ms(10);
}
           

繼續閱讀