主发送I2C发送完数据后没有接收到应答信号

2019-07-14 15:02发布

我用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;   
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
18条回答
TOPCB
1楼-- · 2019-07-16 15:04
这个是我找的例程,我以前用过是可以用的。103下面使用,配置的是输出。
YY599566
2楼-- · 2019-07-16 15:35
TOPCB 发表于 2018-12-24 11:20
这个是我找的例程,我以前用过是可以用的。103下面使用,配置的是输出。

就是不用管IO的方向呗,我把我的设置IO方向的语句去掉,的确是可以接收到ACK的,但也有一条语句接收的是NACK,看这个样子是不用设置IO的方向,但是我之前参考了两三版程序都有设置IO的方向,那到底用不用设置IO的方向。我们这个IO的方向一直都配置的是输出啊
TOPCB
3楼-- · 2019-07-16 18:45
我这里用的是没有配置。可能MCU不同,你应该参考ST的。
YY599566
4楼-- · 2019-07-16 23:53
TOPCB 发表于 2018-12-24 11:43
我这里用的是没有配置。可能MCU不同,你应该参考ST的。

这个是我用逻辑分析仪抓到的数据,第二个写寄存器地址,收到的响应是NACK,这说明什么呢?
TOPCB
5楼-- · 2019-07-17 03:34
写完以后,记得要STOP一下,可能是因为8563处于忙状态。
YY599566
6楼-- · 2019-07-17 09:23
TOPCB 发表于 2018-12-24 12:13
写完以后,记得要STOP一下,可能是因为8563处于忙状态。

您说的这个STOP一下,应该不是发一个停止信号吧,因为I2C的时序不是发送从地址等待ACK,发送要写的数据等ACK,最后发STOP信号啊。还是你说的这个stop是把SDA和SCL都拉高呢?

一周热门 更多>