CC1101 使用过程中遇到的问题汇总如下: (未完待续)
PS:TI的东西真心垃圾,就是相关的配套pdf和辅助调试软件很完整,
这个非常重要,不然。。。
好多问题已经忘记。。。 慢慢回忆中
1.
此问题隐藏多年,隐蔽性极大,巨难查找,如果你不是上了点年纪且用过以前51内核的问题芯片的工程师,你很难知道原因。
经常在客户那里RF死掉了,拿回来测试又是好的,问题往往被忽略。 电容放电完(0V),再重新上电又是正常的。
产生过程:
CC1101 无线模块+PA 的发射功率比较大,在外部加上1000uf的大电容以缓冲功耗带来的电平波动,但同时大电容在放电结束时间缓慢(特别是放电曲线的后半段)。当RF的电平进入特定的死区电平(可能 0.3-0.7),此时重新上电RF会死机且无法通过初始化(初始化程序没有配置全部的寄存器,有部分使用默认值)来重新唤起工作。
原因:
没有配置默认值的寄存器在上述过程中会发生改变,而上电的程序又没有全部配置所有的寄存器,被改变的寄存器没有得到修正。
解决方法:
<1> 短接RF模块 VCC 、 GND 充分将电容进行放电。
<2> 在上电初始化代码中配置所有的寄存器,完全初始化。
代码例示:
其他以前的配置
。。。。。。。
//-----------------------------以下值是复位值也必须赋值,不然模块上下电会出现不通讯
{TI_CCxxx0_IOCFG1, 0x2e}, //新增配置
{TI_CCxxx0_FIFOTHR, 0x47},
{TI_CCxxx0_MCSM2, 0x07},
{TI_CCxxx0_WOREVT1, 0x87},
{TI_CCxxx0_WOREVT0, 0X6B},
{TI_CCxxx0_WORCTRL, 0xFB},
{TI_CCxxx0_RCCTRL1, 0x41},
{TI_CCxxx0_RCCTRL0, 0x00},
{TI_CCxxx0_PTEST, 0x7F},
{TI_CCxxx0_AGCTEST, 0x3F},
2.
在SPI的速度很高的时候,SPI连接的IO口上加有上拉电阻的话可能会影响SPI的通讯。
原因:加了上拉电阻,上升沿的爬坡速度是有个斜率,下降沿也是。爬升的速度不够快,下降的速度不够快都会影响SPI的通讯。
解决方法:
<1> 调整上拉电阻,以提高爬坡和下降的速度。
3.
在CC1101交互通信中,能显示表地址,但不能抄读回电能或其他数据。
(1) 原因: CC1101模块在交互通信距离很短时(1m以内),当sender发射功率很大 15 dBm以上,receive接收处于饱和状态,造成接收不成功。
类似于sender喊得很大声,超过recevie听力接受程度,造成暂时性耳聋。(炸弹爆炸,后人暂时失聪)
(2) 原因: CC1101模块在进入sleep后,重新恢复IDLE,功率配置表会丢失,只保留配置表的第一个发送功率。详情参考CC1101 用户手册
(3) 原因: 万高的51内核的单片机Flash扩展后,code区地址复用。具体详见万高 9401A data sheet user‘s guide
(1) 解决方法:
<1> recevie返回数据的时候,发送功率使用弱发送(发射功率3dBm、5dBm或者10dBm)和强发送(17dBm或者更大)交替搭配切换发送的方式。
代码例示:
void RFProcess(void)
{
uint8 Length; //RF 帧长度
if (!RX_FIG) //判断接收标志
return;
RX_FIG = 0;
Disable_ExtInt(); //关闭 接收 IRQ中断
memset(RX_buff, 0, sizeof(RX_buff));
memset(TX_buff, 0, sizeof(TX_buff));
RFWaitSendFlag = 0;
SpiWriteStrobe(SIDLE); //手动切换待机
Length = SpiReadStatus(RXBYTES) & NUM_RXBYTES;
if (RF_frame_length == Length)
{
SpiReadBurstReg(RXFIFO, RX_buff, RF_frame_length); //读取buff data
if (RX_buff[CRC_POSITION] & RF_CRC_OK)
{
RF_OneHourcnt = ONEDAYTIME; //接收到完整一帧赋初值
//DisplayCOM(); 显示通信符 三相表无此功能
RFReceiveMessage();
}
if (RFWaitSendFlag)
{
RFWaitSendFlag = 0;
RFSendData();
PublicDelayMs(8); //为了延时发送
RFSendData();
PublicDelayMs(3);
#ifdef RF_MASH
SpiWriteReg(FREND0,0x12);//弱发送
RFSendData();
PublicDelayMs(3);
SpiWriteReg(FREND0,0x17);//强发送
#endif
}
}
enable_RF_RX(); // 重启接收
RFExtInt_Init(); // 重启RF 接收中断
}
(2) 解决方法:
<1> CC1101恢复IDLE模式后,重新 初始化 功率配置表。
<2> CC1101配置sleep 模式后,再次 初始化 功率配置表。
代码例示:
(2) ---- <1>
void CC1101_Sleep(void)
{
Disable_ExtInt(); //关闭 接收 IRQ中断
EXTI_ClrIntFlag(EXTI_CH13);
SpiWriteStrobe(SIDLE);
SpiWriteStrobe(SPWD);
SetUpCC1101PATABLE(); //init 功率配置表
RX_FIG = 0; //此句防止 写SPWD之前 RX_FIG标志被置位
}
<2> ----- <2>
void enable_RF_RX(void)
{
SpiWriteStrobe(SIDLE);
SetUpCC1101PATABLE(); //init 功率配置表
SpiWriteStrobe(SFRX); // 清cc1100接收buffer
SpiWriteStrobe(SRX); // 置为接收状态
EXTI_ClrIntFlag(EXTI_CH13);
RFExtInt_Init(); // 重启RF 接收中断
}
(3) 解决方法:
为解决前原代码:
const uint8 PA_TABLE[8]= {0x00,0x12,0x0e,0x34,0x60,0xc5,0xc1,0xc0}; //ybz !!! const
void SetCC1101TxPower(uint8 value)
{
SpiWriteReg(FREND0,value); //选择最大功率,
}
修改后代码:
const uint8 PA_TABLE[8]= {0x00,0x12,0x0e,0x34,0x60,0xc5,0xc1,0xc0}; //ybz !!! const
void SetUpCC1101PATABLE(void)
{
uint8 *temp = 0;
MemCpy(temp,PA_TABLE, sizeof(PA_TABLE));
SpiWriteBurstReg(PATABLE, temp, 8); //设置功率表 ybz!!! (uint8 *)PA_TABLEPA_TABLE
}
4.
电表在低压时RF进入sleep模式,维持低压,RF定期初始化之后,RF模式从 sleep 改变为 RX。
原因: 通常GDO2的电平起落变化时是用于指示 TX、RX 数据帧 完成,以此来触发一个IRQ,并通过IRQ服务程序中置起的RF_RX_fig标志来进入RX数据帧处理程序。 CC1101 上电初始化的时候 GDO2会有一个电平起落的变化 ___|ˉˉˉˉˉˉˉ|____ (跟GDO2 IO 配置功能有关系,这个GDO2的电平变化如果没有经过处理,会触发IRQ中断,被误认为是GDO2 RX、TX IRQ,进而进入RX数据帧处理程序,影响正常的程序逻辑。
SPI_byte(SRES); //reset chip 注意!!! 这个语句会造成 GDO2 有一个_|—|_ 电平变化
解决方法:
<1> 在进行RF初始化之前,先关闭RF IRQ中断,初始化完成后在开启RF IRQ中断。
代码例示:
void RF_init_config(void)
{
Vol_low = 1; //上电 、 低功耗 初始化
RF_OneHourcnt = ONEDAYTIME; //定时 init RF 变量复位
RX_FIG = 0;
memset(ReadMeterSerialNumber,0,8);
Disable_ExtInt(); //关闭 RF IRQ中断
RF_IO_Init();
RFReset();
RFSet(); //RF reg config
//set TX power
SetUpCC1101PATABLE(); //设置功率表
SetCC1101TxPower(TXPOWERELEVEL7); //选择最大功率
CC1101_Sleep(); //
}
void RFProcess(void)
{
uint8 Length; //RF 帧长度
if (!RX_FIG) //判断接收标志
return;
RX_FIG = 0;
Disable_ExtInt(); //关闭 接收 IRQ中断
memset(RX_buff, 0, sizeof(RX_buff));
memset(TX_buff, 0, sizeof(TX_buff));
RFWaitSendFlag = 0;
SpiWriteStrobe(SIDLE); //手动切换待机
Length = SpiReadStatus(RXBYTES) & NUM_RXBYTES;
if (RF_frame_length == Length)
{
SpiReadBurstReg(RXFIFO, RX_buff, RF_frame_length); //读取buff data
if (RX_buff[CRC_POSITION] & RF_CRC_OK)
{
RF_OneHourcnt = ONEDAYTIME; //接收到完整一帧赋初值
//DisplayCOM(); 显示通信符 三相表无此功能
RFReceiveMessage();
}
if (RFWaitSendFlag)
{
RFWaitSendFlag = 0;
RFSendData();
PublicDelayMs(8); //为了延时发送
RFSendData();
PublicDelayMs(3);
#ifdef RF_MASH
SpiWriteReg(FREND0,0x12);//弱发送
RFSendData();
PublicDelayMs(3);
SpiWriteReg(FREND0,0x17);//强发送
#endif
}
}
enable_RF_RX(); // 重启接收
RFExtInt_Init(); // 重启RF 接收中断
}
5.
CC1101外加PA时,在操控PA控制引脚时需注意电平关系,避免HH电平关系(利尔达带PA的CC1101模块禁止次电平关系),
此外PA控制引脚需要预留电平爬升时间,一般IO直接控制需要至少200us(保守2ms),如果上拉方式控制需示波器实际测量
爬升时间(利尔达PA模块爬升时间约为5ms),此爬升时间与模块内部的电解电容和上拉电阻的阻值有关系。
PA_EN; delayUs(200); //IO直接控制 //delayMs(5); //上拉方式 SpiWriteStrobe(STX);