stm 32 gpio 模拟 i2c 备忘


最近调试i2c遇到一些问题,在此备忘,总结一句话,还是要特别注意时序,哪怕一个高低点平的错误都可能导致程序工作不正常

另外对于stm32 提供的i2c固件例程一直没有调好,特别烦人

#include "SystemInit.h"

#include <stdint.h>
#include "stm32_eval_i2c_ee.h"





void IIC_Init(void);                  
void IIC_Start(void);    
void IIC_Stop(void);      
void IIC_Send_Byte(u8 txd);   
u8 IIC_Read_Byte(unsigned char ack);
u8 IIC_Wait_Ack(void);     


u8 IIC_Read_One_Byte(u8 daddr,u8 addr);  


__IO uint32_t  timeremain = 0;


void delay_us(__IO uint32_t arg)
{
volatile uint16_t   i = 0;
#if 0

    while(arg--)
    {
      for(i = 5; i > 0; i--);
    }
#else
   timeremain = arg;
    EnableTimer2();
    while(timeremain)
    {
    }
#endif
    
}




/*
#define SDA_IN()  {IIC_SDA_PORT->CRH&=0XFFFF0FFF;IIC_SDA_PORT->CRH|=8<<12;}
#define SDA_OUT() {IIC_SDA_PORT->CRH&=0XFFFF0FFF;IIC_SDA_PORT->CRH|=3<<12;}
*/

#define Set_IIC_SCL  {GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_PIN);}
#define Clr_IIC_SCL  {GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_PIN);}

#define Set_IIC_SDA  {GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_PIN);}
#define Clr_IIC_SDA  {GPIO_ResetBits(IIC_SDA_PORT,IIC_SDA_PIN);}
#define READ_SDA    (GPIO_ReadInputDataBit(IIC_SDA_PORT, IIC_SDA_PIN))



#define IIC_SCL_PORT              GPIOD
#define IIC_SCL_CLK               RCC_APB2Periph_GPIOD
#define IIC_SCL_PIN               GPIO_Pin_8
#define IIC_SDA_PORT              GPIOD
#define IIC_SDA_CLK               RCC_APB2Periph_GPIOD
#define IIC_SDA_PIN               GPIO_Pin_9


void SDA_IN()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
    //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);

}

void SDA_OUT()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
}


#define Set_IIC_SCL  {GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_PIN);}
#define Clr_IIC_SCL  {GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_PIN);}

#define Set_IIC_SDA  {GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_PIN);}
#define Clr_IIC_SDA  {GPIO_ResetBits(IIC_SDA_PORT,IIC_SDA_PIN);}
#define READ_SDA    (GPIO_ReadInputDataBit(IIC_SDA_PORT, IIC_SDA_PIN))

void IIC_Init(void)
{         
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd( IIC_SCL_CLK, ENABLE );

    GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
    GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
    Set_IIC_SCL;
    Set_IIC_SDA;
}

/*
#define Set_IIC_SCL_2  {GPIO_SetBits(GPIOD,GPIO_Pin_8);}
#define Clr_IIC_SCL_2  {GPIO_ResetBits(GPIOD,GPIO_Pin_8);}
#define Set_IIC_SDA_2  {GPIO_SetBits(GPIOD,GPIO_Pin_9);}
#define Clr_IIC_SDA_2  {GPIO_ResetBits(GPIOD,GPIO_Pin_9);}
*/

void IIC_Start(void)
{
    SDA_OUT();    
    Set_IIC_SDA;     
    Set_IIC_SCL;
    delay_us(4);
    Clr_IIC_SDA;
    delay_us(4);
    Clr_IIC_SCL;
}  


void IIC_Stop(void)
{
    SDA_OUT();
        //Set_IIC_SCL;
        //delay_us(4);
    Clr_IIC_SDA;
    delay_us(4);
    Set_IIC_SCL;
        delay_us(4);
    Set_IIC_SDA;
    delay_us(4);           
}


