基于PIC24FJ256GB106读写ROM 24C1024时,读出数据总是不对

2019-07-16 01:41发布

基于PIC24FJ256GB106读写ROM 24C1024时,读出数据总是不对,哪位大牛给看看呀
读出数据一直都是0xffff,不知道问题出在哪里呀呀


#include <p24fxxxx.h>
void Initi2C(void);
void WaitMI2C(void);
void I2C_write(unsigned char data);
void I2C_BYTE_WRITE(unsigned char addhigh,unsigned char addmid,unsigned char addlow,unsigned char data);
unsigned char I2C_BYTE_READ(unsigned char addhigh,unsigned char addmid,unsigned char addlow);
void I2C_ACK_CHECK(void);

#define        StartI2C()  I2C1CONbits.SEN=1                                //启动I2C
#define        StopI2C()        I2C1CONbits.PEN=1                                //停止I2C
#define        RstartI2C()        I2C1CONbits.RSEN=1                                //重新启动I2C      
#define        NACKI2C()        I2C1CONbits.ACKDT=1;I2C1CONbits.ACKEN=1                //发送不应答信号
#define        ACKI2C()        I2C1CONbits.ACKDT=0;I2C1CONbits.ACKEN=1                //发送应答信号
#define        RecI2C()        I2C1CONbits.RCEN=1                                //使能接收允许位

#define CMD_W24C01  0XA0
#define CMD_R24C01  0XA1
unsigned char                I2C_Data;                      //读写24C01的数据暂存单元
unsigned char                I2C_Addr;                        //读写24C01的地址暂存单元               
unsigned char                I2C_DATA_BACK;                //写入24C01的数据备份单元
unsigned char       I2C_STEP = 0;       //调试变量,一旦I2C死机,监视执行到哪个步骤死机

void delay_ms(unsigned char count)   //1ms延时
{
        unsigned int i,j;
            
        for(i = 0 ; i < count ; i++)
        {
            for(j = 0 ; j < 0x2eda; j++);
        }
}

int main(void)
{

    CLKDIV = 0;                         //CPU时钟为32MHZ,外设总线与CPU时钟一致
    while(OSCCONbits.LOCK == 0);        //等待PLL时钟稳定,如果上电后有重要IO要马上设置,此语句可挪到IO初使化后   
    _DISI = 1 ;                         //使能DISI指令,某些内建函数需要配合DISI指令操作

        CM2CON = 0 ;        //模拟比较器2关闭,RB0~3的比较器复用功能关闭
    ODCB &= 0x0000 ;    //RB0~3设置为正常的双向口,其它不变
    AD1PCFGL |= 0xFFFF ;//AN0~3设置为数字口,其它不变

    TRISB &= 0X0000 ;   //TRISB低4位清0,置输出
                        //实验板L4~L1,默认分别对应RB3~0,全亮

    InitI2C();
        I2C_Addr = 0x66;                    //0到127之间有效
        I2C_Data=0x49;
        I2C_DATA_BACK = 0X49;

        I2C_BYTE_WRITE(0x00,0x00,I2C_Addr,I2C_Data);

//        I2C_ACK_CHECK();                    //dsPIC30/PIC24可直接调用此函数后进行读,PIC32还得加延时(错误:执行该语句便进入死循环)

        LATB=0x0002;
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);

        I2C_Data = 0;

        I2C_Data = I2C_BYTE_READ(0x00,0x23,I2C_Addr); //如果读回来的即为写下去的0x49,读写都OK,
                                  //如果读回来为0XFF,未必代表写失败。
        LATB=I2C_Data&0X000F ;    //LATB低4位送1,其它不变

    while(1);
}
/*
函数功能:I2C初使化
入口参数:无
出口参数:无
调用说明:无
*/
void InitI2C(void)
{
    _ODD9 = 1;              //RD9/10设置OC功能打开
    _ODD10 = 1;             //
    LATDbits.LATD9 = 1;
    LATDbits.LATD10 = 1;
    TRISDbits.TRISD9 = 1;
    TRISDbits.TRISD10 = 1;

    I2C1CON = 0X8000;
        I2C1STAT = 0;
        I2C1BRG = 159;              //16mips,调整到接近100KHZ
}
/*
函数说明:通用的等待I2C各种动作完成函数
入口参数:无
出口参数:无
调用说明:无
*/
void WaitMI2C(void)
{
    while(_MI2C1IF == 0);       //判断MI2CIF以判定各种动作是否完成
    Nop();
    Nop();
        _MI2C1IF = 0;               //清标志位       
}

