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代表由高电平跳到低电平? mark下 发送和接收数据时被声明 好贴子关注中。。。 zhouying3129 发表于 2012-12-25 12:29 static/image/common/back.gif
你好,我的设备A在使用CC1101时从发送转到接收状态后不能收到数据,希望能得到你的一些指点,我的QQ:1851 ...
状态切换成功了吗?
中断转过去了么?
dzymushi 发表于 2012-7-25 21:51 static/image/common/back.gif
这个得看你接收端数据包是怎么配置的,如果你设置了那两个字节附在数据包后面,应该还是会产生这两个字节 ...
你好,我的设备A在使用CC1101时从发送转到接收状态后不能收到数据,希望能得到你的一些指点,我的QQ:185166322. MARK !!!!!! 本帖最后由 物联小莫 于 2012-7-27 20:04 编辑
mtbf 发表于 2012-7-27 17:45 static/image/common/back.gif
1,发送加超时检测
2,不要查询 PIN 寄存器,改成查询 IFG 寄存器。事先设置好IES寄存器。查询之前发送之前 ...
发送现在已经加了超时检测, 我现在改由查询CC1101的状态寄存器了,你说的查询标志位也是一种比较好的办法。感谢你的建议
我现在似乎找到问题的所在了,是因为我关联GDO0脚的中断函数里面+了跳进入RX模式的语句,但是想不通为什么这条语句会导致错误 1,发送加超时检测
2,不要查询 PIN 寄存器,改成查询 IFG 寄存器。事先设置好IES寄存器。查询之前发送之前先清除IFG寄存器。 物联小莫 发表于 2012-7-26 15:30 static/image/common/back.gif
嗯,是的。我目前速率是2400 比较慢了的,数据包时间间隔足够长的。实在不行,我只能定时用RES给芯片复位 ...
也是FLUSH FIFO,RES这办法 dzymushi 发表于 2012-7-26 14:25 static/image/common/back.gif
死在发送一般有这么几个解决方法
1、降低速率
2、降低两包数据的时间间隔
嗯,是的。我目前速率是2400 比较慢了的,数据包时间间隔足够长的。实在不行,我只能定时用RES给芯片复位一下了。
那么如果死在RX中呢?该如何解决呢?
物联小莫 发表于 2012-7-26 13:09 static/image/common/back.gif
死在发送里面了。 我知道它只能复位单片机。从机刚启动的时候,会发一个上电信息包的,我通过while(1)故 ...
死在发送一般有这么几个解决方法
1、降低速率
2、降低两包数据的时间间隔
3、开启TXFIFO溢出中断,如果产生中断,FLUSH一下FIFO.或者干脆一下用RES那个指令复位一下1101,记得校准 dzymushi 发表于 2012-7-26 10:09 static/image/common/back.gif
你这个发送死了还是接收死了?
WTD是不能复位RF死机的,他只能复位单片机
我是自己读取RSSI的
死在发送里面了。 我知道它只能复位单片机。从机刚启动的时候,会发一个上电信息包的,我通过while(1)故意使单片机复位,每次复位都能收到上电包,说明cc1101是被重新初始化了的。 物联小莫 发表于 2012-7-26 09:21 static/image/common/back.gif
昨天按照你的建议修改过程序后,今天发现还是不行,心跳包发了一个晚上就死掉,估计还是死在里面了,程序 ...
你这个发送死了还是接收死了?
WTD是不能复位RF死机的,他只能复位单片机
我是自己读取RSSI的
这种做法是可以的。 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);
} 物联小莫 发表于 2012-7-25 16:21 static/image/common/back.gif
还有一个问题哦!
我接收端开启了APPEND_STATUS,发送端关闭了CRC校验。 这个时候接收到数据后额外的两 ...
这个得看你接收端数据包是怎么配置的,如果你设置了那两个字节附在数据包后面,应该还是会产生这两个字节的,具体我没试过,去掉CRC不好的,毕竟接受到一包错误的数据,会占用你不少时间处理这个数据包的 dzymushi 发表于 2012-7-25 15:46 static/image/common/back.gif
不是,重新配置频率,偏偏,误差这些寄存器的时候
还有一个问题哦!
我接收端开启了APPEND_STATUS,发送端关闭了CRC校验。 这个时候接收到数据后额外的两个字节中的最后一个的CRC位应该是无效的吧?那这个时候它是否是一个固定的值0或者1? 物联小莫 发表于 2012-7-25 15:34 static/image/common/back.gif
你所说的重新设置radio是不是指idle状态下就该一些配置寄存器?
不是,重新配置频率,偏偏,误差这些寄存器的时候 dzymushi 发表于 2012-7-25 14:52 static/image/common/back.gif
死机一般的表现是无法产生packetEND这个中断,或者发送不出数据。
我感觉还是由于FIFO溢出或者误操作引起 ...
你所说的重新设置radio是不是指idle状态下就该一些配置寄存器? 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死机了吧
物联小莫 发表于 2012-7-25 13:47 static/image/common/back.gif
好的,我马上修改测试下......感谢你的建议,其实程序原来是有这个判断的,我经验不足,觉得没什么用,就 ...
低功耗后可以不校准 物联小莫 发表于 2012-7-25 13:47 static/image/common/back.gif
好的,我马上修改测试下......感谢你的建议,其实程序原来是有这个判断的,我经验不足,觉得没什么用,就 ...
死机一般的表现是无法产生packetEND这个中断,或者发送不出数据。
我感觉还是由于FIFO溢出或者误操作引起的
你仔细看下这个GDO的含义,是不是有说这个中断也可能是由溢出或者地址检测(ADDR)错误触发?不一定是数据包接收或者发完成
频率校准可以使用默认的4次一校准那个,没有必要每次都校准
校准一般在这几个情况下,最好校准一次,1切换载波频率,2是换通道的时候,3重新设置radio的shi的时候 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,容易出错,这个是什么原因呢? 物联小莫 发表于 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死机。 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();
} 原因可能是这样的,
1、地址过滤失败产生的这个中断,这时候读取一下RX-BYTE,读出来的应该是0.这个时候你操作RXFIFO,是可能死机的,
2、在中断里面做了RXOFF的操作,这样你可能FIFO的最后一字节没有及时更新进来,造成FIFO错乱,
这个情况的可能比较大,你可以在接受中断里面先把RXFIFO的数据拷出来。退出中断之前将这个FIFO FLUSH掉 eliachen 发表于 2012-7-20 20:27 static/image/common/back.gif
单片机主频有点低啊,你是用外部晶振还是内部的?
主频使用DCO 1M的,但是我觉得应该够了的。 你觉得1M会对这个有影响吗?用1M主要是为了降低功耗 单片机主频有点低啊,你是用外部晶振还是内部的? 物联小莫 发表于 2012-7-20 08:54 static/image/common/back.gif
单步试过了,就是这样的。单片机主频是1M的,cc是2400波特率,发一个包是毫秒级别的,我想不通....应该跟得 ...
加个QQ 690185122 交流下 我也有点问题 想不通?690185122 单步试过了,就是这样的。单片机主频是1M的,cc是2400波特率,发一个包是毫秒级别的,我想不通....应该跟得上的。
另外,我后来又式了下,在卡死的那个while语句里面读取cc的状态寄存器,发现它居然处于RX模式,但是实际读取RSSI信号显示它应该处于TX模式的,好奇怪....
后来我驱动改了一下,测了一个晚上了没有发现问题,再测一段时间看看 跟单片机的运行速度有关 你单步试试 我也是这样的 然后加入延时 就可以了
页:
[1]