本文使用的是AT32F403A的PB14和PB15来模拟IIC的时序,设置IO为复用开漏输出模式。
由于AT24C02的三个地址硬件上都是拉到地,所以地址为0xA0。
驱动软件部分就是通过对IO的拉高拉低,以及读取值等操作,实现iic的时序,包括开始时序,停止时序,ack、no ack、等待ack,发送时序,接收时序等,想要了解的可去看源码,同时此驱动代码是从雅特力官网获取的然后修改io部分。
初始化代码 /**
* [url=home.php?mod=space&uid=247401]@brief[/url] i2c gpio initialization.
* @param none.
* @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);
}
驱动代码:
/**
* @brief used to set the i2c clock frequency.
* @param none.
* @retval none.
*/
void i2c_delay(void)
{
delay_us(5);
}
/**
* @brief used to generate start conditions.
* @param none.
* @retval none.
*/
void i2c_start(void)
{
i2c_delay();
I2C_SDA_HIGH();
I2C_SCL_HIGH();
i2c_delay();
I2C_SDA_LOW();
i2c_delay();
I2C_SCL_LOW();
}
/**
* @brief used to generate stop conditions.
* @param none.
* @retval none.
*/
void i2c_stop(void)
{
I2C_SCL_LOW();
I2C_SDA_LOW();
i2c_delay();
I2C_SCL_HIGH();
i2c_delay();
I2C_SDA_HIGH();
i2c_delay();
}
/**
* @brief used to generate ack conditions.
* @param none.
* @retval none.
*/
void i2c_ack(void)
{
I2C_SCL_LOW();
I2C_SDA_LOW();
i2c_delay();
I2C_SCL_HIGH();
i2c_delay();
I2C_SCL_LOW();
}
/**
* @brief used to generate nack conditions.
* @param none.
* @retval none.
*/
void i2c_no_ack(void)
{
I2C_SCL_LOW();
I2C_SDA_HIGH();
i2c_delay();
I2C_SCL_HIGH();
i2c_delay();
I2C_SCL_LOW();
}
/**
* @brief used to wait ack conditions.
* @param none.
* @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;
}
/**
* @brief send a byte.
* @param data: 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();
}
/**
* @brief receive a byte.
* @param data: 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;
}
|