标题:
发送完地址后24c02一直不产生应答,附单片机程序
[打印本页]
作者:
大口吃橘子
时间:
2021-9-21 16:43
标题:
发送完地址后24c02一直不产生应答,附单片机程序
#include "mpu_i2c.h"
#include "usart.h"
//配置i2c端口
void I2C_GPIO_Config(void)
{
//定义结构体
GPIO_InitTypeDef GPIO_InitStruct;
//打开SDA与SCL端口时钟
RCC_APB2PeriphClockCmd(I2C_SDA_CLK,ENABLE);
RCC_APB2PeriphClockCmd(I2C_SCL_CLK,ENABLE);
//配置SDA端口
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//开漏复用输出
GPIO_InitStruct.GPIO_Pin = I2C_SDA_Pin;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(I2C_SDA_PORT,&GPIO_InitStruct);
//配置SCL端口
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//开漏复用输出
GPIO_InitStruct.GPIO_Pin = I2C_SCL_Pin;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(I2C_SCL_PORT,&GPIO_InitStruct);
}
void I2C_InitConfig(void)
{
I2C_GPIO_Config();
}
void delay(void)
{
uint8_t time = 10;
while(time--)
{
}
}
void I2C_START(void)
{
SDA_OUT();
I2C_SDA_1();
I2C_SCL_1();
delay();
I2C_SDA_0();
delay();
I2C_SCL_0();
delay();
}
void I2C_STOP(void)
{
SDA_OUT();
I2C_SDA_0();
I2C_SCL_1();
delay();
I2C_SDA_0();
delay();
}
void I2C_Ack(void)
{
I2C_SCL_0();
I2C_SDA_1();
delay();
I2C_SDA_1();
delay();
I2C_SDA_0();
delay();
I2C_SCL_1();
delay();
I2C_SCL_0();
delay();
I2C_SDA_1();
}
void I2C_NACK(void)
{
I2C_SCL_0();
I2C_SDA_0() ;
delay();
I2C_SDA_1();
delay();
I2C_SCL_1();
delay();
I2C_SCL_0();
delay();
I2C_SDA_0();
delay();
}
void I2C_Sent_Byte(uint8_t msg)
{
uint8_t i;
SDA_OUT();
I2C_SCL_0();
delay();
/* 先发送字节的高位bit7 */
for (i = 0; i < 8; i++)
{
if (msg & 0x80 ==1)
{
I2C_SDA_1();
}
else
{
I2C_SDA_0();
}
delay();
I2C_SCL_1();
delay();
I2C_SCL_0();
if (i == 7)
{
I2C_SDA_1(); // 释放总线
}
msg <<= 1; /* 左移一个bit */
delay();
}
I2C_SCL_0();
}
uint8_t I2C_Read_Byte(void)
{
uint8_t i;
uint8_t receive = 0;
/* 读到的第一位为数据的7bit位!!!
所以每次读取数据时都要将数据左移一位*/
I2C_SCL_1();//锁定SCL线,确保其稳定
for(i=0;i<8;i++)
{
receive <<= 1;
I2C_SCL_0();//读取数据时拉低SCL
delay();
if(I2C_SDA_State() == 1)
{
receive++;
}
I2C_SCL_0();
delay();
}
return receive;
}
void delay_us(uint8_t i)
{
while(i--)
{
}
}
uint8_t I2C_WaitAck(void)
{
uint8_t re;
I2C_SDA_1(); /* CPU释放SDA总线 */
delay();
I2C_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
delay();
if (I2C_SDA_State()) /* CPU读取SDA口线状态 */
{
re = 1;
}
else
{
re = 0;
}
I2C_SCL_0();
delay();
return re;
}
uint8_t EEPROM_Byte_Write(uint16_t _usAddress, uint16_t data)
{
uint8_t i;
//开始信号
I2C_START();
//发送地址
I2C_Sent_Byte(Slave_Addr | I2C_Write);
//检测应答
//delay();
//return printf("SDA的状态为:%d\n",I2C_SDA_State());
if(I2C_WaitAck() != 0)
{
return printf("写入失败,未检测到响应1\n");
}
//发送从机中的数据地址(起始地址)
I2C_Sent_Byte(_usAddress);
//检测应答
if(I2C_WaitAck() != 0)
{
return printf("写入失败,未检测到响应2\n");
}
for(i=0;i<8;i++)
{
I2C_Sent_Byte(data & 0x80);
I2C_Ack();
data <<= 1;
}
return printf("写入完成!!!\n");
}
uint8_t EEPROM_Byte_Read(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize)
{
uint8_t i;
//开始信号
//test SDA
//return printf("开始信号前SDA状态为:%d\n",READ_I2C_SDA());
I2C_START();
//发送地址
//test SDA
//return printf("开始信号后SDA状态为:%d\n",READ_I2C_SDA());
I2C_Sent_Byte(Slave_Addr | I2C_Write);
//test SDA
//return printf("发送地址后SDA状态为:%d\n",READ_I2C_SDA());
//检测应答
if(I2C_WaitAck() != 0)
{
return printf("读取失败,未检测到响应1\n");
}
//发送从机中的数据地址(起始地址)
I2C_Sent_Byte(_usAddress);
//检测应答
if(I2C_WaitAck() != 0)
{
return printf("读取失败,未检测到响应2\n");
}
//开始信号
I2C_START();
//发送地址
I2C_Sent_Byte(Slave_Addr | I2C_Read);
//检测应答
if(I2C_WaitAck() != 0)
{
return printf("读取失败,未检测到响应3\n");
}
//读取数据
for(i=0;i< _usSize;i++)
{
// if(I2C_GetFlagStatus(I2C_Driver,I2C_FLAG_BUSY) == SET)
// {
// return printf("他妈的锁死了,读取失败\n");
// }
_pReadBuf[i] = I2C_Read_Byte();//每次读取一个字节
if(i != (_usSize-1))
{
I2C_Ack();
}
else
{
I2C_NACK();
}
}
//发送停止信号
I2C_STOP();
return printf("读取完成!\n");
}
复制代码
作者:
大口吃橘子
时间:
2021-9-21 16:44
前前后后搞了几天了,真不知道问题出在了哪里
作者:
yzwzfyz
时间:
2021-9-21 22:28
用示波器看通讯的波形,是否与手册上说的相符。
作者:
lkc8210
时间:
2021-9-21 23:17
放入Protues仿真看波型时序
如有硬件示波器更好
作者:
sadv
时间:
2021-9-22 09:20
你的IIC_READ_BYTE函数,读取数据的时候为什么要先把SCL拉低????应该是先把SCL拉高,然后读取数据再拉低循环8次。按照你的操作,先把SCL拉高,读取之前又拉低了,这时候你读取即可能是高电平也可能是低电平,根据IIC的协议,这时候SDA上的电平是允许变化的,所以这么读是有问题的。建议你用逻辑分析仪去抓一下IIC,然后再结合你的代码分析。最好去看一下别人的IIC怎么写的,参考一下
作者:
188610329
时间:
2021-9-22 17:10
没仔细看,但是,看到STOP就觉得不太对劲了……
STOP 不是应该拉高时钟之后,拉高数据线么?为什么,拉高时钟之后,你SDA 还是 0?
void I2C_STOP(void)
{
SDA_OUT();
I2C_SDA_0();
I2C_SCL_1();
delay();
I2C_SDA_0(); // 这里不应该 SDA 1 么?
delay();
}
你仔细看看你的整个时序 我感觉 你的 读 ACK 那里 也 少一个 CLK 0,所以读不到 ACK
作者:
oblivionqqqqq
时间:
2021-9-22 17:28
用逻辑分析仪,抓波形,看发送接收有没有问题
作者:
sadv
时间:
2021-9-22 17:51
整个IIC的起始信号,停止信号等都有问题啊,都不用逻辑分析仪抓了,肯定通讯不成功的,你去看别人写好的IIC吧,对照着IIC的协议时序仔细看
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1