打印
[家电应用]

中颖79F6442目标板TWI通讯测试

[复制链接]
1119|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
rwf5956|  楼主 | 2024-6-21 15:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 rwf5956 于 2024-6-22 08:50 编辑

问题:主机发出START指令后,TWICON相应的中断标志位未产生,START发送不成功,主机一直在跑START发送检测,从机一直在等待
指令说明:
1、相应的寄存器配置
        CLKCON |=0x08;
         Delay();
         CLKCON |=0x04;//时钟
        
         TWITOUT = 0x02; //打开 SCL,SDA 上拉电阻
         TWIBR=0x02; //配置发送波特率,禁止总线超时判断 f=fsys/(16+2*CR*TWIBR)
         TWISTA=0x0; //64 分频
         TWICON = 0x40; //ENTWI,禁止高电平超时
         TWTFREE = 0xff; //最大超时配置
         TWIAMR =0 ;//关闭TWI地址屏蔽
         IEN0|=0X80;//使能所有中断允许开关
         IEN1|=0X01;//使能TWI中断
        INSCON |=0X40;
        TWICR|=0X01;//使用默认管脚作为SCL、SDA//LCM功能配置SCL、SDA管脚
        INSCON &= 0XBF;
2、代码说明
基于官方DEMOCODE
主机
/*******************************************************************************
TWI 主站发送START指令
*******************************************************************************/

bit M_TwiSendStart()
{
         TWICON |=0x20; //TWICON=OX60 总线空闲时发送起始条件
         //TWICON &= 0xdf;
         while(1) //等待 TWI 中断(?是否初始化需要开启TWI中断允许IEN0 IEN1?)
         {
                if(TWICON&0x08) //TWICON bit3中断标志位=1,需软件复位
                {
                 if(((TWISTA&0xF8)==0x08)||((TWISTA&0xF8)==0x10))
                 {
                        return OK; //成功发送开始条件或重复开始条件
                 }
                 else
                 {
                        return FAIL;
                 }
                }
                if(0x02 == (0x02 & TWICON))//TWICON bit1时钟线高电平超时,需软件复位
                {
                        TWICON &= 0xdf;
                        return FAIL; //等待中断超时
                }
         }
}

