求助PIC18F14K50硬件I2C读写AT24C02问题。

2020-02-06 10:11发布

本帖最后由 liulangmao 于 2013-5-9 22:41 编辑

     目前总线上波形已经接近AT24C02数据手册上写和读的波形了,个人感觉读取应该是没有问题的,只是写入不能成功。调试期间有一将数据写入到了24C02且读了出来,另有一次是在板子重新上电时读出来,其余读出来都不对。
PCB.jpg (470.79 KB, 下载次数: 0) 下载附件 2013-5-9 22:27 上传
PCB图,中间图红星是去掉的电阻。
再不行就只能用模拟的方法了。

部分源代码

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

  10.         PIE1bits.SSPIE                =        1;
  11.        
  12. }

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

  18.         SSPBUF        =        0xAE;                                //AT24C02地址1010,A2-A0:111,写入 0.
  19.         while(SSPSTATbits.BF);                        // SSPBUF为空.
  20.        
  21.         SSPCON2bits.ACKDT        =        1;
  22.         SSPCON2bits.ACKEN        =        1;
  23.         while(SSPCON2bits.ACKEN);                //        NotAckI2C1()
  24.                
  25.         Delay_us(1);
  26.                
  27.         SSPBUF        =        0x0F;                                //地址.
  28.         while(SSPSTATbits.BF);                        // SSPBUF为空.
  29.        
  30.         SSPCON2bits.ACKDT        =        1;
  31.         SSPCON2bits.ACKEN        =        1;
  32.         while(SSPCON2bits.ACKEN);                //        NotAckI2C1()
  33.                
  34.         Delay_us(1);
  35.                                
  36.         SSPBUF        =        0x7C;                                //数据124.
  37.         while(SSPSTATbits.BF);                        // SSPBUF为空.

  38.         while(SSPCON2bits.ACKSTAT)                // 收到应答说明器件写操作成功,否则一直查询 。
  39.         {
  40.                 SSPBUF        =        0xAE;                                //AT24C02地址1010,A2-A0:111,写入 0.
  41.                 while(SSPSTATbits.BF);                        // SSPBUF为空.
  42.         }
  43.        
  44. //        Delay_us(1);
  45.        
  46.         SSPCON2bits.ACKDT        =        1;
  47.         SSPCON2bits.ACKEN        =        1;
  48.         while(SSPCON2bits.ACKEN);                //        NotAckI2C1()
  49.                
  50.         //Delay_us(1);
  51.        
  52.         SSPCON2bits.PEN=1;
  53.         while(SSPCON2bits.PEN);                //StopI2C2()  
  54.                
  55.         Delay_us(1);
  56.        
  57. }


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

  63.         SSPBUF        =        0xAE;                                //AT24C02地址1010,A2-A0:111,寻址使用伪写 1.
  64.         while(SSPSTATbits.BF);                        // SSPBUF为空.
  65.                
  66. //        Delay_us(1);
  67.        
  68.         SSPCON2bits.ACKDT        =        1;
  69.         SSPCON2bits.ACKEN        =        1;
  70.         while(SSPCON2bits.ACKEN);                //        NotAckI2C1()
  71.                
  72.         Delay_us(1);
  73.        
  74.         SSPBUF        =        0x0F;                                //地址.
  75.         while(SSPSTATbits.BF);                        // SSPBUF为空.
  76.                
  77.        
  78.         SSPCON2bits.ACKDT        =        1;
  79.         SSPCON2bits.ACKEN        =        1;
  80.         while(SSPCON2bits.ACKEN);                //        NotAckI2C1()

  81.         Delay_us(1);

  82.         SSPCON2bits.SEN        =        1;                        // 1:在SDA 和SCL 引脚上发起启动条件。由硬件自动清零。
  83.         while ( SSPCON2bits.SEN );                //
  84.        
  85.         SSPBUF        =        0xAF;                                //AT24C02地址1010,A2-A0:111,读取 1.
  86.         while(SSPSTATbits.BF);                        // SSPBUF为空.
  87.        
  88.         SSPCON2bits.ACKDT        =        1;
  89.         SSPCON2bits.ACKEN        =        1;
  90.         while(SSPCON2bits.ACKEN);                //        NotAckI2C1()
  91.                
  92.         Delay_us(1);
  93.        
  94.         SSPCON2bits.RCEN        =        1;                //使能接受。
  95.         while(!SSPSTATbits.BF);                        // SSPBUF为满.
  96.        
  97.         SSPCON2bits.ACKDT        =        0;
  98.         SSPCON2bits.ACKEN        =        1;
  99.         while(SSPCON2bits.ACKEN);                //        AckI2C1()
  100.                
  101. //        Delay_us(1);
  102.                
  103.         SSPCON2bits.PEN=1;
  104.         while(SSPCON2bits.PEN);                //StopI2C2()  
  105.        
  106.         Buff_Number        =        SSPBUF;                                //数据123.
  107. }


  108. void interrupt Isr(void)
  109. {
  110.         if(TMR0IF        ==        1)
  111.         {
  112.                 TMR0IF        =        0;
  113.                 LED        =        ~LED;
  114.                 if(LED == 1)
  115.                 {
  116.                         I2C_HD_Write();
  117.                         I2C_HD_Read();
  118.                         Cont_Number = Buff_Number;
  119.                 }
  120.                 else
  121.                 {
  122.                         Cont_Number = 12345;
  123.                 }
  124.                 TMR0H        =        Timer0_RH;
  125.                 TMR0L        =        Timer0_RL;
  126.         }
  127.        
  128.         if(SSPIF        ==        1)
  129.         {
  130.         SSPIF = 0;                                                //清中断。
  131.         }
  132. }
