物联小莫 发表于 2012-7-18 14:29:56

CC1101数据包发送函数

本帖最后由 物联小莫 于 2012-7-18 14:34 编辑

如题...
   cc1101用430单片机驱动的,cc1101这些驱动函数是从原来一个项目拷贝过来的。发送代码如下图。

后期测试的时候通过主机读取RSSI信号强度偶尔发现有个从机一直处于TX模式,后来用仿真器调试了半天终于触发了这个BUG,
程序一直卡在了绿色那条语句。P2IN&0X40对应GDO2引脚,我把它配置为0x06. 资料上是:
Asserts when sync word has been sent / received, and de-asserts at the end of the packet. In RX, the pin will de-assert
when the optional address check fails or the RX FIFO overflows. In TX the pin will de-assert if the TX FIFO underflows.
我把全局中断都关掉了,但是还是有一定概率会卡在这条语句上。有没有人给一些解释呢?
另外,资料里面的assert是否一定代表是由低电平跳到高电平?而deassert代表由高电平跳到低电平?

jinshaopu 发表于 2014-7-22 15:11:30

mark下                        

芽芽小宝 发表于 2014-3-21 16:44:31

发送和接收数据时被声明

15242026 发表于 2013-2-18 13:10:43

好贴子关注中。。。

dzymushi 发表于 2013-1-5 10:37:06

zhouying3129 发表于 2012-12-25 12:29 static/image/common/back.gif
你好,我的设备A在使用CC1101时从发送转到接收状态后不能收到数据,希望能得到你的一些指点,我的QQ:1851 ...

状态切换成功了吗?
中断转过去了么?

zhouying3129 发表于 2012-12-25 12:29:06

dzymushi 发表于 2012-7-25 21:51 static/image/common/back.gif
这个得看你接收端数据包是怎么配置的,如果你设置了那两个字节附在数据包后面,应该还是会产生这两个字节 ...

你好,我的设备A在使用CC1101时从发送转到接收状态后不能收到数据,希望能得到你的一些指点,我的QQ:185166322.

fjxsos 发表于 2012-10-12 21:46:03

MARK !!!!!!

物联小莫 发表于 2012-7-27 20:01:22

本帖最后由 物联小莫 于 2012-7-27 20:04 编辑

mtbf 发表于 2012-7-27 17:45 static/image/common/back.gif
1,发送加超时检测
2,不要查询 PIN 寄存器,改成查询 IFG 寄存器。事先设置好IES寄存器。查询之前发送之前 ...

发送现在已经加了超时检测, 我现在改由查询CC1101的状态寄存器了,你说的查询标志位也是一种比较好的办法。感谢你的建议

我现在似乎找到问题的所在了,是因为我关联GDO0脚的中断函数里面+了跳进入RX模式的语句,但是想不通为什么这条语句会导致错误

mtbf 发表于 2012-7-27 17:45:27

1,发送加超时检测
2,不要查询 PIN 寄存器,改成查询 IFG 寄存器。事先设置好IES寄存器。查询之前发送之前先清除IFG寄存器。

dzymushi 发表于 2012-7-26 15:50:58

物联小莫 发表于 2012-7-26 15:30 static/image/common/back.gif
嗯,是的。我目前速率是2400 比较慢了的,数据包时间间隔足够长的。实在不行,我只能定时用RES给芯片复位 ...

也是FLUSH FIFO,RES这办法

物联小莫 发表于 2012-7-26 15:30:43

dzymushi 发表于 2012-7-26 14:25 static/image/common/back.gif
死在发送一般有这么几个解决方法
1、降低速率
2、降低两包数据的时间间隔


嗯,是的。我目前速率是2400 比较慢了的,数据包时间间隔足够长的。实在不行,我只能定时用RES给芯片复位一下了。
那么如果死在RX中呢?该如何解决呢?

dzymushi 发表于 2012-7-26 14:25:31

物联小莫 发表于 2012-7-26 13:09 static/image/common/back.gif
死在发送里面了。 我知道它只能复位单片机。从机刚启动的时候,会发一个上电信息包的,我通过while(1)故 ...

死在发送一般有这么几个解决方法
1、降低速率
2、降低两包数据的时间间隔
3、开启TXFIFO溢出中断,如果产生中断,FLUSH一下FIFO.或者干脆一下用RES那个指令复位一下1101,记得校准

物联小莫 发表于 2012-7-26 13:09:04

dzymushi 发表于 2012-7-26 10:09 static/image/common/back.gif
你这个发送死了还是接收死了?
WTD是不能复位RF死机的,他只能复位单片机
我是自己读取RSSI的


死在发送里面了。 我知道它只能复位单片机。从机刚启动的时候,会发一个上电信息包的,我通过while(1)故意使单片机复位,每次复位都能收到上电包,说明cc1101是被重新初始化了的。

