STM32单片机硬件I2C驱动程序(查询方式)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SheepTech/article/details/82696959

本文章原始地址:http://feotech.com/?p=69

本程序主要用于驱动STM32单片机芯片的硬件I2C寄存器,实现通过使用芯片自带的I2C寄存器进行数据的发送与接收.
本例程中采用I2C寄存器查询的方式来实现数据传输,当I2C对应寄存器指定状态时方可执行下一步操作.

/**
  ******************************************************************************
  * @file    Hardware_I2C.c 
  * @author  Ryan Zhao
  * @version V1.0.0
  * @date    2017-04-27
  * @brief   STM32硬件I2C底层驱动.
  ******************************************************************************
  * @attention   Null
  * 
  ******************************************************************************
  */



/**
* @brief  I2C引脚与寄存器功能配置.
* @param  None.
* @retval None.
*/
void I2C_Configuration(void)
{
  /*GPIO与IIC初始化结构体*/  
  GPIO_InitTypeDef GPIO_InitStructure;  
  I2C_InitTypeDef I2C_InitStructure;  

  /*GPIO与IIC时钟使能*/  
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );     //GPIOB时钟使能  
  RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );      //I2C时钟使能  

  /*初始化GPIO*/  
  GPIO_InitStructure.GPIO_Pin =  HW_I2C_SDA_PIN | HW_I2C_SCL_PIN;   //初始化 IIC GPIO 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //最高输出速度50Hz  
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;     //输入输出模式为复用功能开漏输出  
  GPIO_Init( GPIOB, &GPIO_InitStructure );            //根据GPIO初始化结构体初始化GPIOB  

  /*初始化I2C*/  
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;                  //设置为I2C模式  
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;          //设置I2C的占空比,低电平除以高电平值为2  

  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;                 //使能ACK信号  
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;   //指定7位地址  
  I2C_InitStructure.I2C_ClockSpeed = 400000;                  //时钟频率,必须小于等于400KHz  

  I2C_Cmd( HW_I2C, ENABLE );                                    //使能I2C 
  I2C_Init( HW_I2C, &I2C_InitStructure );                       //根据I2C初始化结构体初始化I2C  

  /*允许一字节一应答模式*/  
  I2C_AcknowledgeConfig( HW_I2C, ENABLE );                      //使能I2C应答状态 
}


/**
* @brief  从I2C指定地址中读取数据;
* @param  读取的地址,读取后返回的数据;
* @retval 1:读取数据成功,0:读取数据无效;
*/
unsigned char  I2C_ReadByte(unsigned char Read_Address,unsigned char * Read_Data)
{ 
  unsigned char wait_time_out = wait_time_value;//等待I2C器件响应的延时
  * Read_Data = 0;

  while (I2C_GetFlagStatus(HW_I2C, I2C_FLAG_BUSY))   //判断IIC接口状态.当IIC状态为BUSY时,一直停在这里循环  
  {
    if((wait_time_out --) == 0) //延时等待
    {
      return 0; //响应超时,返回无效标志
    }
  }

  /*发送START之后要等待,意味着START条件被正确释放,此时IIC总线上没有其它外设*/  
  I2C_GenerateSTART( HW_I2C, ENABLE );                                          //产生START条件     
  while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_MODE_SELECT))             //判断开始信号是否已经发送完成  
  {
    if((wait_time_out --) == 0) //延时等待
    {
      return 0; //响应超时,返回无效标志
    }
  }

  I2C_Send7bitAddress(HW_I2C, ADXL_WRITE, I2C_Direction_Transmitter );          //发送从机地址ADXL_WRITE以选择从机,主机为发送模式  
  while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))  //如果主机发射模式被选中(死循环等待从机发送ACK信号)  
  {
    if((wait_time_out --) == 0) //延时等待
    {
      return 0; //响应超时,返回无效标志
    }
  }

  I2C_SendData(HW_I2C, Read_Address );                                         //将write_address,即要读的地址通过IIC2发送出去 
  while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))         //如果地址已经从IIC成功发射出去(死循环等待ACK信号
  {
    if((wait_time_out --) == 0) //延时等待
    {
      return 0; //响应超时,返回无效标志
    }
  }

  I2C_GenerateSTART(HW_I2C, ENABLE );                                            //产生START条件  
  while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_MODE_SELECT))                //如果主机被选中(死循环等待ACK信号)
  {
    if((wait_time_out --) == 0) //延时等待
    {
      return 0; //响应超时,返回无效标志
    }
  }
   /***主机接收数据***/  
  I2C_Send7bitAddress(HW_I2C, ADXL_READ, I2C_Direction_Receiver );              //主机设置为接收模式  
  while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))      //如果主机接收模式被选中(死循环等待ACK信号) 
  {
    if((wait_time_out --) == 0) //延时等待
    {
      return 0; //响应超时,返回无效标志
    }
  }

  I2C_AcknowledgeConfig(HW_I2C, DISABLE );                                        //失能IIC的应答状态 NACK  
  I2C_GenerateSTOP( HW_I2C, ENABLE );                                           //产生STOP条件  
  while (!(I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)))           //判断数据是否接收完成       
  {
    if((wait_time_out --) == 0) //延时等待
    {
      return 0; //响应超时,返回无效标志
    }
  }

  I2C_AcknowledgeConfig(HW_I2C, ENABLE );                                      //再一次使能IIC的应答状态  
  * Read_Data = I2C_ReceiveData(HW_I2C);                                        //返回IIC接收的数据 
  return 1;
}