/*******************************************************************************
(2)TWI 主站发送slave地址+W/R指令
*******************************************************************************/
UCHAR M_TwiSendCmd(UCHAR addr,UCHAR cmd)
{
        UCHAR SlaveAddr;
        UCHAR i=0;
        if(cmd)
        {
                SlaveAddr=((addr&0x7f)<<1)|0x01; //读
        }
        else
        {
                SlaveAddr=((addr&0x7f)<<1); //写
        }
        
        TWICON &= 0xf7; //清除中断标志
        TWIDAT=SlaveAddr;//执行发送指令

        while(1) //等待 TWI 中断
        {
                i++;
                if(TWICON&0x08)//主站自身对指令发送是否成功的反馈判断,根据是否产生TWI中断来判断的,该标志位需要再下一次判断前进行清零,复位
                {
                 if(cmd) //发送的是读指令
                 {
                        if((TWISTA&0xF8)==0x40)//从站对指令发送是否成功的反馈判断,
                         {        
                                        return ACK; //成功发送 SLA+R
                         }
                 else if((TWISTA&0xF8)==0x48)
                         {
                                        return NAK;
                         }
                 }
                 else  //发送的是写指令
                 {
                         if((TWISTA&0xF8)==0x18)
                         {
                                        return ACK; //成功发送 SLA+W
                         }
                         else if((TWISTA&0xF8)==0x20)
                         {
                                        return NAK;
                                }
                 
                 }
                 
                 if((TWISTA&0xF8)==0x38)//反馈的是其他情况
                 {
                        return LOSEARBITRATION;//失去仲裁
                 }
                 
                 else if((TWISTA&0xF8)==0x68)
                 {
                        return RCVCMDWRITE;
                 }

                 else if((TWISTA&0xF8)==0x78)
                 {
                 return RCVCMDREAD;
                 }
                 
                 else if((TWISTA&0xF8)==0xB0)
                 {
                 return RCVADDRESS0;
                 }
                 
                 else
                 {
                 return ERR;
                 }
                }
               
                if(i>=250)//尝试次数不超过250次
                {
                 return ERR; //等待中断超时
                }
        }
}
/*******************************************************************************
(3)TWI 主站发送DATA数据
*******************************************************************************/
UCHAR M_TwiSendData(UCHAR byte)
{
        UCHAR i=0;
        TWICON &= 0xf7;//清除了中断标志位
        TWIDAT=byte;
        TWICON=0x40;
        while(1)
        {
         i++;
         if(TWICON&0x08)//自身中断判断
         {
                 if((TWISTA&0xF8)==0x28)
                 {
                        return ACK;
                 }
                 
                 else if((TWISTA&0xF8)==0x30)
                 {
                        return NAK;
                 }
                 
                 else if((TWISTA&0xF8)==0x38)
                 {
                        return LOSEARBITRATION;
                 }
                 
                 else
                 {
                        return ERR;
                 }
         }
         if(i>=250)
         {
                return ERR; //等待中断超时
         }
        }
}
/*****************************************************************************************************
(4)Twi 主机发送结束指令                  
*****************************************************************************************************/
UCHAR M_TwiSendEnd()
{
   UCHAR i=0;
   TWICON=0x50;
           while(1)
        {         
                i++;
                if((TWICON&0x10)==0)
                {
                   if(TWISTA==0xF8)
                   {
                            return OK;
                   }
                   else
                   {
                            return FAIL;
                   }
                  
                }
                if(i>=250)
            {
                   return ERR;       //等待终止位清除超时
            }

        }
}
/*******************************************************************************
(5)TWI 主站发送指令及数据给从站
*******************************************************************************/
bit M_SendDataToSlave()
{
        UCHAR ret,i=0;
        TwiInit();
        H_Timeout_check; //使能总线超时,SCL 总线高电平超时判断
        ret=M_TwiSendStart();//发送起始START
        if(ret==OK) //send-STA OK
        {
                 if(M_TwiSendCmd(0x2D,0x0)==ACK)//0X2D左移一位,对应从站地址0X5A
                 {
                        while(i < 0xff)
                        {
                                ret=M_TwiSendData(0x40+i);
                                i++;
                                if(ret==NAK)
                                {
                                return 1; //数据发送结束
                                }

                                else if((ret==LOSEARBITRATION)||(ret==ERR))
                                {
                                 return 0;
                                }
                        }
                 }
                 else
                 {
                        return 0;
                 }
        }
        else //err process
        {
        return 0;
         while(1);
        }
}

