GD32F427VK软件模拟IIC,但是IIC总会有收不到ACK的情况,
/*
* description:本文件为模拟I2C驱动代码
* version: 1.0
* Change Logs:
* Date Author Notes
* 2020-01-17 yina create
*
*/
#include "audio_i2c.h"
#include "audio_port_i2c.h"
#include "systick.h"
/**********************************************************
* @NOTE 产生IIC起始信号
* @param
* @return
*********************************************************/
void audio_iic_start(void)
{
audio_i2c_sda_out(); //sda线输出
audio_i2c_sda_set(1);
audio_i2c_scl_set(1);
delay_1us(4);
audio_i2c_sda_set(0);//START:when CLK is high,DATA change form high to low
delay_1us(4);
audio_i2c_scl_set(0);//钳住I2C总线,准备发送或接收数据
}
/**********************************************************
* @note 产生IIC停止信号
* @param
* @return
*********************************************************/
void audio_iic_stop(void)
{
audio_i2c_sda_out();//sda线输出
audio_i2c_scl_set(0);
audio_i2c_sda_set(0);//STOP:when CLK is high DATA change form low to high
delay_1us(4);
audio_i2c_scl_set(1);
audio_i2c_sda_set(1);//发送I2C总线结束信号
delay_1us(4);
}
/**********************************************************
* @note 等待应答信号到来
* @param
* @return 1:接收应答失败 0:接收应答成功
*********************************************************/
uint8_t audio_iic_wait_ack(void)
{
uint8_t ucErrTime=0;
audio_i2c_sda_in(); //SDA设置为输入
audio_i2c_sda_set(1);
delay_1us(1);
audio_i2c_scl_set(1);
delay_1us(1);
while(audio_i2c_sda_read())
{
ucErrTime++;
if(ucErrTime>250)
{
audio_iic_stop();
return 1;
}
}
audio_i2c_scl_set(0);//时钟输出0
audio_i2c_sda_out();
return 0;
}
/**********************************************************
* @note 产生ACK应答信号
* @param
* @return
*********************************************************/
static void audio_iic_ack(void)
{
audio_i2c_scl_set(0);
audio_i2c_sda_out();
audio_i2c_sda_set(0);
delay_1us(2);
audio_i2c_scl_set(1);
delay_1us(2);
audio_i2c_scl_set(0);
}
/**********************************************************
* @note 不产生ACK应答信号
* @param
* @return
*********************************************************/
void audio_iic_noack(void)
{
audio_i2c_scl_set(0);
audio_i2c_sda_out();
audio_i2c_sda_set(1);
delay_1us(2);
audio_i2c_scl_set(1);
delay_1us(2);
audio_i2c_scl_set(0);
}
/**********************************************************
* @note IIC发送一个字节
* @param
* @return 1:有应答 0:无应答
*********************************************************/
void audio_iic_sendbyte(uint8_t txd)
{
uint8_t t;
audio_i2c_sda_out();
audio_i2c_scl_set(0);//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
if( (txd & 0x80) == 0x80 )
{
audio_i2c_sda_set(1);
}
else audio_i2c_sda_set(0);
// audio_i2c_sda_set((txd&0x80)>>7);
txd<<=1;
delay_1us(2); //对TEA5767这三个延时都是必须的
audio_i2c_scl_set(1);
delay_1us(2);
audio_i2c_scl_set(0);
delay_1us(2);
}
}
/**********************************************************
* @note 读1个字节,ack=1时,发送ACK,ack=0,发送nACK
* @param
* @return 1:有应答 0:无应答
*********************************************************/
uint8_t audio_iic_Readbyte(uint8_t txd)
{
unsigned char i,receive=0;
audio_i2c_sda_in();//SDA设置为输入
for(i=0;i<8;i++ )
{
audio_i2c_scl_set(0);
delay_1us(2);
audio_i2c_scl_set(1);
receive<<=1;
if(audio_i2c_sda_read())receive++;
delay_1us(1);
}
audio_i2c_scl_set(0);
audio_i2c_sda_out();
if (!txd)
audio_iic_noack();//发送nACK
else
audio_iic_ack(); //发送ACK
return receive;
}
|