问答

汇集网友智慧,解决技术难题

21ic问答首页 - SC95F8517模拟 IIC无应答

模拟 iic sd define ck AC

SC95F8517模拟 IIC无应答

Huanghuiz2021-04-14
#define IIC_SDA P16
#define IIC_SCL P15
#define READ_SDA P1CON &= 0xbf
#define SDA_OUT()        P1CON |= 0x40,P1PH |=0x40
#define SDA_IN()        P1CON &= 0xbf,P1PH |=0x40

#define ADDR_PLF2105D 0x50


void delay_us( uint us)               
{
         uint x;
         for(x=us;x>0;x--);
}
void delay_ms(u16 nms)
{
        u32 i;
        for(i=0;i<nms;i++) delay_us(3200);
}

void IIC_Init(void)
{
    P1CON = 0xFF;        //SDA与SCL设置为推挽输出模式
        P1PH  = 0x00;        //SDA与SCL的上拉电阻打开
    IIC_SDA = 1;        //IIC_SDA 置高电平
    IIC_SCL = 1;        //IIC_SCL 置低电平  
}

//产生IIC起始信号
void IIC_Start(void)
{
        SDA_OUT();     //sda线输出
        IIC_SDA = 1;                    
        IIC_SCL = 1;
        delay_us(32);
        IIC_SDA=0;//START:when CLK is high,DATA change form high to low
        delay_us(32);
        IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}          
//产生IIC停止信号
void IIC_Stop(void)
{
        SDA_OUT();//sda线输出
        IIC_SCL=0;
        IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
        delay_us(32);
        IIC_SCL=1;
        IIC_SDA=1;//发送I2C总线结束信号
        delay_us(32);                                                                  
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
uchar IIC_Wait_Ack(void)
{
        uchar ucErrTime=0;
        SDA_IN();      //SDA设置为输入  
        IIC_SDA=1;
        delay_us(6);          
        IIC_SCL=1;
        delay_us(6);         
        while(READ_SDA)
        {
                ucErrTime++;
                if(ucErrTime>250)
                {
                        IIC_Stop();
                        return 1;
                }
        }
        IIC_SCL=0;//时钟输出0           
        return 0;  
}
//产生ACK应答
void IIC_Ack(void)
{
        IIC_SCL=0;
        SDA_OUT();
        IIC_SDA=0;
        delay_us(6);
        IIC_SCL=1;
        delay_us(6);
        IIC_SCL=0;
}
//不产生ACK应答                    
void IIC_NAck(void)
{
        IIC_SCL=0;
        SDA_OUT();
        IIC_SDA=1;
        delay_us(6);
        IIC_SCL=1;
        delay_us(6);
        IIC_SCL=0;
}                                                                              
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答                          
void IIC_Send_Byte(uchar txd)
{                        
    uchar t;   
    SDA_OUT();             
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
                        IIC_SDA=(txd&0x80)>>7;
                txd<<=1;           
                delay_us(6);   //对TEA5767这三个延时都是必须的
                IIC_SCL=1;
                delay_us(6);
                IIC_SCL=0;       
                delay_us(6);
    }         
}             
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
uchar IIC_Read_Byte(uchar ack)
{
        unsigned char i,receive=0;
        SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
        {
        IIC_SCL=0;
        delay_us(32);
        IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
                delay_us(16);
    }                                         
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
       
    return receive;
}
//IIC连续写
//addr:器件地址
//reg:寄存器地址
//len:写入长度
//buf:数据区
//返回值:0,正常
//    其他,错误代码
uchar IIC_Write_Len(uchar addr,uchar len,uchar *buf)
{
        uchar i;
            IIC_Start();
        IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令       
        if(IIC_Wait_Ack())        //等待应答
        {
                IIC_Stop();                 
                return 1;               
        }
        for(i=0;i<len;i++)
        {
                IIC_Send_Byte(buf[i]);        //发送数据
                if(IIC_Wait_Ack())                //等待ACK
                {
                        IIC_Stop();         
                        return 1;                 
                }               
        }   
    IIC_Stop();         
        return 0;       
}
//IIC连续读
//addr:器件地址
//reg:要读取的寄存器地址
//len:要读取的长度
//buf:读取到的数据存储区
//返回值:0,正常
//    其他,错误代码
uchar IIC_Read_Len(uchar addr,uchar len,uchar *buf)
{

            IIC_Start();
        IIC_Send_Byte((addr<<1)|1);//发送器件地址+读命令       
            IIC_Wait_Ack();                //等待应答
        delay_ms(5);
        while(len)
        {
                if(len==1) *buf=IIC_Read_Byte(0);//读数据,发送nACK
                else *buf=IIC_Read_Byte(1);                //读数据,发送ACK  
                len--;
                delay_us(64);
                buf++;
        }   
            IIC_Stop();        //产生一个停止条件
        return 0;       
}

本人新手初次使用赛元模拟IIC,原先是利用STM32F103来模拟IIC,后移植过来 发现SDA_OUT();似乎并未起作用

通过逻辑分析仪,只执行void IIC_Ack(void)得到的波形图如下图

channel2 3 是在stm32 上可以用的IIC应答时序

SDA SCL是移植在赛元的IIC时序

小白求解












回答 +关注 1
347人浏览 1人回答问题 分享 举报
1 个回答

您需要登录后才可以回复 登录 | 注册