iic读写测试,为什么主机接受应答时读取SDA一直为1,接受失败,求大神帮忙解决

BadJiang 2017-11-22 04:56:26
ii2c.h
#ifndef __I2C_H
#define __I2C_H
#include "stm32f10x.h"

void I2C_Configuration(void);
void I2C_SDA_OUT(void);
void I2C_SDA_IN(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_Ack(void);
void I2C_NAck(void);
u8 I2C_Wait_Ack(void);
void I2C_Send_Byte(u8 txd);
u8 I2C_Read_Byte(void);

void I2CWriteByteToDevice16(u8 deviceWriteAddr,u16 registerAddr,u8 dat);
u8 I2CReadByteFromDevice16(u8 deviceWriteAddr,u16 registerAddr);
#endif

i2c.c
#include "delay.h"
#include "I2C.h"

#define I2C_SCL GPIO_Pin_6
#define I2C_SDA GPIO_Pin_7
#define GPIO_I2C GPIOB

#define I2C_SCL_H GPIO_SetBits(GPIO_I2C,I2C_SCL)
#define I2C_SCL_L GPIO_ResetBits(GPIO_I2C,I2C_SCL)

#define I2C_SDA_H GPIO_SetBits(GPIO_I2C,I2C_SDA)
#define I2C_SDA_L GPIO_ResetBits(GPIO_I2C,I2C_SDA)

void I2C_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin=I2C_SCL|I2C_SDA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);

I2C_SCL_H;
I2C_SDA_H;
}

void I2C_SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin=I2C_SDA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}

void I2C_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin=I2C_SDA;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}

//产生起始信号
void I2C_Start(void)
{
I2C_SDA_OUT();

I2C_SDA_H;
I2C_SCL_H;
delay_us(5);
I2C_SDA_L;
delay_us(6);
I2C_SCL_L;
}

//产生停止信号
void I2C_Stop(void)
{
I2C_SDA_OUT();

I2C_SCL_L;
I2C_SDA_L;
delay_us(6);
I2C_SCL_H;
I2C_SDA_H;
delay_us(6);
}

//主机产生应答信号ACK
void I2C_Ack(void)
{
I2C_SCL_L;
I2C_SDA_OUT();
I2C_SDA_L;
delay_us(2);
I2C_SCL_H;
delay_us(5);
I2C_SCL_L;
}