dzymushi 发表于 2012-7-26 10:09:14

物联小莫 发表于 2012-7-26 09:21 static/image/common/back.gif
昨天按照你的建议修改过程序后,今天发现还是不行,心跳包发了一个晚上就死掉,估计还是死在里面了,程序 ...

你这个发送死了还是接收死了?
WTD是不能复位RF死机的,他只能复位单片机
我是自己读取RSSI的
这种做法是可以的。

物联小莫 发表于 2012-7-26 09:21:15

dzymushi 发表于 2012-7-25 21:51 static/image/common/back.gif
这个得看你接收端数据包是怎么配置的,如果你设置了那两个字节附在数据包后面,应该还是会产生这两个字节 ...

昨天按照你的建议修改过程序后,今天发现还是不行,心跳包发了一个晚上就死掉,估计还是死在里面了,程序跑不出来,然后看门狗也不会复位,我刚刚试过,故意在txModeOn函数里面加了个while(1),单片机是会重启的。底层驱动我改为下面的函数。同时,在发送心跳包之前,读取RSSI信号强度来作为判断信道是否占用的参考,过程如下:

低功耗下唤醒->进入RX模式->等待1ms->读取RSSI值->然后回到低功耗。如果判断信道被占用,则在低功耗状态下随机延时一段时间,再重复上述过程。 你觉得这样行吗? 还是用CS CCA比较好?我觉得直接读RSSI比设置CS CCA来得直观



void sendMsg(lockMSG *msg, uint8_t msgType)
{
   _DINT();
   startWDT();
      
   if(msg == NULL)
   {
           return;
   }
   if(msgType == WSN_MSG)
   {
        halRfSendPacket((INT8U *)msg, msg->pktLen);
   }
   
   P2IFG &= ~BIT6;
   _EINT();
}


void halRfSendPacket(INT8U *txBuffer, INT8U size)
{   
    idleModeOn();   
    clearTxFifo();   
    TI_CC_SPIWriteReg(TI_CCxxx0_TXFIFO, size);
    writeBurstReg(TI_CCxxx0_TXFIFO, txBuffer, size);        //写入要发送的数据   
    txModeOn();
    clearTxFifo();
}

void idleModeOn(void)
{
halSpiStrobe(TI_CCxxx0_SIDLE);
while(readCCstatus()!= STATE_IDLE);
}

INT8U readCCstatus(void)
{
   INT8U state;
   state=halSpiReadStatus(TI_CCxxx0_MARCSTATE);
   return state;
}

void clearTxFifo(void)
{
halSpiStrobe(TI_CCxxx0_SFTX);
while(readCCstatus() != STATE_IDLE);
}

void txModeOn(void)
{
    halSpiStrobe(TI_CCxxx0_STX);//进入发送模式发送数据
    while(1);
   
    while(readCCstatus() != STATE_IDLE)
    {
      extern INT8U test;
      test=0xbe;
      if(readCCstatus() == STATE_TX_UNDERFLOW)
      {
            halSpiStrobe(TI_CCxxx0_SFTX);            
      }
    }   
   
}


void clearTxFifo(void)
{
halSpiStrobe(TI_CCxxx0_SFTX);
while(readCCstatus() != STATE_IDLE);
}

dzymushi 发表于 2012-7-25 21:51:33

物联小莫 发表于 2012-7-25 16:21 static/image/common/back.gif
还有一个问题哦!
我接收端开启了APPEND_STATUS,发送端关闭了CRC校验。 这个时候接收到数据后额外的两 ...

这个得看你接收端数据包是怎么配置的,如果你设置了那两个字节附在数据包后面,应该还是会产生这两个字节的,具体我没试过,去掉CRC不好的,毕竟接受到一包错误的数据,会占用你不少时间处理这个数据包的

物联小莫 发表于 2012-7-25 16:21:42

dzymushi 发表于 2012-7-25 15:46 static/image/common/back.gif
不是,重新配置频率,偏偏,误差这些寄存器的时候

还有一个问题哦!
我接收端开启了APPEND_STATUS,发送端关闭了CRC校验。 这个时候接收到数据后额外的两个字节中的最后一个的CRC位应该是无效的吧?那这个时候它是否是一个固定的值0或者1?

dzymushi 发表于 2012-7-25 15:46:16

物联小莫 发表于 2012-7-25 15:34 static/image/common/back.gif
你所说的重新设置radio是不是指idle状态下就该一些配置寄存器?

不是,重新配置频率,偏偏,误差这些寄存器的时候

物联小莫 发表于 2012-7-25 15:34:38

dzymushi 发表于 2012-7-25 14:52 static/image/common/back.gif
死机一般的表现是无法产生packetEND这个中断,或者发送不出数据。
我感觉还是由于FIFO溢出或者误操作引起 ...