/**
* @brief  通过I2C接口将数据写入从机指定地址中.
* @param  要写入的数据,接收数据的地址;
* @retval 1:数据写入成功 0:数据写入失败
*/
unsigned char  I2C_Write_Byte(uint8_t Point_Buffer,uint8_t Write_Address)
{
  unsigned char wait_time_out = wait_time_value;//等待I2C器件响应的延时

  while (I2C_GetFlagStatus(HW_I2C, I2C_FLAG_BUSY))   //判断当前I2C接口状态是否为Busy 
  {
    if((wait_time_out --) == 0) //延时等待
    {
      return 0; //响应超时,返回无效标志
    }
  }

  I2C_GenerateSTARTHW_I2C, ENABLE );                                          //产生Start信号  
  while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_MODE_SELECT))               //判断Start信号是否已经发送
  {
    if((wait_time_out --) == 0) //延时等待
    {
        return 0;   //响应超时,返回无效标志
    }
  }

  I2C_Send7bitAddress(HW_I2C, ADXL_WRITE, I2C_Direction_Transmitter );              //发送从机地址以选择从机,主机为发送模式  
  while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))   //判断发送的地址是否与从机匹配,等待从机发送ACK信号
  {
    if((wait_time_out --) == 0) //延时等待
    {
      return 0; //响应超时,返回无效标志
    }
  } 

  I2C_SendData(HW_I2C, Write_Address );                                        //将write_address,即要写的寄存器地址通过IIC发送出去     
  while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))          //判断数据是否发送完成
  {
    if((wait_time_out --) == 0) //延时等待
    {
      return 0; //响应超时,返回无效标志
    }
  }
   /*往寄存器发送数据data*/  
  I2C_SendData(HW_I2C, Point_Buffer );  
  while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))            //判断数据是否发送完成
  {
    if((wait_time_out --) == 0) //延时等待
    {
      return 0; //响应超时,返回无效标志
    }
  }

  I2C_GenerateSTOP( HW_I2C, ENABLE );                                           //IIC2产生STOP条件  

  return 1;//数据写入完成 1
}
/**
  ******************************************************************************
  * @file    Hardware_I2C.h 
  * @author  Ryan Zhao
  * @version V1.0.0
  * @date    2017-04-27
  * @brief   STM32硬件I2C底层驱动.
  ******************************************************************************
  * @attention   Null
  * 
  ******************************************************************************
  */



/*********************I2C 物理层GPIO定义*******************/
#define HW_I2C                           I2C1       //第一组I2C接口
#define HW_I2C_SDA_PIN                   GPIO_Pin_7               
#define HW_I2C_SDA_GPIO_PORT             GPIOB                      
#define HW_I2C_SCL_PIN                   GPIO_Pin_6                  
#define HW_I2C_SCL_GPIO_PORT             GPIOB  
#define wait_time_value                  200         //等待I2C器件响应的延时

猜你喜欢

转载自blog.csdn.net/SheepTech/article/details/82696959