药无尘 发表于 2024-3-7 16:51

AT32F403A基于V2库 io模拟iic读写AT24C04

概述
         本文主要是使用AT32F403A开发板,基于V2库实现通过io模拟iic读写AT24C04功能。

         串口工具使用的Atlink-ez自带的串口功能。

         工程建立、调试工具配置在前面章节有详细介绍。

硬件
      硬件方面使用的是参考官方AT32F437 SURF 板子而设计的一个AT32F403A开发板,板子上的芯片是AT32F403AVGT7的型号,开发板上面还板载了一个atlink-ez的仿真器,atlink-ez除了可以在线仿真和下载之外还有一个串口的功能,硬件上是通过跳线帽接到了MCU的串口1,pa9/10上面。
概述
         本文主要是使用AT32F403A开发板,基于V2库实现通过io模拟iic读写AT24C04功能。

         串口工具使用的Atlink-ez自带的串口功能。

         工程建立、调试工具配置在前面章节有详细介绍。

IIC
         IIC是很常用的一种串行总线协议,总线上可挂设多个主从机。 IIC使用两条线在主控制器和从机之间进行数据通信。一条是SCL(串行时间线),另一条是SDA(串行数据线),这两条数据线需要上拉电阻,总线空闲的时候SCL和SDA处于高电平。

         IIC是支持多从机的,也就是一个IIC控制器下可以挂多个IIC从设备,这些不同的IIC从设备有不同的器件地址,这样IIC主控制器就可以通过IIC设备的器件地址访问指定的IIC设备。具体的协议时钟等可网上查找相关资料。

AT24C02
         AT24C02是一颗2Kb的存储芯片,也就是容量大小为256字节。地址是1010xxxx,低四位里面的高三位是由硬件的A0/1/2来决定的,拉高时为1,拉低为0,最低位就是读写位,0为写,1为读。

初始化   
         本文使用的是AT32F403A的PB14和PB15来模拟IIC的时序,设置IO为复用开漏输出模式。

         由于AT24C02的三个地址硬件上都是拉到地,所以地址为0xA0。

         驱动软件部分就是通过对IO的拉高拉低,以及读取值等操作,实现iic的时序,包括开始时序,停止时序,ack、no ack、等待ack,发送时序,接收时序等,想要了解的可去看源码,同时此驱动代码是从雅特力官网获取的然后修改io部分。

      IO宏定义如下:(使用不同的io的时候,直接修改为对应的IO即可。)

初始化代码
/**
* @briefi2c gpio initialization.
* @paramnone.
* @retval none.
*/
void i2c_config(void)
{
gpio_init_type gpio_initstructure;

/* i2c gpio clock enable */
crm_periph_clock_enable(I2Cx_SCL_GPIO_CLK, TRUE);
crm_periph_clock_enable(I2Cx_SDA_GPIO_CLK, TRUE);

I2C_SDA_HIGH();

I2C_SCL_HIGH();

/* gpio configuration */
gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
gpio_initstructure.gpio_pull         = GPIO_PULL_UP;
gpio_initstructure.gpio_mode         = GPIO_MODE_OUTPUT;
gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;

/* configure i2c pins: scl */   
gpio_initstructure.gpio_pins = I2Cx_SCL_PIN;
gpio_init(I2Cx_SCL_GPIO_PORT, &gpio_initstructure);

/* configure i2c pins: sda */   
gpio_initstructure.gpio_pins = I2Cx_SDA_PIN;
gpio_init(I2Cx_SDA_GPIO_PORT, &gpio_initstructure);
}驱动代码

/**
* @briefused to set the i2c clock frequency.
* @paramnone.
* @retval none.
*/
void i2c_delay(void)
{
delay_us(5);
}

/**
* @briefused to generate start conditions.
* @paramnone.
* @retval none.
*/
void i2c_start(void)
{
i2c_delay();

I2C_SDA_HIGH();
I2C_SCL_HIGH();
i2c_delay();

I2C_SDA_LOW();
i2c_delay();

I2C_SCL_LOW();
}

/**
* @briefused to generate stop conditions.
* @paramnone.
* @retval none.
*/
void i2c_stop(void)
{
I2C_SCL_LOW();
I2C_SDA_LOW();
i2c_delay();

I2C_SCL_HIGH();
i2c_delay();

I2C_SDA_HIGH();
i2c_delay();
}

/**
* @briefused to generate ack conditions.
* @paramnone.
* @retval none.
*/
void i2c_ack(void)
{
I2C_SCL_LOW();
I2C_SDA_LOW();
i2c_delay();

I2C_SCL_HIGH();
i2c_delay();

I2C_SCL_LOW();
}

/**
* @briefused to generate nack conditions.
* @paramnone.
* @retval none.
*/
void i2c_no_ack(void)
{
I2C_SCL_LOW();
I2C_SDA_HIGH();
i2c_delay();

I2C_SCL_HIGH();
i2c_delay();

I2C_SCL_LOW();
}

/**
* @briefused to wait ack conditions.
* @paramnone.
* @retval ack receive status.
*         - 1: no ack received.
*         - 0: ack received.
*/
uint8_t i2c_wait_ack(uint8_t timeout)
{
I2C_SCL_LOW();
I2C_SDA_HIGH();

i2c_delay();

while(timeout)
{
    if (I2C_SDA_READ() == 0)
    {
      I2C_SCL_HIGH();
      
      i2c_delay();
      
      I2C_SCL_LOW();
      
      return 0;
    }
   
    i2c_delay();
   
    timeout--;
}

I2C_SCL_HIGH();
i2c_delay();      

I2C_SCL_LOW();

i2c_delay();

return 1;
}

/**
* @briefsend a byte.
* @paramdata: byte to be transmitted.
* @retval none.
*/
void i2c_send_byte(uint8_t data)
{
uint8_t i = 8;

while (i--)
{
    I2C_SCL_LOW();
   
    if (data & 0x80)
    {
      I2C_SDA_HIGH();   
    }
    else
    {
      I2C_SDA_LOW();   
    }   
   
    i2c_delay();

    data <<= 1;
   
    I2C_SCL_HIGH();
    i2c_delay();
}

I2C_SCL_LOW();
I2C_SDA_HIGH();   
}

/**
* @briefreceive a byte.
* @paramdata: byte to be received.
* @retval none.
*/
uint8_t i2c_receive_byte(void)
{
uint8_t i = 8;
uint8_t byte = 0;

I2C_SDA_HIGH();

while (i--)
{
    byte <<= 1;
   
    I2C_SCL_LOW();
    i2c_delay();
   
    I2C_SCL_HIGH();
    i2c_delay();
   
    if (I2C_SDA_READ())
    {
      byte |= 0x01;
    }
}

I2C_SCL_LOW();

return byte;
}


盗铃何须掩耳 发表于 2024-3-13 09:36

如果是AT24C16,怎么修改代码

呐咯密密 发表于 2024-3-18 14:55

软件IIC,方便移植

micoccd 发表于 2024-3-20 17:09

软件模拟好,换一下GPIO的宏定义,通用
页: [1]
查看完整版本: AT32F403A基于V2库 io模拟iic读写AT24C04