你所说的重新设置radio是不是指idle状态下就该一些配置寄存器?

物联小莫 发表于 2012-7-25 15:04:32

dzymushi 发表于 2012-7-25 14:54 static/image/common/back.gif
低功耗后可以不校准

对了,其实我是有那个检测PKTLEN的语句的,就是这句: if ((halSpiReadStatus(TI_CCxxx0_RXBYTES) & BYTES_IN_RXFIFO))//如果接的字节数不为0,BYTES_IN_RXFIFO为0x7f

昨晚上测试5台,到今天只有2台正常工作,3台估计是cc1101死机了吧


dzymushi 发表于 2012-7-25 14:54:01

物联小莫 发表于 2012-7-25 13:47 static/image/common/back.gif
好的,我马上修改测试下......感谢你的建议,其实程序原来是有这个判断的,我经验不足,觉得没什么用,就 ...

低功耗后可以不校准

dzymushi 发表于 2012-7-25 14:52:30

物联小莫 发表于 2012-7-25 13:47 static/image/common/back.gif
好的,我马上修改测试下......感谢你的建议,其实程序原来是有这个判断的,我经验不足,觉得没什么用,就 ...

死机一般的表现是无法产生packetEND这个中断,或者发送不出数据。
我感觉还是由于FIFO溢出或者误操作引起的
你仔细看下这个GDO的含义,是不是有说这个中断也可能是由溢出或者地址检测(ADDR)错误触发?不一定是数据包接收或者发完成
频率校准可以使用默认的4次一校准那个,没有必要每次都校准
校准一般在这几个情况下,最好校准一次,1切换载波频率,2是换通道的时候,3重新设置radio的shi的时候

物联小莫 发表于 2012-7-25 13:47:32

