STM32模拟I2C与ad5161通讯,为什么接收不到应答信号?
/*
* 函数名:void I2C_GPIO_Config(void)
* 描述 : I2C管脚初始化
* 输入 :无
* 输出 : 无
*/
void I2C_GPIO_Config(void)//void I2C_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB ,ENABLE);
// PB6-I2C1_SCL、PB7-I2C1_SDA
//初始化SCL管脚
GPIO_InitStructure.GPIO_Pin = SCL_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//PP;
GPIO_Init(SCL_PORT, &GPIO_InitStructure);
//初始化SDA管脚
GPIO_InitStructure.GPIO_Pin = SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//;
GPIO_Init(SDA_PORT, &GPIO_InitStructure);
SCL_H;
SDA_H;
}
/*
* 函数名: void I2C_delay(void)
* 描述 : 短暂延时
* 输入 : 无
* 输出 : 无
* 说明 : 内部定义的i可以优化速度,经测试最低到5还能写入
*/
static void I2C_delay(void) //
{
u16 i=2000;
while(i)
{
i--;
}
}
static void I2C_delay1(void) //
{
u16 i=500;
while(i)
{
i--;
}
}
void I2C_Delay(vu32 nCount)
{
for(; nCount != 0; nCount--);
}
/*
* 函数名: bool I2C_Start(void)
* 描述 : 起始信号
* 输入 : 无
* 输出 : TRUE : 成功
FALSE : 失败
* 说明 : IIC起始信号定义为当SCL为高电平(HIGH)时,SDA线从高到低的跳变
*/
bool I2C_Start(void)
{
SDA_OUT(); //sda线输出
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
SDA_L;
I2C_delay();
SCL_L; //钳住I2C总线,准备发送或接收数据,避免在SCL为高电平期间,再次发出起始信号或者停止信号
//I2C_delay();
return TRUE;
}
/*
* 函数名: static void I2C_Stop(void)
* 描述 : 终止信号
* 输入 : 无
* 输出 : 无
* 说明 :IIC停止信号定义为当SCL为高电平(HIGH)时,SDA线从低到高的跳变
*/
void I2C_Stop(void)
{
SDA_OUT(); //sda线输出
SCL_L;
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SDA_H;
I2C_delay();
}
/*
* 函数名: static void I2C_Ack(void)
* 描述 :产生应答信号 ,主机从从机读取数据后,向从机发出应答信号
* 输入 : 无
* 输出 : 无
* 说明 : 主机在接收到从机的数据后,向从机返回一个应答信号,
继续通信,在SCL为高电平器件,SDA一直保持低电平表示应答
*/
static void I2C_Ack(void)
{
SCL_L;
SDA_OUT();
// I2C_delay();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L; //SCL再输出低电平,保证在SCL为高电平期间,SDA始终保持高电平,表示应答信号
//I2C_delay();
}
/*
* 函数名: void I2C_NoAck(void)
* 描述 : 不产生应答信号,主机接收到从机的数据后,不发出应答信号
* 输入 : 无
* 输出 : 无
* 说明 :
*/
static void I2C_NoAck(void)
{
SCL_L;
SDA_OUT();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L; //SCL再次输出低电平,保证SCL为高时,SDA一直为高
//I2C_delay();
}
/*
* 函数名: bool I2C_WaitAck(void)
* 描述 : 等待应答信号
* 输入 : 无
* 输出 : TRUE : 有应答
FALSE : 无应答
* 说明 : IIC通信时,接收到数据,从机(Slave)会发出ACK信号,
一般是一个低电平 信号出现在SDA线上,若主机检测到,则认为此次通信成功
*/
static bool I2C_WaitAck(void)
{
u16 ucErrTime=0;
SDA_IN();
SDA_H; //释放总线
I2C_delay1();
SCL_H;
I2C_delay1();
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>500)
{
I2C_Stop();
return FALSE;
}
}
SCL_L;
// I2C_delay();
return TRUE;
}
/*
* 函数名: static void I2C_SendByte(u8 SendByte)
* 描述 : 发送一个字节
* 输入 : SendByte : 字节数据
* 输出 : 无
* 说明 : 数据从高位到低位
*/
static void I2C_SendByte(u8 SendByte)
{
u8 i;
SDA_OUT();
SCL_L; //拉低时钟开始数据传输
for(i=0;i<8;i++)
{
if((SendByte<<i)&0x80)
{
SDA_H;
}
else
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
}
/*
* 函数名: static u8 I2C_ReceiveByte(void)
* 描述 : 读取一个字节
* 输入 : 无
* 输出 : 字节数据
* 说明 : ReceiveByte : 数据从高位到低位
*/
u8 I2C_ReceiveByte(u8 ack)
{
u8 i,ReceiveByte=0;
SDA_IN();
// SDA_H;
// I2C_delay();
for(i=0;i<8;i++)
{
SCL_L;
I2C_delay();
SCL_H;
ReceiveByte<<=1;
// I2C_delay();
if(READ_SDA)
ReceiveByte++;
I2C_delay();
}
if(!ack)
I2C_NoAck(); //不回应
else
I2C_Ack(); //回应
return ReceiveByte;
}
/*
* 函数名: Delay(vu32 nCount)
* 描述 : 延时函数
* 输入 :
* 输出 :
* 说明 :
*/
void Delay_ms(vu32 nCount)
{
for(; nCount != 0; nCount--);
}
/*
* 函数名: bool I2C_WriteByte(u8 DeviceAddress, u16 cmd, u8 SendByte)
* 描述 : 写入1字节数据
* 输入 : DeviceAddress : 器件地址
cmd:控制命令
SendByte : 要写入数据
* 输出 : TRUE : 成功
FALSE : 失败
* 说明 :
*/
bool I2C_WriteByte(u8 DeviceAddress, u16 cmd, u8 SendByte)
{
I2C_Start();
I2C_SendByte(DeviceAddress);//写入器件地址
I2C_WaitAck();
I2C_SendByte(cmd); //写入控制命令
I2C_WaitAck();
I2C_SendByte(SendByte); //写入数据
I2C_WaitAck();
I2C_Stop();
return TRUE;
}
/*
* 函数名: bool I2C_ReadByte(u8* pBuffer, u8 length, u16 ReadAddress, u8 DeviceAddress)
* 描述 : 读出1串数据
* 输入 : pBuffer : 要读取数据缓冲区指针
length : 待读取长度
DeviceAddress : 器件地址
* 输出 : TRUE : 成功
FALSE : 失败
* 说明 : 跨页写入1串数据
*/
u8 I2C_ReadByte(u8 DeviceAddress)
{
u8 pBuffer=0xFE;
I2C_Start();
I2C_SendByte(DeviceAddress);//设置器件地址 0x59
I2C_WaitAck();
I2C_delay();
pBuffer=I2C_ReceiveByte(0); //接收数据无应答位
I2C_Stop();
return pBuffer;
}
|