//主机不产生应答信号NACK
void I2C_NAck(void)
{
I2C_SCL_L;
I2C_SDA_OUT();
I2C_SDA_H;
delay_us(2);
I2C_SCL_H;
delay_us(5);
I2C_SCL_L;
}
//等待从机应答信号
//返回值:1 接收应答失败
// 0 接收应答成功
u8 I2C_Wait_Ack(void)
{
u8 tempTime=0;

I2C_SDA_IN();

I2C_SDA_H;
delay_us(1);
I2C_SCL_H;
delay_us(1);

while(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
{
tempTime++;
if(tempTime>250)
{
I2C_Stop();
return 1;
}
}
I2C_SCL_L;
return 0;
}
//I2C 发送一个字节
void I2C_Send_Byte(u8 txd)
{
u8 i=0;

I2C_SDA_OUT();
I2C_SCL_L;//拉低时钟开始数据传输

for(i=0;i<8;i++)
{
if((txd&0x80)>0) //0x80 1000 0000
I2C_SDA_H;
else
I2C_SDA_L;

txd<<=1;
I2C_SCL_H;
delay_us(2); //发送数据
I2C_SCL_L;
delay_us(2);
}
}


//I2C 读取一个字节
u8 I2C_Read_Byte(void)
{
u8 i=0,receive=0;

I2C_SDA_IN();
for(i=0;i<8;i++)
{
I2C_SCL_L;
delay_us(2);
I2C_SCL_H;
receive<<=1;
if(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
receive|=0x01; //////////////////////////////////////////////////
delay_us(1);
}

return receive;
}


void I2CWriteByteToDevice16(u8 deviceWriteAddr,u16 registerAddr,u8 dat)
{
I2C_Start();
I2C_Send_Byte(deviceWriteAddr); //设备写地址
I2C_Wait_Ack();
I2C_Send_Byte(registerAddr>>8); //先写高8位地址
I2C_Wait_Ack();
I2C_Send_Byte(registerAddr&0x00ff); //再写低8位地址
I2C_Wait_Ack();

I2C_Send_Byte(dat);
I2C_Wait_Ack();
I2C_Stop();
delay_ms(10);
}


u8 I2CReadByteFromDevice16(u8 deviceWriteAddr,u16 registerAddr)
{
u8 dat=0;
I2C_Start();
I2C_Send_Byte(deviceWriteAddr); //设备写地址
I2C_Wait_Ack();
I2C_Send_Byte(registerAddr>>8); //先写高8位地址
I2C_Wait_Ack();
I2C_Send_Byte(registerAddr&0x00ff); //再写低8位地址
I2C_Wait_Ack();

I2C_Start();
I2C_Send_Byte(deviceWriteAddr|0x01); //修改设备地址的读写标志位
I2C_Wait_Ack();
dat=I2C_Read_Byte();
I2C_NAck();
I2C_Stop();
return dat;
}

main.c
#include "stm32f10x.h"
#include "system.h"
#include "i2c.h"
#include "delay.h"

void RCC_Configuration(void);
u8 dat=7;
u8 rece;

#define AT24C64_WRITE_ADDR 0xA0 //AT24C64的IIC写地址
int main(void)
{
RCC_Configuration();
delay_init(72);
NVIC_Config();
I2C_Configuration();
delay_ms(1);

I2CWriteByteToDevice16(AT24C64_WRITE_ADDR,0x01,dat);
delay_ms(10);
rece=I2CReadByteFromDevice16(AT24C64_WRITE_ADDR,0x01);
delay_ms(10);

while(1);
}

...全文
2378 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
小帖 2017-12-08
  • 打赏
  • 举报
回复
能不能返回i2c的状态寄存器,
躺着睡的蜗牛 2017-12-07
  • 打赏
  • 举报
回复
读完一Byte数据后要主机侧要发一个ACK,而不是等待从机的ACK。 最后一Byte数据读完后主机侧要发一个NAK
xiaofengxiyu 2017-12-01
  • 打赏
  • 举报
回复
用示波器看下,再看自己的时序延时设置是否合理
tianxj001 2017-11-25
  • 打赏
  • 举报
回复
学习IIC 串口等,最好条件是有个示波器,如果没有,至少弄一个淘宝上便宜的数字逻辑分析器,几十大毛,可分析串口、IIC、SPI等协议。 https://item.taobao.com/item.htm?spm=a230r.1.14.98.585db400PbsMtI&id=542457595407&ns=1&abbucket=2#detail 现在这样,我们都不明白说的是什么:我写入单个字节7,结果出来0xFF?这个是你用 I2C_Send_Byte(u8 txd) 写的?然后是测试到的数据线是FF?
zgl7903 2017-11-25
  • 打赏
  • 举报
回复
I2C启动后的 第一个字节 应该是丛机地址, 连接的丛是什么? 7 是什么设备的地址? 示波器测量 CLK 频率, 看是否满足要求
thinkers 2017-11-23
  • 打赏
  • 举报
回复 1
应答电平如果一直不变,可能是硬件有问题。建议换个板子测试。
BadJiang 2017-11-23
  • 打赏
  • 举报
回复
我写入单个字节7,结果出来0xFF' ' .按照方式我也改了的,还是那个问题,我qq805150499,你能发个完整的代码我吗?
Acuity. 2017-11-22
  • 打赏
  • 举报
回复
1、IO口设置为开漏模式(GPIO_Mode_Out_OD),无须切换输入、输出方向; 2、无应答,检查时序是否正确、从机地址。
Rampage_SS 2017-11-22
  • 打赏
  • 举报
回复
这种情况下一般借助示波器查看自己的波形是否正常。
BadJiang 2017-11-22
  • 打赏
  • 举报
回复
拜托各位大牛们了

21,599

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