查看: 918|回复: 0
打印 上一主题 下一主题

PIC18F14K50硬件I2C读写AT24C02问题。

[复制链接]
跳转到指定楼层
沙发
发表于 2015-10-15 08:27:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  目前总线上波形已经接近AT24C02数据手册上写和读的波形了,个人感觉读取应该是没有问题的,只是写入不能成功。调试期间有一将数据写入到了24C02且读了出来,另有一次是在板子重新上电时读出来,其余读出来都不对。




PCB图,中间图红星是去掉的电阻。
再不行就只能用模拟的方法了。

部分源代码

void I2C_HD_Init(void)
{
        //MSSP状态寄存器(I2C模式)
        SSPSTAT                                =        0x80;        //压摆率控制位,使用100KHz标准速率,SMBus 选择位,不开启
        SSPADD                                =         0x1D;        //(Fosc/100000)/4 - 1;        //100KHz总线频率 12MHz/100KHz/4-1 = 0x1D;
        SSPCON1                                =        0x28;        //I2C 主模式,时钟 = FOSC/(4 * (SSPADD + 1)),同步串口使能位,开启
        SSPCON2                                =        0x00;        //Clear Control Bits
        DDRBbits.RB4                =        1;                                                //开启SDA和SCL为输入
        DDRBbits.RB6                =        1;         

        PIE1bits.SSPIE                =        1;

}

//----------------------------------------I2C写入数据--------------------------------------------
void I2C_HD_Write(void)
{
        SSPCON2bits.SEN        =        1;                        // 1:在SDA 和SCL 引脚上发起启动条件。由硬件自动清零。
        while ( SSPCON2bits.SEN );                //

        SSPBUF        =        0xAE;                                //AT24C02地址1010,A2-A0:111,写入 0.
        while(SSPSTATbits.BF);                        // SSPBUF为空.

        SSPCON2bits.ACKDT        =        1;
        SSPCON2bits.ACKEN        =        1;
        while(SSPCON2bits.ACKEN);                //        NotAckI2C1()

        Delay_us(1);

        SSPBUF        =        0x0F;                                //地址.
        while(SSPSTATbits.BF);                        // SSPBUF为空.

        SSPCON2bits.ACKDT        =        1;
        SSPCON2bits.ACKEN        =        1;
        while(SSPCON2bits.ACKEN);                //        NotAckI2C1()

        Delay_us(1);

        SSPBUF        =        0x7C;                                //数据124.
        while(SSPSTATbits.BF);                        // SSPBUF为空.

        while(SSPCON2bits.ACKSTAT)                // 收到应答说明器件写操作成功,否则一直查询 。
        {
                SSPBUF        =        0xAE;                                //AT24C02地址1010,A2-A0:111,写入 0.
                while(SSPSTATbits.BF);                        // SSPBUF为空.
        }

//        Delay_us(1);

        SSPCON2bits.ACKDT        =        1;
        SSPCON2bits.ACKEN        =        1;
        while(SSPCON2bits.ACKEN);                //        NotAckI2C1()

        //Delay_us(1);

        SSPCON2bits.PEN=1;
        while(SSPCON2bits.PEN);                //StopI2C2()  

        Delay_us(1);

}


//----------------------------------------I2C读取--------------------------------------------
void I2C_HD_Read(void)
{
        SSPCON2bits.SEN        =        1;                        // 1:在SDA 和SCL 引脚上发起启动条件。由硬件自动清零。
        while ( SSPCON2bits.SEN );                //

        SSPBUF        =        0xAE;                                //AT24C02地址1010,A2-A0:111,寻址使用伪写 1.
        while(SSPSTATbits.BF);                        // SSPBUF为空.

//        Delay_us(1);

        SSPCON2bits.ACKDT        =        1;
        SSPCON2bits.ACKEN        =        1;
        while(SSPCON2bits.ACKEN);                //        NotAckI2C1()

        Delay_us(1);

        SSPBUF        =        0x0F;                                //地址.
        while(SSPSTATbits.BF);                        // SSPBUF为空.


        SSPCON2bits.ACKDT        =        1;
        SSPCON2bits.ACKEN        =        1;
        while(SSPCON2bits.ACKEN);                //        NotAckI2C1()

        Delay_us(1);

        SSPCON2bits.SEN        =        1;                        // 1:在SDA 和SCL 引脚上发起启动条件。由硬件自动清零。
        while ( SSPCON2bits.SEN );                //

        SSPBUF        =        0xAF;                                //AT24C02地址1010,A2-A0:111,读取 1.
        while(SSPSTATbits.BF);                        // SSPBUF为空.

        SSPCON2bits.ACKDT        =        1;
        SSPCON2bits.ACKEN        =        1;
        while(SSPCON2bits.ACKEN);                //        NotAckI2C1()

        Delay_us(1);

        SSPCON2bits.RCEN        =        1;                //使能接受。
        while(!SSPSTATbits.BF);                        // SSPBUF为满.

        SSPCON2bits.ACKDT        =        0;
        SSPCON2bits.ACKEN        =        1;
        while(SSPCON2bits.ACKEN);                //        AckI2C1()

//        Delay_us(1);

        SSPCON2bits.PEN=1;
        while(SSPCON2bits.PEN);                //StopI2C2()  

        Buff_Number        =        SSPBUF;                                //数据123.
}


void interrupt Isr(void)
{
        if(TMR0IF        ==        1)
        {
                TMR0IF        =        0;
                LED        =        ~LED;
                if(LED == 1)
                {
                        I2C_HD_Write();
                        I2C_HD_Read();
                        Cont_Number = Buff_Number;
                }
                else
                {
                        Cont_Number = 12345;
                }
                TMR0H        =        Timer0_RH;
                TMR0L        =        Timer0_RL;
        }

        if(SSPIF        ==        1)
        {
        SSPIF = 0;                                                //清中断。
        }
}
复制代码
附件: 您需要 登录 才可以下载或查看,没有帐号?注册
最佳答案

lyl3257
查看完整内容
用不了那么复杂,给你一个PIC24 的程序参考 #include #define USE_AND_OR // To enable AND_OR mask setting for I2C. #include #define Fosc        (16000000) #define Fcy         (Fosc/2) //#define Fsck        400000 //400k #define Fsck        100000 //100k //#define I2C_BRG        79 #define I2C_BRG        ((Fcy/2/Fsck)-1) #define uchar unsigned #define uint16 unsigned int void __delay32(unsigned long cycles); void DelayMS(unsigned ...
转载

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表