dzymushi 发表于 2012-7-25 11:12 static/image/common/back.gif
else
            {
                  //当前处于非wor模式


好的,我马上修改测试下......感谢你的建议,其实程序原来是有这个判断的,我经验不足,觉得没什么用,就删掉了,呵呵。
另外,能不能解释下,cc1101死机的时候是个什么现象?另外,我看资料的时候,关于手动校准频率(滤波命令SCAL),资料上面说:
This calibration should be done regularly, and must be performed after turning on power and before using a new frequency (or channel).
turning on power是指cc1101重新上电?是否建议每次从低功耗唤醒以后都使用SCAL命令校准一次频率?还有就是如果packetLength读出来的是0,容易出错,这个是什么原因呢?

dzymushi 发表于 2012-7-25 11:12:52

物联小莫 发表于 2012-7-25 10:42 static/image/common/back.gif
首先,非常感谢你的回答,根据你提出的两种可能情况,我进行如下说明。
你考虑的第一种情况:(我不知 ...

            else
            {
                  //当前处于非wor模式
                  packetLength = halSpiReadReg(TI_CCxxx0_RXFIFO);//读出第一个字节,此字节为该帧数据长度      
                  halSpiReadBurstReg(TI_CCxxx0_RXFIFO, wsnRxBuf, packetLength);//读出所有接收到的数据
                  clearRxFifo();
                  prcWsnMsg(wsnRxBuf);
                  rxModeOn();
            }

你在这个位置用断点观察一下packetLength是不是0,如果是0的话,这个时候读取FIFO是可能出错的,我之前也碰到过。
我说的司机是指1101死机。

物联小莫 发表于 2012-7-25 10:42:54

dzymushi 发表于 2012-7-24 20:19 static/image/common/back.gif
原因可能是这样的,
1、地址过滤失败产生的这个中断,这时候读取一下RX-BYTE,读出来的应该是0.这个时候你 ...

首先,非常感谢你的回答,根据你提出的两种可能情况,我进行如下说明。
你考虑的第一种情况:(我不知道我这么理解对不对,请前辈指正)进入到这个发射函数以后,我关掉了全局中断,并且进入到TX模式,我认为地址滤波只在接收的时候起作用,因此地址滤波失败在非RX模式下是不会发生的,因此GDO0脚也不会有相应的电平。另外你说之后操作RXFIFO会死机,一般是什么原因?是MCU死机还是说CC1101进入到RX_OVERFLOW状态(这时候只能用滤波命令SFRX才能恢复到IDLE模式)或者说是CC1101死机?我认为RXFIFO是队列,队列中如果没有数据读出来的就是0,应该对整个FIFO没有太大影响吧。
你考虑的第二种情况:RXOFF操作是什么意思?关闭RX模式,回到IDLE模式?另外,触发进入数据处理的中断并不和GDO0脚相联系,我程序里面是与GDO2脚联系(配置为0x01),并且在处理数据的时候,就是你所建议的把RXFIFO里的数据拷贝出来,之后紧接着就执行了SFRX命令。
GDO0脚与MCU的P26脚相连,在重新开启全局中断前,我刻意清除了中断标志位。另附上我的中断处理函数:


//PORT2引脚中断
#pragma vector=PORT2_VECTOR
__interrupt void WSNIsr(void)
{
    INT8U packetLength;
    startWDT();
   
    if(P2IFG&BIT7)//CC1101接收到数据——GDO2引脚
    {      
          //读取WSN数据   
          if ((halSpiReadStatus(TI_CCxxx0_RXBYTES) & BYTES_IN_RXFIFO))//如果接的字节数不为0,BYTES_IN_RXFIFO为0x7f
          {
            if(SLAVE_WOR == nowAction)
            {
                  //当前cc1101处于wor模式
                  halSpiReadBurstReg(TI_CCxxx0_RXFIFO, wsnRxBuf, PKT_LEN);//读出所有接收到的数据
                  clearRxFifo();
                  prcWsnMsg(wsnRxBuf);
                  if(SLAVE_WOR == nowAction)
                  {
                      worModeOn();
                  }
                  else
                  {
                      __bic_SR_register_on_exit(LPM3_bits);//退出低功耗模式
                  }
            }
            else
            {
                  //当前处于非wor模式
                  packetLength = halSpiReadReg(TI_CCxxx0_RXFIFO);//读出第一个字节,此字节为该帧数据长度      
                  halSpiReadBurstReg(TI_CCxxx0_RXFIFO, wsnRxBuf, packetLength);//读出所有接收到的数据
                  clearRxFifo();
                  prcWsnMsg(wsnRxBuf);
                  rxModeOn();
            }
          }
      }

      else if(P2IFG&BIT6)//下降沿触发引起的中断,关联引脚:GDO0
      {
          if(nowAction == SLAVE_WOR)
          {
             worModeOn();
          }
          else
          {            
             rxModeOn();
          }
      }
    //P27上升沿触发,当CC1101的RXFIFO >= RXFIFO 阀值时或者 接收状态下数据包末端到达时P27出现上升沿;
    //P26下降沿触发,CC1101发送或接收状态下到达数据包末端时 或 接收状态下地址检测失败或者RXFIFO上溢 或 发送状态下TXFIFO下溢时P26出现下降沿
    //综上,接收到数据包时P27 和P26同时产生中断请求,因此需要屏蔽掉P26中断;地址检测失败时只有P26产生中断请求,
    //而此程序对CC1101的配置和处理机制是不会使TX/RX FIFO产生溢出。所以加入以下语句防止重复进入中断
    //此外,在发送数据包时要注意把P26中断使能关掉
    P2IFG = 0x00;
    stopWDT();
}

dzymushi 发表于 2012-7-24 20:19:32

原因可能是这样的,
1、地址过滤失败产生的这个中断,这时候读取一下RX-BYTE,读出来的应该是0.这个时候你操作RXFIFO,是可能死机的,
2、在中断里面做了RXOFF的操作,这样你可能FIFO的最后一字节没有及时更新进来,造成FIFO错乱,
    这个情况的可能比较大,你可以在接受中断里面先把RXFIFO的数据拷出来。退出中断之前将这个FIFO FLUSH掉

物联小莫 发表于 2012-7-22 09:35:23

eliachen 发表于 2012-7-20 20:27 static/image/common/back.gif
单片机主频有点低啊,你是用外部晶振还是内部的?

主频使用DCO 1M的,但是我觉得应该够了的。 你觉得1M会对这个有影响吗?用1M主要是为了降低功耗

eliachen 发表于 2012-7-20 20:27:20

单片机主频有点低啊,你是用外部晶振还是内部的?

aizhixi106 发表于 2012-7-20 10:26:00

物联小莫 发表于 2012-7-20 08:54 static/image/common/back.gif
单步试过了,就是这样的。单片机主频是1M的,cc是2400波特率,发一个包是毫秒级别的,我想不通....应该跟得 ...

加个QQ 690185122 交流下 我也有点问题 想不通?690185122

物联小莫 发表于 2012-7-20 08:54:49

单步试过了,就是这样的。单片机主频是1M的,cc是2400波特率,发一个包是毫秒级别的,我想不通....应该跟得上的。
另外,我后来又式了下,在卡死的那个while语句里面读取cc的状态寄存器,发现它居然处于RX模式,但是实际读取RSSI信号显示它应该处于TX模式的,好奇怪....
后来我驱动改了一下,测了一个晚上了没有发现问题,再测一段时间看看

aizhixi106 发表于 2012-7-19 23:38:21

跟单片机的运行速度有关 你单步试试 我也是这样的 然后加入延时 就可以了
页: [1]
查看完整版本: CC1101数据包发送函数