u8 IIC_Wait_Ack(void)
{
    u8 ucErrTime=0;
         SDA_IN();
    Set_IIC_SDA;
        delay_us(4);   
        
        //SDA_IN();
    Set_IIC_SCL;
        delay_us(4);
         
    while(READ_SDA)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            IIC_Stop();
            return 1;
        }
    }
    Clr_IIC_SCL;
        //delay_us(4);
        //SDA_OUT();
        
    return 0;
}



void IIC_Send_Byte(u8 txd)
{                       
    u8 t;  
        
    SDA_OUT();     
    Clr_IIC_SCL;
    for(t=0;t<8;t++)
    {             
        if ((txd&0x80)>>7)  
            Set_IIC_SDA
        else
            Clr_IIC_SDA;
            
        txd<<=1;   
        delay_us(2);  
        Set_IIC_SCL;
        delay_us(2);
        Clr_IIC_SCL;
        delay_us(2);
    }
}

u8 IIC_Read_Byte(unsigned char ack)
{
    unsigned char i,receive=0;
    SDA_IN();
    for(i=0;i<8;i++ )
    {
        Clr_IIC_SCL;
        delay_us(2);      
        Set_IIC_SCL;
        delay_us(2);
                receive<<=1;
        if(READ_SDA)receive++;                 
    }  /*   
    if (!ack)
        IIC_NAck();
    else
        IIC_Ack();
        */
    return receive;
}

u8 EE_TYPE = 0;

u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{     
    u8 temp=0;                         
    IIC_Start();

        IIC_Send_Byte(0XA0);    
        IIC_Wait_Ack();
        IIC_Send_Byte(ReadAddr);
        IIC_Wait_Ack();
        IIC_Start();       
        IIC_Send_Byte(0XA1);           
        IIC_Wait_Ack();
        temp=IIC_Read_Byte(0);    
        IIC_Stop();
        return temp;
}

void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{                               
    IIC_Start();

        
        IIC_Send_Byte(0XA0);    
        IIC_Wait_Ack();
        IIC_Send_Byte(WriteAddr);   
        IIC_Wait_Ack();
        IIC_Send_Byte(DataToWrite);       
        IIC_Wait_Ack();           
        IIC_Stop();
        

                
}


void time2callback()
{
    if (timeremain > 0) timeremain--;
    if (timeremain == 0)
    {    
        DisableTimer2();
    }
}
/**
 * @fn void main(int argc, char** argv)
 * @brief main, system entry function
 * @param argc: input params count
 * @param argv: input params
 * @return none
*/
void main(int argc, char** argv)
{
  InitSystem;
  InitTimer2();
  RegTimer2Callback(time2callback);
 
  int data, addr, readdata;

  IIC_Init();
    
 
   
   while(1)
   {
 
    data = 0xff;
    addr = 0x1;
    readdata = 0;
    for (addr = 0; addr < 16; addr++)
    {
      AT24CXX_WriteOneByte(addr, data);
      delay_us(5 * 100);
    }
    for (addr = 0; addr < 16; addr++)
    {
      readdata = AT24CXX_ReadOneByte(addr);
     // printf("read data = %X\n", readdata);
    }
 
    delay_us(10000);
   }
}


uint32_t sEE_TIMEOUT_UserCallback(void)
{
  /* Use application may try to recover the communication by resetting I2C
    peripheral (calling the function I2C_SoftwareResetCmd()) then re-start
    the transmission/reception from a previously stored recover point.
    For simplicity reasons, this example only shows a basic way for errors
    managements which consists of stopping all the process and requiring system
    reset. */
 
  printf("Communication ERROR!");
 
  /* Block communication and all processes */
  while (1)
  {   
  }  
}
#ifdef USE_FULL_ASSERT
/*******************************************************************************
* Function Name  : assert_failed
* Description    : Reports the name of the source file and the source line number
*                  where the assert_param error has occurred.
* Input          : - file: pointer to the source file name
*                  - line: assert_param error line source number
* Output         : None
* Return         : None
*******************************************************************************/
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {}
}
#endif

你可能感兴趣的:(c)