程序代码如下,读写AD5161。写入的时候能够收到应答信号,但是读数据的时候读出的却总是00
/*
* 函数名: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);
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 ,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_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_IN_FLOATING;//GPIO_Mode_Out_PP;
GPIO_Init(SDA_PORT, &GPIO_InitStructure);
SCL_H;
SDA_H;
/*
RCC->APB2ENR|=1<<3; //先使能外设IO PORTB时钟
GPIOB->CRL&=0X00FFFFFF; //PB6/7 推挽输出
GPIOB->CRL|=0X33000000;
GPIOB->ODR|=3<<6; //PB6,7输出高
*/
}
/*
* 函数名: void I2C_delay(void)
* 描述 : 短暂延时
* 输入 : 无
* 输出 : 无
* 说明 : 内部定义的i可以优化速度,经测试最低到5还能写入
*/
static void I2C_delay(void)
{
u16 i=2000;
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线输出
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();
/*
SCL_L;
I2C_delay();
I2C_delay();
*/
// SDA_H; //释放总线
I2C_delay();
I2C_delay();
I2C_delay();
SCL_H;
I2C_delay();
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();
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();
Delay(50000*2);
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;
}
|