求教模拟I2C发数据,最后一位为1时波形异常

2019-08-22 15:54发布

本帖最后由 Alvanbai 于 2017-4-5 13:02 编辑

各位前辈好,请教一下。我用的模拟I2C,发送一个字节8bit的数据,发现只要最后一位数据为1,SDA就异常。最后一位为0的话是正常的,请教一下可能的原因,谢谢。

图中分别发送的是0xFE和0xFF黄线是SDA,红线是SDL。经过测试,发现规律只要是最后一位数据为1,波形就拉不下去。
0xFE 0xFE


0xFF 0xFF


驱动代码参考了这位前辈,感谢。http://www.openedv.com/posts/list/61112.htm
I2C.C
[mw_shl_code=c,true]/**
  ******************************************************************************
  * @file      IIC.c
  * @brief     simulation function
  * @CPU       STM32F10x
  * @compiler  Keil uVision V4.74
  * @author    Alex.fang(china shenzhen)
  * @copyright GPL
  * @version   V1.0.0
  * @date      02-Sept-2015
  ******************************************************************************
  * @attention
  */  
     

  
GPIO_InitTypeDef  GPIO_InitStructure;   
   
   

void IIC_Init(void)  
{                          
        RCC_APB2PeriphClockCmd(IIC_RCC_APB2Periph_GPIOx, ENABLE);   
        GPIO_InitStructure.GPIO_Pin = IIC_SDA_GPIO_Pin | IIC_SCL_GPIO_Pin;  
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出  //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);  
        GPIO_SetBits(IIC_GPIOx,IIC_SDA_GPIO_Pin | IIC_SCL_GPIO_Pin);  //PB10,PB11 输出高   
}  
  

void SDA_OUT(void)   
{   
        GPIO_StructInit(&GPIO_InitStructure);   
        GPIO_InitStructure.GPIO_Pin   = IIC_SDA_GPIO_Pin;   
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出  //推挽输出   //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
        GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);   
}   
  

void SDA_IN(void)   
{   
        GPIO_StructInit(&GPIO_InitStructure);   
        GPIO_InitStructure.GPIO_Pin   = IIC_SDA_GPIO_Pin;   
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     
        GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);   
}   
  
  
unsigned char SDA_READ(void)  
{  
        return GPIO_ReadInputDataBit(IIC_GPIOx, IIC_SDA_GPIO_Pin);  
}  
  

void IIC_SDA_1(void)  
{  
        GPIO_SetBits(IIC_GPIOx, IIC_SDA_GPIO_Pin);  
}  
  
  
void IIC_SDA_0(void)  
{  
        GPIO_ResetBits(IIC_GPIOx, IIC_SDA_GPIO_Pin);  
}  
  

void IIC_SCL_1(void)  
{  
        GPIO_SetBits(IIC_GPIOx, IIC_SCL_GPIO_Pin);  
}  
  

void IIC_SCL_0(void)  
{  
        GPIO_ResetBits(IIC_GPIOx, IIC_SCL_GPIO_Pin);   
}  
  
  
  
void IIC_Start(void)  
{  
    SDA_OUT();     //sda output   
    IIC_SDA_1();            
    IIC_SCL_1();  
    delay_us(4);  
    IIC_SDA_0();   //START:when CLK is high,DATA change form high to low   
    delay_us(4);  
    IIC_SCL_0();   //hold scl line, prepare to transmit data   
}      
  

void IIC_Stop(void)  
{  
    SDA_OUT();    //sda output mode   
    IIC_SCL_0();  
    IIC_SDA_0();  //STOP:when CLK is high DATA change form low to high   
    delay_us(4);  
    IIC_SCL_1();   
    IIC_SDA_1();  //indicate transmit over   
    delay_us(4);                              
}  
  

unsigned char IIC_Wait_Ack(void)  
{  
    unsigned char ucErrTime = 0;  
    SDA_IN();      //set as input mode   
    IIC_SDA_1();  
    delay_us(1);        
    IIC_SCL_1();  
    delay_us(1);      
    while(SDA_READ())  
    {  
        ucErrTime++;  
        if(ucErrTime > 250)  
        {  
            IIC_Stop();  
            return 1;  
        }  
    }  
    IIC_SCL_0(); //release scl line   
    return 0;   
}   
  
  
void IIC_Ack(void)  
{  
    IIC_SCL_0();  
    SDA_OUT();  
    IIC_SDA_0();  
    delay_us(2);  
    IIC_SCL_1();  
    delay_us(2);  
    IIC_SCL_0();  
}  
  
  
void IIC_NAck(void)  
{  
    IIC_SCL_0();  
    SDA_OUT();  
    IIC_SDA_1();  
    delay_us(2);  
    IIC_SCL_1();  
    delay_us(2);  
    IIC_SCL_0();  
}                                          
  
  
  
void IIC_Send_Byte(unsigned char txd)  
{                          
        unsigned char i;     
        SDA_OUT();         
        IIC_SCL_0();//push down scl  to start transmit data   
        for(i = 0; i < 8; ++i)  
        {               
        if(txd & 0x80)  
        {  
                IIC_SDA_1();  
        }  
        else  
        {  
                IIC_SDA_0();  
        }  
        txd <<= 1;        
        delay_us(2);     
        IIC_SCL_1();  
        delay_us(2);   
        IIC_SCL_0();      
        delay_us(2);  
        }   
}      
  
   
unsigned char IIC_Read_Byte(unsigned char ack)  
{  
        unsigned char i, res = 0;  
        SDA_IN();               //SDA input mode   
        for(i = 0; i < 8; ++i ){  
                IIC_SCL_0();   
                delay_us(2);  
                IIC_SCL_1();  
                res <<= 1;  
                if(SDA_READ()){  
                        res++;   
                }        
                delay_us(1);   
        }                    
        if (!ack){  
                IIC_NAck();//make NACK   
        }  
        else {  
                IIC_Ack(); //make ACK   
        }  
        return res;  
}  [/mw_shl_code]

I2C.H
[mw_shl_code=c,true]#define IIC_SDA_GPIO_Pin           GPIO_Pin_12
#define IIC_SCL_GPIO_Pin           GPIO_Pin_15
#define IIC_GPIOx                  GPIOB
#define IIC_RCC_APB2Periph_GPIOx   RCC_AHBPeriph_GPIOB



void IIC_Init(void);
  
void SDA_OUT(void);   
  
void SDA_IN(void);  
  
unsigned char SDA_READ(void);
  
void IIC_SDA_1(void);
  
void IIC_SDA_0(void);
  
void IIC_SCL_1(void);
  
void IIC_SCL_0(void);
  
void IIC_Start(void);      

void IIC_Stop(void);
  
unsigned char IIC_Wait_Ack(void);  

void IIC_Ack(void);

void IIC_NAck(void);
  
void IIC_Send_Byte(unsigned char txd);      

unsigned char IIC_Read_Byte(unsigned char ack);


#endif[/mw_shl_code]


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。