I2C之硬件IIC

硬件IIC

自我总结一下stm32的硬件IIC。
硬件IIC和模拟IIC的优缺点就不再分析,普遍的观点就是模拟IIC好移植、不受管脚的限制,硬件IIC效率高,可以使用DMA、中断等,但是也存在bug。
先不管bug吧,本着人人都是懒狗的理由,用cube生成代码,先学会怎么使用吧。

生成IIC代码

  1. cube软件里面设置比较简单
    I2C之硬件IIC_第1张图片2. 代码
    基础的配置就按cube生成就好,一处需要修改的地方是,需要把IIC的时钟使能放置到GPIO初始化之前,如图
    I2C之硬件IIC_第2张图片否则iic就不能工作,应该是一个小bug。
    这样基本的工作就完成了。

读写操作

  1. 写操作

    ///IIC写操作
    ///返回操作结果
    ///在循环调用时需要加一定的延时

    HAL_StatusTypeDef EE_I2C_Write(uint16_t Write_Address, uint16_t InChipReg_Address, uint16_t OSSetSize, uint8_t *Data_Buffer, uint16_t Data_Length)
    {
    HAL_StatusTypeDef status =HAL_OK;

    status =HAL_I2C_Mem_Write(&hi2c1, Write_Address, InChipReg_Address, OSSetSize, Data_Buffer, Data_Length, 1000);

    if (status!=HAL_OK)
    {
    EE_I2C_Error();
    }

    return status;
    }
    里面的各项参数:
    Write_Address:IIC设备的写地址,比如在AT24C02中,如果三个地址引脚全设置为底,那么它的写地址就是0xA0.
    InChipReg_Address:IIC设备片内的地址,在AT24C02中,它有256个字节,那么参数可以为0-255
    OSSetSize:这个参数是HAL中提供了的,只能是I2C_MEMADD_SIZE_8BIT或
    I2C_MEMADD_SIZE_16BIT。
    Data_Buffer:这个是自己写的那个数据缓冲区的地址,比如我在main.c中定义了一个 uint8_t write_buf[256];
    Data_Length:这个是从缓冲区写入数据的字节个数

这些形参名都是根据自己理解定义的,具体的分析要根据HAL_I2C_Mem_Write()函数展开理解。

  1. 读操作

    HAL_StatusTypeDef EE_I2C_Read(uint16_t Read_Address, uint16_t InChipReg_Address, uint16_t OSSetSize, uint8_t *Data_Buffer, uint16_t Data_Length)
    {
    HAL_StatusTypeDef status =HAL_OK;

    status =HAL_I2C_Mem_Read(&hi2c1, Read_Address, InChipReg_Address, OSSetSize, Data_Buffer, Data_Length, 1000);

    if (status!=HAL_OK)
    {
    EE_I2C_Error();
    }

    return status;
    }
    具体的参数可根据上面的写操作理解。在hal库中HAL_I2C_Mem_Read()和HAL_I2C_Mem_Write()形参是一样的,很好理解。

  2. 错误处理

    ///IIC通信错误处理函数
    ///无输入参数
    ///无返回值
    ///在IIC通信超时时调用该函数
    static void EE_I2C_Error(void)
    {
    HAL_I2C_DeInit(&hi2c1);

    EE_I2C1_Init();
    printf(“EEPROM I2C通信超时!!重新启动…\n”);
    }

实例:AT24C02读写操作

创建两个数据缓冲区,将写缓冲区的数值写入到EEPROM中,然后再将EEPROM中的数据读出来,打印到串口上。

uint8_t write_buf[256];
uint8_t read_buf[256];

int main(void)
{

 
  HAL_Init();

  SystemClock_Config();

  LED_GPIO_Init();
  DEBUG_USART1_UART_Init();
  EE_I2C1_Init();

  printf("开始进行一个IIC的实验\n");
  
  for(int i=0;i<256;i++)
  {
    read_buf[i]=0;//读缓冲区全清零
    write_buf[i]=i;//给写缓冲区赋值
  }
  for(int i=0;i<256;i++)
  {
    printf("read[%d]=%d write[%d]=%d   ",i,read_buf[i],i,write_buf[i]);
    if(i%8==7)
      printf("\n");
  }
  
  //AT24C02共有32页,每页8个字节,这是一次写入一页。当然也可以按一个一个字节写入
  for(int i=0;i<256;i+=8)
  {
    EE_I2C_Write(0xA0,i,I2C_MEMADD_SIZE_8BIT,&write_buf[i],8);
    HAL_Delay(5);
  }
  
  printf("EEPROM按页已经写入数据,下面将数据从EEPROM中读出来\n");
  
 //将256个字节一次读出来
  EE_I2C_Read(0xA1,0,I2C_MEMADD_SIZE_8BIT,&read_buf[0],256);
  
   for(int i=0;i<256;i++)
  {
    printf("read[%d]=%d write[%d]=%d   ",i,read_buf[i],i,write_buf[i]);
    if(i%8==7)
      printf("\n");
  }
 
  while (1)
  {

  }


}

实验结果如图:
I2C之硬件IIC_第3张图片I2C之硬件IIC_第4张图片读缓冲区的值已经变成了EEPROM内部读出来的值。
完成

你可能感兴趣的:(单片机)