完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我用STM32F103做主I2C,用PCF8563做从I2C,用模拟I2C进行的通信,但是主给从发送了数据之后,接收的到都是NACK信号,为什么接收不到ACK呢?代码如下
#include "stm32f10x.h" #include "stm32f10x_i2c.h" #include "stm32f10x_gpio.h" #include "i2c_mgr.h" #include "stm32f10x_it.h" #include "rtc_mgr.h" #include "timer_mgr.h" void I2C_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //------------RTC_SDA->PB_11RTC_SCL->PB_10---------------------------------------- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//¿ªÂ©Êä³ö GPIO_Init(GPIOB,&GPIO_InitStructure); GPIO_SetBits(GPIOB,GPIO_Pin_11|GPIO_Pin_10); } void I2C_START(void) { SDA_OUT(); SCL_H(); SDA_H(); delay_us(5); SDA_L(); delay_us(5); } void I2C_Send_Byte(u8 txd) { u8 t; SDA_OUT(); for(t=0;t<8;t++) { SCL_L(); delay_us(1); if((txd&0x80)>>7) { SDA_H(); SCL_H(); delay_us(5); txd<<=1; } else { SDA_L(); SCL_H(); delay_us(5); txd<<=1; } } SCL_L(); } void I2C_STOP(void) { SDA_OUT(); SCL_L(); delay_us(5); SDA_L(); delay_us(5); SCL_H(); delay_us(5); SDA_H(); delay_us(5); } u8 I2C_Wait_ACK(void) { u8 waitcnt = 0; u8 slaveack = 0; SCL_L(); SDA_IN(); //delay_us(5); SCL_H(); delay_us(5); if(READ_SDA()) { SCL_L(); return 1; } SCL_L(); delay_us(5); return 0; } void I2C_ACK(void) { SCL_L(); SDA_OUT(); SDA_L(); delay_us(5); SCL_H(); delay_us(5); SCL_L(); } void I2C_NACK(void) { SCL_L(); SDA_OUT(); SDA_H(); delay_us(5); SCL_H(); delay_us(5); SCL_L(); } u8 I2C_Read_Byte(unsigned char ack) { unsigned char i,receive=0; SDA_IN(); for(i=0;i<8;i++ ) { SCL_H(); delay_us(5); receive<<=1; if(READ_SDA())receive++; delay_us(5); SCL_L(); delay_us(5); } if (!ack) I2C_NACK(); else I2C_ACK(); return receive; } void I2C_Write(u8 WriteAddr,u8 Dat) { I2C_START(); I2C_Send_Byte(PCF8563_ADDR_W); I2C_Wait_ACK(); I2C_Send_Byte(WriteAddr); I2C_Wait_ACK(); I2C_Send_Byte(Dat); I2C_Wait_ACK(); I2C_STOP(); } u8 I2C_Read(u8 ReadAddr) { u8 ReData,t=0; I2C_START( ); I2C_Send_Byte(PCF8563_ADDR_W); I2C_Wait_ACK(); I2C_Send_Byte(ReadAddr); I2C_Wait_ACK(); I2C_START(); I2C_Send_Byte(PCF8563_ADDR_R); I2C_Wait_ACK(); ReData = I2C_Read_Byte(0); I2C_STOP(); return ReData; } |
|
相关推荐
35个回答
|
|
|
|
|
|
是哪一步收不到应答呢
|
|
|
|
|
|
|
|
用示波器看看引脚的波形, I2C时序对不对 I2C从设备地址对不对 |
|
|
|
|
|
|
|
本帖最后由 watercici 于 2018-3-27 09:29 编辑 我是用逻辑分析仪抓的,时序和地址发的没有问题 |
|
|
|
不好意思,工程不方便贴,我这个程序还没有调试到主循环中,只是main函数中的初始化,我觉得其他模块应该不影响它,我的从设备是PCF8563,我觉得它是不是没有收到数据啊 |
|
|
|
楼主看一下8563的硬件地址是否正确。
|
|
|
|
知道第一个字节发送的时候没收到ACK意味着什么吗? 就是说,在这个地址就没找到有I2C设备。如果确定你的8563地址没错,那看看前面一个干扰脉冲怎么回事。 |
|
|
|
zhouxk 发表于 2018-12-24 10:39 那个干扰脉冲有影响吗?因为我在初始化IO口后,IO口的电平都是拉低的,然后我在初始化中加了一句“ GPIO_SetBits(GPIOB,GPIO_Pin_11|GPIO_Pin_10);”之后,就会有前面的那个低脉冲了 |
|
|
|
|
|
|
|
|
|
我看了一下您的程序,我先问一下,您的程序中没有对SDA方向进行控制吗,当等ACK的时候SDA的方向不应该是输入吗 |
|
|
|
这个是我找的例程,我以前用过是可以用的。103下面使用,配置的是输出。
|
|
|
|
就是不用管IO的方向呗,我把我的设置IO方向的语句去掉,的确是可以接收到ACK的,但也有一条语句接收的是NACK,看这个样子是不用设置IO的方向,但是我之前参考了两三版程序都有设置IO的方向,那到底用不用设置IO的方向。我们这个IO的方向一直都配置的是输出啊 |
|
|
|
我这里用的是没有配置。可能MCU不同,你应该参考ST的。
|
|
|
|
这个是我用逻辑分析仪抓到的数据,第二个写寄存器地址,收到的响应是NACK,这说明什么呢? |
|
|
|
写完以后,记得要STOP一下,可能是因为8563处于忙状态。
|
|
|
|
您说的这个STOP一下,应该不是发一个停止信号吧,因为I2C的时序不是发送从地址等待ACK,发送要写的数据等ACK,最后发STOP信号啊。还是你说的这个stop是把SDA和SCL都拉高呢? |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
2105 浏览 1 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
1941 浏览 3 评论
4537 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
2084 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
2599 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 22:35 , Processed in 0.794597 second(s), Total 79, Slave 73 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号