复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
15条回答
lyl3257
1楼-- · 2020-02-06 15:44
用不了那么复杂,给你一个PIC24 的程序参考
#include <p24FJ32GA002.h>
#define USE_AND_OR // To enable AND_OR mask setting for I2C.
#include <i2c.h>
#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 int ms);
void i2c_init(void)
{
  TRISBbits.TRISB8 = 0;   // SCL1
  TRISBbits.TRISB9 = 0;  //SDA1
  OpenI2C1( I2C_ON, I2C_BRG );
}
//写2402,值写到指定的地址
void AT2402_Write(uchar address,uchar val)  //AT2402寄存器地址0-255h
{
    StartI2C1();                //Send the Start Bit
     IdleI2C1();                    //Wait to complete
    MasterWriteI2C1(0XA0);    // addresses the chip      
       IdleI2C1();
    MasterWriteI2C1(address);     // mem address
        IdleI2C1();
    MasterWriteI2C1( val );    // write value into minutes register
        IdleI2C1();
   StopI2C1();        //Send the Stop condition
        IdleI2C1();
}
//读2402,存储器地址的值****************************************
uchar AT2402_Read(uchar address)  //AT2402存储器地址0-255h
{
  uchar ret;
    StartI2C1();                //Send the Start Bit
     IdleI2C1();                    //Wait to complete

   MasterWriteI2C1(0xa0);    // addresses the chip      
    IdleI2C1();
  MasterWriteI2C1(address);    // addresses the chip      
    IdleI2C1();

RestartI2C1();        //Send the Restart condition
__delay32(40);
      IdleI2C1();
  MasterWriteI2C1(0XA1);    // addresses the chip  
     IdleI2C1();
    ret = MasterReadI2C1();        // read one byte

  StopI2C1();        //Send the Stop condition
        IdleI2C1();        //Wait to complete
  return ret;
}
ibichao
2楼-- · 2020-02-06 17:34
1:要按照手册上的时序来,尤其是最后的应答一定要加上。
2:写每个数据之间要加点延时,否则会出现乱码。
liulangmao
3楼-- · 2020-02-06 21:56
 精彩回答 2  元偷偷看……
lyl3257
4楼-- · 2020-02-07 03:06
从10地址读出一字节,值是0xac

READ_BIT.JPG (131.68 KB, 下载次数: 0)

下载附件

2013-5-15 17:43 上传

northseawind
5楼-- · 2020-02-07 07:19

        while ( SSPCON2bits.SEN );                //

        SSPCON2bits.ACKDT        =        1;
        SSPCON2bits.ACKEN        =        1;

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

感觉有应先改寄存器状态再发送
huarana
6楼-- · 2020-02-07 10:08
你们用的什么软件啊,好高端的样子。

求下载,求推荐。

一周热门 更多>