void I2C_write(unsigned char data)
{
    while (I2C1STATbits.TBF);       //传输正在进行中,等待
    I2C1TRN = data;                 //写入数据
}


void I2C_BYTE_WRITE(unsigned char addhigh,unsigned char addmid,unsigned char addlow,unsigned char data)
{
    unsigned char temp_i2cdata,add;
    StartI2C();                                        //1, 启动I2C
        WaitMI2C();                                        //等待启动完成

        add=CMD_W24C01|addhigh;

        I2C_write(add);                //2, 送入命令,
                                                                //地址+读写方式,地址为101 0000 ,写方式=0               
        WaitMI2C();                                        //等待写入完成
    temp_i2cdata = I2C1RCV;     //


        I2C_write(addmid);                        //3,要操作24C1024的高地址值发送到I2C总线
        WaitMI2C();
        temp_i2cdata = I2C1RCV;     //


        I2C_write(addlow);                        //3,要操作24C1024的地址值发送到I2C总线
        WaitMI2C();
        temp_i2cdata = I2C1RCV;     //

        I2C_write(data);                        //4,要写入24C01的数据值发送到I2C总线
        WaitMI2C();       
    temp_i2cdata = I2C1RCV;     //

        StopI2C();                                        //5,发送停止信号
        WaitMI2C();                             //
            //
}
unsigned char I2C_BYTE_READ(unsigned char addhigh,unsigned char addmid,unsigned char addlow)
{
    unsigned char data;
    unsigned char temp_i2cdata,add_w,add_r;
        StartI2C();                                        //1, 启动I2C
        WaitMI2C();                                        //等待启动完成

        add_w=CMD_W24C01|addhigh;

        I2C_write(add_w);                //2, 送入命令,
                                                                //地址+读写方式,地址为101 0000 ,写方式=0               
        WaitMI2C();                                        //等待写入完成
        temp_i2cdata = I2C1RCV;     //


        I2C_write(addmid);                        //3,要操作24C1024的高地址值发送到I2C总线
        WaitMI2C();
        temp_i2cdata = I2C1RCV;     //


        I2C_write(addlow);                        //3,要操作24C1024的地址值发送到I2C总线
        WaitMI2C();
        temp_i2cdata = I2C1RCV;     //

        RstartI2C();                                //4,发送重启动信号
        WaitMI2C();

        add_r=CMD_R24C01|addhigh;
        I2C_write(add_r);                //5, 送入命令,
                                                                //地址+读写方式,地址为101 0000 ,读方式=1               
        WaitMI2C();                                        //等待写入完成
    temp_i2cdata = I2C1RCV;     //

        RecI2C();                                        //6,使能接收
        WaitMI2C();

        data = I2C1RCV;                                //7,保存数据

        NACKI2C();                                        //8,发送非应答信号,停止从发送方的发送
        WaitMI2C();

        StopI2C();                                        //9,发送停止信号
        WaitMI2C();                                       
        return        (data);                                //10,返回读到的数据
}
/*
函数功能;通过发读命令检测I2C总线是否空闲
入口参数:无
出口参数:无
调用说明:PIC24F/dsPIC30F上均可用,PIC32上还需配合延时函数

*/

void I2C_ACK_CHECK(void)
{
        do
        {
                StartI2C();
                WaitMI2C();
                I2C_write(CMD_R24C01);
                WaitMI2C();
                StopI2C();
                WaitMI2C();
            LATB=I2C1STATbits.ACKSTAT&0X000F;  
        }
        while(I2C1STATbits.ACKSTAT);
               
}

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