关于PIC16F887的I2C通信

[复制链接]
 楼主| zhuguangpeng 发表于 2012-10-23 13:34 | 显示全部楼层 |阅读模式
我参照  877的例程 拷到 887里面结果仿真的时候出现问题,但现在问题不知道出现在什么地方? 我看了数据手册 感觉没有什么变化啊。  主机的程序

#include <pic.h>       
  
  //__CONFIG (HS & LVPDIS & WDTDIS);
  
#define  B1 RC0   // 按键B1状态由RC0端口输入
#define        XTAL_FREQ        4        // 外接晶振主频,单位为MHz

void DelayMS(unsigned int ms) //定义延时函数
{
  unsigned int j=0;
  for(ms;ms>0;ms--)
   for(j=27*XTAL_FREQ;j>0;j--) // 1MHz时约是27,其它主频请酌情修改
   {
   }
}  
void main( void )
{
  unsigned char i=1;
      //        TRISC0=1;    // RC0用于读取按钮B1的状态
       
        SSPEN=0;    // 关闭MSSP模块,初始化完毕后再打开
       
  TRISC3=1;   // 把SCL设为输入引脚
  TRISC4=1;   // 把SDA设为输入引脚
  SSPCON2=0;
   WCOL=0;     // 写冲突检测位清零,若发送数据不正确请检查此位   
  SSPM3=1;    //SSPM=1000,I2C主模式
  SSPM2=0;
  SSPM1=0;
  SSPM0=0;
   SMP=1;
  // I2C波特率=Fosc/(4*(SSPADD+1))
  // SSPADD=[(Fosc/(BandRate*4)]-1
  SSPADD = 0x9;            // 当主频为4Mhz时波特率为100kbps
  CKP=1;
  CKE=0;     // 使用I2C协议规范电平
       // 关闭斜率控制

  SSPIF=0;      //若使用SSPIF作为信号发送状态位则需要清空此位
  
  SSPEN=1;    // 使能MSSP模块
   
        while (1)
        {
   // if(B1==0)  // 若按键B1有变化
  //  {
      //DelayMS(100); // 消除机械按键前沿抖动
     // if(B1==0)  // 再判断为0说明是一次正常按键
     // {
        SEN=1;  // 发送起始位
        while(SEN); // SEN=1说明未发送完毕
        // 循环退出说明SEN=0,即发送完毕

   
        SSPBUF = 0b10010000; // 从机地址为0b1001000,写操作
        while(R_nW);  //RW=1说明数据发送进行中
        // 循环退出说明RW=0,即发送完毕
        if(ACKSTAT) // ACKSTAT为1说明未收到从机应答
          while(1); // 死循环,便于调试,实际项目中应做错误处理
         
        SSPBUF = i; //向从机写入数据i,即发送数据i
        while(R_nW);  //RW=1说明数据发送进行中
        // 循环退出说明RW=0,即发送完毕
        if(ACKSTAT) // ACKSTAT为1说明未收到从机应答
          while(1); // 死循环,便于调试,实际项目中应做错误处理
        
        PEN=1;  // 发送停止位
        while(PEN); // PEN=1说明未发送完毕
        // 循环退出说明PEN=0,即发送完毕

               i++;  // 为了能看到效果,发生数据自加一
        DelayMS(100); // 过滤机械按键的后沿抖动
      //}
   // }
         
        }
       
}
  从机的程序

/*  PIC16F877 I2C从机模式接收数据例程
*  把收到的数据显示在数码管上
*
*/

#include <pic.h>        // 改用PIC16F877控制

//  __CONFIG (HS & LVPDIS & WDTDIS);
  const char NumFont[10]={0x3F,0x06,0x5B,0x4F,0x66,
           0x6D,0x7D,0X07,0x7F,0x6F}; // 共阴极数码管字形码

interrupt ISR(void)
{
        char tmp;
        if(SSPIF==1)
        {
                SSPIF=0;
                if(D_nA==1)  // 1 是数据
                {
                        if(BF==1)  // 缓冲区满,说明从主机收到一个字节
                        {
                                tmp=SSPBUF;  // 保存收到的普通数据
                                PORTD=NumFont[tmp];  // 显示收到的数据
                        }
                        else  // BF=0,主机读取结束
                        {
                                if(R_nW==1) // 读标志位有效,说明主机还在继续读数据
                                {
          SSPBUF=0x06; // 把主机要的数据保存在SSPBUF中等待主机读取                                         
                                }
                                else
                                {  // 读标志位无效,说明主机已经读取完最后一个字节了
                                }
                        }
                }
                else  //0 是地址
                {
                        tmp=SSPBUF;
                        if( (tmp & 0b00000001)!=0) // R/W =1,read
                        {
                                SSPBUF=0x06;  // 准备好数据等待下一次主机读取
                        }
                        else  //R/W=0, write
                        {
                                // 等待下一次主机来数据放到SSPBUF中
                        }
                }
        }
CKP=1;
SSPOV=0; //  从机释放SCL

}
           
I2C_Init()
{
        SSPSTAT=0;
        TRISC3=1;
        TRISC4=1;
        SSPCON2=0B10000000;
        SSPADD=0B10010000; // 从机地址码范围:1001000x
        SSPCON=0B00110110;  
        SSPIE=1; // 允许SSPIF产生中断
        GIE=1;
        PEIE=1;
}

