作者 主题: TWI一主多从实战程序片段  (阅读 265 次)

hotpower

  • 管理员
  • Full Member
  • *****
  • 帖子: 134
TWI一主多从实战程序片段
« 于: 十二月 18, 2019, 10:16:04 下午 »
程序代码: [选择]
若是AVR的TWI,要注意每次通信都要先
  DDRC &= ~((1 << SCL) | (1 << SDA));//SCL、SDA 引脚内部上拉电阻
  TWCR &= ~(1 << TWEN);
  PORTC |= (1 << SCL) | (1 << SDA);//SCL、SDA 引脚内部上拉电阻
再在TWStart()内TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN) | (1 << TWIE);

我反复做过实验...把我害苦了...助好友TestCode成功!!!

哈哈...以下程序在ouravr那里都没舍得发...(非常好用)

inline
void TwiObj::WorkExec(void)
{
static unsigned char Count = 0;
unsigned char worknum;
  DDRC &= ~((1 << SCL) | (1 << SDA));//SCL、SDA 引脚内部上拉电阻
  TWCR &= ~(1 << TWEN);
  PORTC |= (1 << SCL) | (1 << SDA);//SCL、SDA 引脚内部上拉电阻
  if (Busy) {//主机忙
    TWStop();
  }
  else {
    MainCount = 0;//发送0个数据
    SubComm = 0;//不允许发送数据
    SubCount = 4;//接收4个数据
    Count &= 0x0f;//16个为一轮
    if ((Count & 1) == 0) {//偶数为1通道
      worknum = 0;
      SubAddr = UsiSlaveAddrRd1;//从机地址
    }
    else {//奇数为2通道
      worknum = 1;
      SubAddr = UsiSlaveAddrRd2;//从机地址
    }
//..................






inline
void TwiObj::TWStart(void)
{
  Busy = true;
  Status = 0;//主机准备发送启始位
  Count = 0;//发送数据个数
  TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN) | (1 << TWIE);
}


inline
void TwiObj::TWREStart(void)
{
  Busy = true;
  Status = 0x55;//主机准备发送启始位
  Count = 0;//接收数据个数
  TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN) | (1 << TWIE);
}

inline
void TwiObj::TWStop(void)
{
  Busy = false;
//  Status = 0xaa;//pwy
  Count = 0;
  TWCR = (1 << TWINT) | (1 << TWSTO);//关闭TWIE//pwy
}

//inline(不敢加)
void TwiObj::Exec(void)
{
//  TW_Error = TW_STATUS;
//  if (!Busy) TWStop();//pwy
//  else {
  switch(TW_STATUS) {
    case TW_START://主机收到自己发送的开始信号
          if (Status == 0) {//本次中断应该接收TW_START信号//pwy
            TWDR = SubAddr & 0xfe;//发送子机地址(写)
            Status = 1;//Status下次主发为1,主收为2
            TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE);//发送出去
//::Uart.puts("TW_START");
//::Uart.putstr("Status=");
//::Uart.puthex(Status);
//::Uart.puts("");
          }
          else TWStop();
          break;
    case TW_REP_START://主机收到自己发送的重新开始信号
          if ((Status == 0x55) && (SubAddr & 0xfe)) {//本次中断应该接收TW_START信号//pwy
            TWDR = SubAddr;//发送子机地址(读)
            Status = 2;//Status下次主发为1,主收为2
            TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE);//发送出去
          }
          else TWStop();
          break;
    case TW_MT_SLA_ACK://主发机接收到从机的地址应答信号后发送命令
          if (Status == 1) {//本次中断应该接收TW_MT_SLA_ACK信号
            Status = 3;//Status下次应该收TW_MT_DATA_ACK
            TWDR = SubComm;//发送子机命令
/*-----------------------------------------------------------------------------
            以后可以复杂些
-----------------------------------------------------------------------------*/
            TxBuffer[0] = SubComm;//简单命令校验
            TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE);//发送出去
//::Uart.puts("TW_MT_SLA_ACK");
//::Uart.putstr("Status=");
//::Uart.puthex(Status);
//::Uart.puts("");
          }
          else  TWStop();
          break;
    case TW_MR_SLA_ACK://主收机接收到从机的地址应答信号
          if (SubCount && (Status == 2)) {//本次中断应该接收TW_MR_SLA_ACK信号
            Status = 4;//Status下次应该收TW_MR_DATA_ACK
            TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE) | (1 << TWEA);//主机转入接收状态
//::Uart.puts("TW_MT_SLA_ACK");
//::Uart.putstr("Status=");
//::Uart.puthex(Status);
//::Uart.puts("");
          }
          else TWStop();
          break;
    case TW_MT_DATA_ACK:
          if ((Count < MainCount) && (Status == 3) && ((SubAddr & 1) == 0)) {//本次中断应该接收TW_MT_DATA_ACK信号
            TWDR = TxBuffer[Count ++];//发送子机数据
            TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE);//发送出去
          }
          else
            if ((Count == MainCount) && (Status == 3) && (SubAddr & 1)) {//本次中断应该接收TW_MT_DATA_ACK信号
              TWREStart();//
            }
//            else if ((Count == MainCount) && (Status == 3) && ((SubAddr & 1) == 0)) {
//              TW_Error = 0xfe;//数据发送成功
//              TWStop();
//            }
            else TWStop();
          break;
//    case TW_MT_DATA_NACK://数据发送结束
//          if ((Count == MainCount) && (Status == 4)) {
//            TW_Error = 0xf0;//数据发送失败
//          }
//          TWStop();
//          break;
    case TW_MR_DATA_ACK:
          if ((Count < SubCount) && (Status == 4)) {
            RxBuffer[Count ++] = TWDR;//接收子机数据
            if (Count < SubCount)
              TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE) | (1 << TWEA);//主机转入接收状态
            else
              TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE);//主机转入接收状态
          }
          else TWStop();
          break;
    case TW_MR_DATA_NACK://数据接收结束
//::Uart.puts("TWI_GOOD");
          if ((Count == SubCount) && (Status == 4)) {
            if (((RxBuffer[0] ^ RxBuffer[2]) == 0xff) && ((RxBuffer[1] ^ RxBuffer[3]) == 0xff)) {
              if ((RxBuffer[0] & 0xf0) == (SubComm & 0xf0)){
                SetTwiDataBuff();
//Uart.puts("TWI_GOOD");
              }
            }
//::Uart.puts("TWI_GOOD");
//            TW_Error = 0xff;//数据接收成功
          }
//          TWStop();
//          break;
    default:
          TWStop();
//::Uart.puts("TWI_BAD");
//::Uart.putstr("TW_STATUS=");
//::Uart.puthex((unsigned int)TW_STATUS);
//::Uart.puts("");
          break;
    }
//  }
}