求助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条回答
zenith1032
1楼-- · 2020-02-07 12:37
你没检测总线空闲,
Friendz
2楼-- · 2020-02-07 16:05
 精彩回答 2  元偷偷看……
liulangmao
3楼-- · 2020-02-07 20:33
      问题已解决,应该是没有进行等待写入完成这一步。感谢楼上所有提示语帮助的坛友,话说赏金没平分功能抱歉了。。。

AT24C02读取.png (36.66 KB, 下载次数: 0)

下载附件

2013-6-15 13:07 上传

  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. }
复制代码
fengyunyu
4楼-- · 2020-02-08 01:14
lyl3257 发表于 2013-5-9 22:28
用不了那么复杂,给你一个PIC24 的程序参考
#include
#define USE_AND_OR // To enable AND_OR mask setti ...

StartI2C1,这个是pic的外设库函数么?
lyl3257
5楼-- · 2020-02-08 01:27
是的外设库函数
lyl3257
6楼-- · 2020-02-08 04:16
fengyunyu 发表于 2014-11-22 16:35
StartI2C1,这个是pic的外设库函数么?

是的外设库函数

一周热门 更多>