从站
/*******************************************************************************
(1)从站等待接收指令
*******************************************************************************/
UCHAR S_TwiWaitRcvCmd()
{
   TWIADR=0x5A;                        //从机地址设定
   TWICON=0x44;
   while(1)
   {
//          if(TWICON&0x08)
//          {
                  if((TWISTA&0xF8)==0x60) //收到SLA+W
                 {
                        return CMD_WRITE;
                 }
                 else if((TWISTA&0xF8)==0xA8)        //收到SLA+R
                 {

                        return CMD_READ;
                 }
                 else
                 {
                        return ERR;
                 }
//          }

   }

}
/*******************************************************************************
(2)从站等待接收数据
*******************************************************************************/
UCHAR S_TwiWaitRcvData()
{        UCHAR i=0;
        TWIDAT=0;
        TWICON=0x44;
        while(1)
        {
          i++;
          if(TWICON&0x08)
          {
                    if(((TWISTA&0xF8)==0x80)||((TWISTA&0xF8)==0x90)) //收到1个byte数据
                  {
                                _nop_();
                                return ACK;
                  }
                  else
                  {
                                _nop_();
                                return ERR;
                  }
          }

        }
        
}
/*******************************************************************************
(3)从站接收最后1个byte数据
*******************************************************************************/
UCHAR S_TwiWaitRcvLastData()
{
        UCHAR i=0;
        TWIDAT=0;
        TWICON=0x40;
        while(1)
        {
          i++;
          if(TWICON&0x08)
          {
                    if(((TWISTA&0xF8)==0x88)||((TWISTA&0xF8)==0x98)) //收到最后1个byte数据
                  {
                         return NAK;
                  }
                  else
                  {
                         return ERR;
                  }
          }

        }

}
/*******************************************************************************
(4)从站 发送数据
*******************************************************************************/
UCHAR S_TwiSendData(UCHAR byte)
{
        UCHAR i=0;
        TWIDAT=byte;
        TWICON=0x44;
        while(1)
        {
          i++;
          if(TWICON&0x08)
          {
                  if((TWISTA&0xF8)==0xB8)
                  {
                         return ACK;
                  }
                  else if((TWISTA&0xF8)==0xC0) //主机接收数据结束,从机切换至非寻址状态
                  {
                         return NAK;
                  }
                  else
                  {
                         return ERR;
                  }
          }
          if(i>=250)
          {
                 return ERR;       //等待中断超时
          }

        }

}
/*******************************************************************************
(5)从站发送最后1byte数据
*******************************************************************************/
UCHAR S_TwiSendLastData(UCHAR byte)
{
        UCHAR i=0;
        TWIDAT=byte;
        TWICON=0x40;
        while(1)
        {
          i++;
          if(TWICON&0x08)
          {
                  if((TWISTA&0xF8)==0xC8)           //从机发送数据结束,切换至非寻址状态
                  {
                         return ACK;
                  }
                  else if((TWISTA&0xF8)==0xC0) //主机接收数据结束,从机切换至非寻址状态
                  {
                         return NAK;
                  }
                  else
                  {
                         return ERR;
                  }
          }
          if(i>=250)
          {
                 return ERR;       //等待中断超时
          }

        }
}
/*******************************************************************************
(6)从站收发数据
*******************************************************************************/
bit SlaveTransfer()
{
    UCHAR* rcv_data,i=0,ret;
        TwiInit();
        ret=S_TwiWaitRcvCmd();
        if(ret==CMD_WRITE)
        {

           while(1)
           {
                 if(S_TwiWaitRcvData()==ACK)//成功接收到1个byte
             {
                          i++;
                    rcv_data[i-1]=TWIDAT;
                        if(i>=9)
                        {
                           if(S_TwiWaitRcvLastData()==NAK)
                           {
                                  rcv_data=TWIDAT;
                                  return 1;                 //接收数据结束
                           }
                           else
                           {
                                  return 0;             //接收最后1个byte数据过程中出错
                           }
                        }
             }
             else
             {
                    return 0;        //接收数据失败
             }

           }
           

        }
        else if(ret==CMD_READ)                  
        {
                while(1)
                {
                        ret=S_TwiSendData(0x40+i);
                        if(ret==NAK)  //主机接收数据结束
                        {
                           return 1;
                        }
                        else if(ret==ACK) //主机还可继续接收数据
                        {
                          i++;
                          if(i>=9)
                          {
                                if(S_TwiSendLastData(0x49)==ERR)
                                {
                                         return 0;                 //发送最后1个byte数据过程中出错
                                }
                                else
                                {
                                    return 1;         //成功发送最后1个byte数据
                                }
                          }
                        }
                        else
                        {
                           return 0; //发送数据出错
                        }
            }

     }
         else
         {
                 return 0;
         }
}

main函数
主站:
                if(M_SendDataToSlave())
        {
                UCHAR M_TwiSendEnd();               
        }


从站
        SlaveTransfer();

使用特权

评论回复
沙发
rwf5956|  楼主 | 2024-6-21 18:03 | 只看该作者
用示波器测试:
1、主从站之间SCL和SDA引脚未连接前:
(1)主站 SCL和SDA均输出方波信号;
(2)从站 SCL和SDA均输出高电平信号;
2、主从站之间SCL和SDA引脚连接后:
SCL和SDA均输出掺杂高电平和半电平(2.5V左右)的方波信号;

使用特权

评论回复
板凳
qd118| | 2024-6-23 11:21 | 只看该作者
twi头一次看到,不知楼主能否介绍下与串口比较有何优势?谢谢!

使用特权

评论回复
地板
rwf5956|  楼主 | 2024-6-24 19:16 | 只看该作者
qd118 发表于 2024-6-23 11:21
twi头一次看到,不知楼主能否介绍下与串口比较有何优势?谢谢!

个人理解有限,我觉得基本可以按照IIC去理解,这个在论坛里有提到

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

8

帖子

0

粉丝