搜索
bottom↓
回复: 15

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

[复制链接]

出0入0汤圆

发表于 2013-5-9 22:28:32 | 显示全部楼层 |阅读模式
本帖最后由 liulangmao 于 2013-5-9 22:41 编辑

     目前总线上波形已经接近AT24C02数据手册上写和读的波形了,个人感觉读取应该是没有问题的,只是写入不能成功。调试期间有一将数据写入到了24C02且读了出来,另有一次是在板子重新上电时读出来,其余读出来都不对。




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. }
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入4汤圆

发表于 2013-5-10 08:15:35 | 显示全部楼层
1:要按照手册上的时序来,尤其是最后的应答一定要加上。
2:写每个数据之间要加点延时,否则会出现乱码。

出0入0汤圆

 楼主| 发表于 2013-5-14 18:19:05 | 显示全部楼层
唉,PIC18真的这么不待见,自己再顶一下。

出0入0汤圆

发表于 2013-5-9 22:28:33 | 显示全部楼层
用不了那么复杂,给你一个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;
}

出0入0汤圆

发表于 2013-5-15 17:43:51 | 显示全部楼层
从10地址读出一字节,值是0xac

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-5-29 16:02:02 | 显示全部楼层

        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);

感觉有应先改寄存器状态再发送

出0入4汤圆

发表于 2013-5-30 10:20:56 | 显示全部楼层
你们用的什么软件啊,好高端的样子。

求下载,求推荐。

出0入0汤圆

发表于 2013-5-30 14:07:43 | 显示全部楼层
你没检测总线空闲,

出0入0汤圆

发表于 2013-6-1 12:22:14 | 显示全部楼层
2楼8楼 说的很清楚了。

软件是逻辑分析仪自带的吧。

出0入0汤圆

 楼主| 发表于 2013-6-15 13:09:10 | 显示全部楼层
      问题已解决,应该是没有进行等待写入完成这一步。感谢楼上所有提示语帮助的坛友,话说赏金没平分功能抱歉了。。。
  1. //18F_I2C_HD
  2. #include <p18f14k50.h>                      //优先选用编译器路径头文件
  3. #include "18F_I2C_HD.h"
  4. #include "main.h"
  5. #include "Delay_us.h"


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

  15.         PIE1bits.SSPIE                =        1;
  16.        
  17.         ControlByte = 0xAE;                                // AT24C02地址1010,A2-A0:111,写入 0.
  18.         length        =        1;                                        //接受的字节长度 3 Byte

  19. }

  20. //----------------------------------------I2C写入数据--------------------------------------------
  21. void I2C_HD_Write(void)
  22. {
  23.         IdleI2C();                                                        // 确保总线空闲。
  24.         StartI2C();                                                        // 发出起始位。
  25.         while ( SSPCON2bits.SEN );                        // 等待起始位完成。
  26.        
  27.         WriteI2C( ControlByte );                        // 写控制位。
  28.         IdleI2C();                                                        // 确保总线空闲。
  29.        
  30.         WriteI2C( 0x01 );                                        // 地址 0x01.
  31.         IdleI2C();                                                        // 确保总线空闲。
  32.        
  33.         WriteI2C( 0x7B );                                        // 数据 0x7B.
  34.         IdleI2C();                                                        // 确保总线空闲。
  35.        
  36.         StopI2C();                          // 发送停止指令
  37.         while ( SSPCON2bits.PEN );                        // 等待停止指令完成
  38.         while (EEAckPolling(ControlByte));        // 等待写入周期完成。
  39. }


  40. //----------------------------------------I2C读取--------------------------------------------
  41. void I2C_HD_Read(void)
  42. {
  43.         unsigned char  *data;
  44.         data = &I2C_Data[0];
  45.         IdleI2C();                                                        // 确保总线空闲。
  46.         StartI2C();                                                        // 发出起始位。
  47.         while ( SSPCON2bits.SEN );                        // 等待起始位完成。
  48.        
  49.         WriteI2C( ControlByte );                        // 写控制位。
  50.         IdleI2C();                                                        // 确保总线空闲。
  51.        
  52.         WriteI2C( 0x01 );                                        // 地址 0x01.
  53.         IdleI2C();                                                        // 确保总线空闲。

  54.         RestartI2C();                                                // 重启总线。
  55.         while ( SSPCON2bits.RSEN );                 // 等待总线重启完成。
  56.        
  57.         WriteI2C( ControlByte | 0x01 );                // 读取。
  58.         IdleI2C();                                                        // 确保总线空闲。
  59.         getsI2C( data, length );                        // 读取数值。
  60.        
  61.         NotAckI2C();                                                // 发送无应答。
  62.         while ( SSPCON2bits.ACKEN );                // 等待应答过程结束。
  63.         StopI2C();                          // 发送停止指令
  64.         while ( SSPCON2bits.PEN );                        // 等待停止指令完成        
  65. }
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出100入101汤圆

发表于 2014-11-22 16:35:39 | 显示全部楼层
lyl3257 发表于 2013-5-9 22:28
用不了那么复杂,给你一个PIC24 的程序参考
#include
#define USE_AND_OR // To enable AND_OR mask setti ...

StartI2C1,这个是pic的外设库函数么?

出0入0汤圆

发表于 2014-11-26 11:50:18 | 显示全部楼层
是的外设库函数

出0入0汤圆

发表于 2014-11-26 11:50:52 | 显示全部楼层
fengyunyu 发表于 2014-11-22 16:35
StartI2C1,这个是pic的外设库函数么?

是的外设库函数

出0入0汤圆

发表于 2015-9-1 08:13:37 | 显示全部楼层
本帖最后由 dianzidianzi 于 2015-9-2 00:18 编辑

楼主现在I2C程序搞定了吗?能否指点一下我,我也遇到了你一样的问题

出0入0汤圆

 楼主| 发表于 2015-9-1 23:09:16 | 显示全部楼层
dianzidianzi 发表于 2015-9-1 08:13
楼主现在I2C程序搞定了吗?能否指点一下我,我也遇到了你一样的问题 Q 243-44-1165 ...

如果使用PIC库的话,可以直接调用我在10楼回复的函数就可完成读写操作。

出0入0汤圆

发表于 2015-9-2 00:03:10 | 显示全部楼层
本帖最后由 dianzidianzi 于 2015-9-2 00:21 编辑
liulangmao 发表于 2015-9-1 23:09
如果使用PIC库的话,可以直接调用我在10楼回复的函数就可完成读写操作。


IdleI2C();   这个函数具体内容是什么。能否把整个程序直接发到我的邮箱 dianzidianzixin@qq.com ,非常感谢!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 08:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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