void main( void )
{
  unsigned char i=0,EEP_Address=0,EEP_Data=0;
         TRISD=0; // 为了读取按钮B1的状态
         PORTD=0;
        I2C_Init();    // 初始化I2C
        while (1)
        {  // 等待中断产生
        }

在用887 仿真的时候会出现如图所示的错误 难道是不可以通用还是有什么其他的问题啊?
       
}

本帖子中包含更多资源

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

×
NE5532 发表于 2012-10-23 14:20 | 显示全部楼层
按功能模块逐个调试,不要想一抄了事。
airwill 发表于 2012-10-25 20:54 | 显示全部楼层
I2C 主从机联合调试, 的确是个蛮讨厌的事情, 出了问题两方面都要考虑, 建议用个好的工具, 比如逻辑分析仪来帮助你分析, 问题是出在了主机还是从机, 收发的数据是否合法等等.
chengqing3968 发表于 2013-9-16 15:41 | 显示全部楼层
敢问楼主实现了嘛……求指导!
涵潇舒雅 发表于 2013-10-21 15:59 | 显示全部楼层
chengqing3968 发表于 2013-9-16 15:41
敢问楼主实现了嘛……求指导!

问一下 你有没有实现啊 我也想咨询一下
涵潇舒雅 发表于 2013-10-21 15:59 | 显示全部楼层
chengqing3968 发表于 2013-9-16 15:41
敢问楼主实现了嘛……求指导!

请问你的实现了吗???
涵潇舒雅 发表于 2013-10-21 16:01 | 显示全部楼层
airwill 发表于 2012-10-25 20:54
I2C 主从机联合调试, 的确是个蛮讨厌的事情, 出了问题两方面都要考虑, 建议用个好的工具, 比如逻辑分析仪来 ...

我用protues仿真能到成功,但是实际应用却出了问题,从机的SSPIF没有置位,进入不了中断,很是不理解、、
涵潇舒雅 发表于 2013-10-22 09:52 | 显示全部楼层
airwill 发表于 2012-10-25 20:54
I2C 主从机联合调试, 的确是个蛮讨厌的事情, 出了问题两方面都要考虑, 建议用个好的工具, 比如逻辑分析仪来 ...

版主我也有关于i2c的问题,能不能帮我分析一下啊,不胜感激
caoyonglu 发表于 2013-12-11 07:45 | 显示全部楼层
问题解决了没,如何解决的
949155525 发表于 2013-12-20 23:11 | 显示全部楼层
逻辑分析仪   妙解决
Anlen 发表于 2014-6-12 15:32 | 显示全部楼层
为什么SSPIF一直都不置位,?
小鱼儿1045 发表于 2014-6-19 14:41 | 显示全部楼层
IIC基本就是时序问题!还有数据格式。
perry_peng 发表于 2014-6-20 08:43 | 显示全部楼层
不用中断不可以吗
perry_peng 发表于 2014-6-20 09:10 | 显示全部楼层
本帖最后由 perry_peng 于 2014-6-20 09:15 编辑

中断麻烦,我以前用的与pcf8574通信。
非中断模式:

  1. uint8 i2c_waitIdle()
  2. {
  3.   uint16 timeout = 0x3ff;
  4.   /**<
  5.    * RW or SEN or RSEN or PEN or RCEN or ACKEN will indicate if the MSSP
  6.    * is in Idle mode.
  7.    */
  8.   while ((SSPSTAT & 0x04 /*RW*/) || (SSPCON2 & 0x1f))  
  9.     if (!--timeout)                                        // Check timeout.
  10.       return 1;
  11.   return 0;
  12. }

  13. uint8 pcf8574_write_port(uint8 addr, uint8 val)
  14. {
  15.   uint8 ret = 1;
  16.   
  17.   if (i2c_waitIdle())
  18.     goto __i2c_write_finish;
  19.   delayUsx(5);
  20.   /*SSPCON2bits.*/SEN = 1;          // Initiate Start condition on SDA and SCL pins.
  21.   delayUsx(15);
  22.   if (i2c_waitIdle())               // Wait for bus idle
  23.     goto __i2c_write_finish;
  24.   delayUsx(5);
  25.   SSPBUF = 0x40 | (addr << 1);      // send address bits with R/W bit
  26.   if (SSPCON2 & 0x40)               // ACKSTAT = 0; Acknowledge was received from slave.
  27.     goto __i2c_write_finish;
  28.   delayUsx(15);
  29.   if (i2c_waitIdle())               // Wait for bus idle
  30.     goto __i2c_write_finish;
  31.   delayUsx(5);
  32.   SSPBUF = val;                     // send data.
  33.   if (SSPCON2 & 0x40)               // ACKSTAT = 0; Acknowledge was received from slave.
  34.     goto __i2c_write_finish;
  35.   delayUsx(15);
  36.   ret = 0;
  37. __i2c_write_finish:
  38.   i2c_waitIdle();                   // Wait for bus idle.
  39.   delayUsx(5);
  40.   /*SSPCON2bits.*/PEN = 1;          // Initiate STOP condition.
  41.   delayUsx(35);
  42.   
  43.   return ret;
  44. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

23

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部