【GD32F307E-START】+I2C驱动的问题
[复制链接]
我的测试计划需要开通I2C通讯,我首先试图启用硬件I2C通讯,参照厂家EEPROM读写的范例,写了I2C单字节和多字节的读和写函数,也许是对I2C通讯的基础函数理解不透彻,调试了几天都没有成功。下面是硬件I2C的初始化代码,这是直接从范例复制过来的,应该没有错误:
void i2c_gpio_config(void)
{
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_I2C0);
gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7);
}
void i2c_config(void)
{
i2c_gpio_config();
rcu_periph_clock_enable(RCU_I2C0);
i2c_clock_config(I2C0,I2C0_SPEED,I2C_DTCY_2);
i2c_mode_addr_config(I2C0,I2C_I2CMODE_ENABLE,I2C_ADDFORMAT_7BITS,I2C0_SLAVE_ADDRESS7);
i2c_enable(I2C0);
i2c_ack_config(I2C0,I2C_ACK_ENABLE);
}
下面是单字节读的代码,程序运行到发送从机地址的即死循环,不知是何原因:
uint8_t i2c_addr8_byte_read(uint8_t i2c_addr, uint8_t dat_addr)
{
uint8_t data;
while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
i2c_start_on_bus(I2C0);
while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
i2c_master_addressing(I2C0, i2c_addr, I2C_TRANSMITTER);
while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND);
while(SET != i2c_flag_get(I2C0, I2C_FLAG_TBE));
i2c_enable(I2C0);
i2c_data_transmit(I2C0, dat_addr);
while(!i2c_flag_get(I2C0, I2C_FLAG_BTC));
i2c_start_on_bus(I2C0);
while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
i2c_master_addressing(I2C0, i2c_addr, I2C_RECEIVER);
while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND);
while(SET != i2c_flag_get(I2C0, I2C_FLAG_TBE));
data = i2c_data_receive(I2C0);
while(I2C_CTL0(I2C0)&0x0200);
i2c_ack_config(I2C0,I2C_ACK_ENABLE);
i2c_ackpos_config(I2C0,I2C_ACKPOS_CURRENT);
i2c_stop_on_bus(I2C0);
return data;
}
通过逻辑分析仪抓取的时序如下图(首行是SCL,第二行是SDA),从图上看不到正常的时钟时序:
硬件I2C调不通,于是我转而使用软件I2C通讯,下面是初始化和设置SDA引脚数据方向的代码,也许问题就出在设置SDA引脚方向的代码上:
void SI2C_Init(void)
{
rcu_periph_clock_enable(SCL_GPIO_CLK);
gpio_init(SCL_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SCL_PIN);
gpio_init(SDA_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, SDA_PIN);
}
void SDA_Dir(uint8_t dir)
{
if(dir)
gpio_init(SDA_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SDA_PIN);
else
gpio_init(SDA_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, SDA_PIN);
}
这些代码是我在沁恒CH579M开发板上正常使用的,移植过来之后首先是调整时钟的延时时间,尽管延时已经调整的符合要求,但读不到从设备发出的SDA数据,就象没有设置好SDA引脚为输入模式一样,下面是截取的时序图,从图上可以看出地址数据发出之后,没有收到从设备的ACK回应:
下图是程序两次对从设备发出地址信息,但没有回应:
我测试用的I2C设备是DS1307日历模块,模块不会有问题,在其他开发板上调换测试仪过的:
下面是模块近景:
从成功驱动LCD之后我就开始尝试开通I2C,弄了几天,反复调试软件I2C和硬件I2C,均没有成功,至今仍未找到解决办法。
|