TI中文支持网
TI专业的中文技术问题搜集分享网站

RFEasyLinkEchoTX例程中,会出现发送不成功的问题

今天在调试RFEasyLinkEchoTx的例程中,发现调用EasyLink_transmitCcaAsync进行发送时,一直出现发送不成功的现象。请问这个是哪里出现问题了。

之前也有利用RFEasyLinkEcho的工程进行收发,之前还是可以好好发送的,之后就会出现发送不成功的现象,然后不管怎样就是发送不成功。请教一下工程师,出现这种问题是什么原因?

我使用的是官方开发板。

lin shi chang:

这是我主程序的内容,因为利用这个工程做远程配置的功能。所以不好进行验证。就请工程师看看发送那部分的逻辑有没有问题

/**======== rfEasyLinkEchoTx.c ========*//* Standard C Libraries */
#include <stdlib.h>
#include <stdint.h>

/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/runtime/Assert.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Clock.h>

/* Board Header files */
#include "Board.h"
#include "smartrf_settings/smartrf_settings.h"
#include "easylink/EasyLink.h"
#include "user/message.h"
#if DISPLAY_OPEN
#include <ti/display/Display.h>
#endif
#include <ti/drivers/NVS.h>
#include <ti/devices/cc13x0/driverlib/sys_ctrl.h>
#include <unistd.h>
#include <ti/drivers/rf/RF.h>

#define RFEASYLINKECHO_TASK_STACK_SIZE2048
#define RFEASYLINKECHO_TASK_PRIORITY2

#define RFEASYLINKECHO_RF_POWER 10

Task_Struct echoTask;/* not static so you can see in ROV */
static Task_Params echoTaskParams;
static uint8_t echoTaskStack[RFEASYLINKECHO_TASK_STACK_SIZE];

static bool bBlockTransmit = true;
static Semaphore_Handle echoDoneSem;

EasyLink_TxPacket txPacket = {{0}, 0, 0, {0}};

/***************************Handle***************************/
#if DISPLAY_OPEN
extern Display_Handle uartDisplayHandle;
#endif
/*NVS handle*/
NVS_Handle nvsHandle;
NVS_Attrs regionAttrs;
/* Pin driver handle */
PIN_State pinState;
/* clock driver handle */
Clock_Struct TxConfigClock;
Clock_Handle hTxConfigClock;

/* TX Semaphore */
Semaphore_Struct TxConfigSemaphore;
Semaphore_Handle TxConfigSemaphoreHandle;

/***************************variable***************************/
Config_Req TX_Config = {//节点初始化通信配置.Data.Frequency = 868000000,.Data.Address= 0xAA,.Data.Time_ms= 10000,.Data.Status= 0,//状态标志位:0:配置阶段 1:正常运行
};
Ack_Req TX_Ack = {.head.Mache = 0x02,.head.Func= 0x84,.Issuccess= false,
};
Data_Req Data = {.head.Mache = 0x01,.head.Func= 0xA0,
};
Recv_Ack_Req RE_Ack;
Rx_ACK_ReqRx_Ack;
uint8_t Cnf_Buff[11];
uint32_t Frq;
uint8_t Add;
uint32_t Time;
bool Status_Flag;
bool Reset_Flag = false;
bool Recv_Flag = false;
uint16_t CRC;
int8_t get_power;
bool WTD_FLAG;

/**************************************************************/
PIN_Config pinTable[] = {Board_PIN_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PULLDOWN | PIN_DRVSTR_MAX,Board_PIN_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PULLDOWN | PIN_DRVSTR_MAX,Board_SPI_CS| PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PULLDOWN | PIN_DRVSTR_MAX,
PIN_TERMINATE
};

/******************************配置阶段使用该定时器******************************/
static void TxConfigClockCb(UArg arg0)
{Clock_start(hTxConfigClock);//在clock的callback函数中必须添加,否则只能进入一次该函数Semaphore_post(TxConfigSemaphoreHandle);
}

void Txconfig_clock_construct(uint32_t time_ms)
{Clock_Params clockParams;Clock_Params_init(&clockParams);clockParams.arg = 0;clockParams.period = 0;//10usClock_construct(&TxConfigClock, TxConfigClockCb, time_ms * (1000 / Clock_tickPeriod), &clockParams);hTxConfigClock = Clock_handle(&TxConfigClock);
Clock_start(hTxConfigClock);//启动定时器
}
/**************************************************************************/

void echoTxDoneCb(EasyLink_Status status)
{if (status == EasyLink_Status_Success){
}else{PIN_setOutputValue(pinHandle, Board_PIN_LED0,!PIN_getOutputValue(Board_PIN_LED0));}
Semaphore_post(echoDoneSem);
}

void echoRxDoneCb(EasyLink_RxPacket * rxPacket, EasyLink_Status status)
{if (status == EasyLink_Status_Success){if(rxPacket->payload[0] == 0x03 && rxPacket->payload[1] == 0x85)//配置器配置命令{//将数据拷贝到配置结构体中memcpy(&TX_Config,rxPacket->payload,sizeof(Config_Req));CRC = crc16((uint8_t *)&TX_Config,sizeof(Config_Req) – 2);if(TX_Config.Crc16 == CRC){bBlockTransmit = false; /* Permit echo transmission */}}else if(rxPacket->payload[0] == 0x03 && rxPacket->payload[1] == 0x86)//配置器ACK{memcpy(&RE_Ack,rxPacket->payload,sizeof(Recv_Ack_Req));CRC = crc16((uint8_t *)&RE_Ack,sizeof(Recv_Ack_Req) – 2);if(CRC == RE_Ack.Crc16){if(memcmp(&RE_Ack.mac,&TX_Ack.Mac,8) == 0){//接收到配置器ACK,可以重启节点。Reset_Flag = true;}}}}else if (status == EasyLink_Status_Aborted){
}else{
}
Semaphore_post(echoDoneSem);
}

static void rfEasyLinkEchoTxFnx(UArg arg0, UArg arg1)
{/* Create a semaphore for Async */Semaphore_Params params;Error_Blockeb;uint8_t i;
/* Init params */Semaphore_Params_init(&params);Error_init(&eb);
/* Create semaphore instance */echoDoneSem = Semaphore_create(0, &params, &eb);if(echoDoneSem == NULL){System_abort("Semaphore creation failed");}
// Initialize the EasyLink parameters to their default valuesEasyLink_Params easyLink_params;EasyLink_Params_init(&easyLink_params);
/** Initialize EasyLink with the settings found in easylink_config.h* Modify EASYLINK_PARAM_CONFIG in easylink_config.h to change the default* PHY*/if(EasyLink_init(&easyLink_params) != EasyLink_Status_Success){System_abort("EasyLink_init failed");}
/** If you wish to use a frequency other than the default, use* the following API:* EasyLink_setFrequency(868000000);*///获取自身的MAC地址uint8_t Status = EasyLink_getIeeeAddr(TX_Ack.Mac);if(Status == EasyLink_Status_Success){memcpy(Data.Mac,TX_Ack.Mac,8);}
if(Status_Flag == false){Txconfig_clock_construct(TX_TIME);Status = EasyLink_setRfPower(DB1);//处于配置阶段,在可以传输的条件下,将发送强度设置为最小值}else{Status = EasyLink_setRfPower(DB2);//正式工作时,将信号强度设置成最大}
EasyLink_setFrequency(Frq);RF_yield(rfHandle);
// Packet Originatorwhile(1){if(Status_Flag == false){//配置阶段,节点处于接收状态一段时间EasyLink_receiveAsync(echoRxDoneCb, 0);
/* Wait 500ms indefinitely for Rx *///3usif(Semaphore_pend(echoDoneSem, (3 / Clock_tickPeriod)) == FALSE)//,(500000 / Clock_tickPeriod){/* RX timed out abort */if(EasyLink_abort() == EasyLink_Status_Success){/* Wait for the abort */Semaphore_pend(echoDoneSem, BIOS_WAIT_FOREVER);}}if(bBlockTransmit == false){bBlockTransmit = true;//发送ACK,将得到的频率地址重新发回去。TX_Ack.Crc16 = crc16((uint8_t *)&TX_Ack, sizeof(Ack_Req) – 2);memcpy(txPacket.payload, &TX_Ack, sizeof(Ack_Req));txPacket.len = sizeof(Ack_Req);txPacket.dstAddr[0] = Add;txPacket.absTime = 0;for(i = 0; i < 3; i++)//多次发送ACK,以此得到ReACK,进一步进行复位。否则下一个周期继续{EasyLink_transmitCcaAsync(&txPacket, echoTxDoneCb);Semaphore_pend(echoDoneSem, BIOS_WAIT_FOREVER);
EasyLink_receiveAsync(echoRxDoneCb, 0);/* Wait 1s indefinitely for Rx */if(Semaphore_pend(echoDoneSem, (1000000 / Clock_tickPeriod)) == FALSE)//{/* RX timed out abort */if(EasyLink_abort() == EasyLink_Status_Success){/* Wait for the abort */Semaphore_pend(echoDoneSem, BIOS_WAIT_FOREVER);}}
if(Reset_Flag == true){break;}else{Task_sleep(50000);}}if(Reset_Flag == true){//把数据拷到NVS寄存器中,发送ACK,等待接收ACKNVS_erase(nvsHandle, 0, regionAttrs.sectorSize);NVS_write(nvsHandle, 0, &TX_Config.Data,sizeof(Config_Data),\NVS_WRITE_PRE_VERIFY | NVS_WRITE_POST_VERIFY);//延时1s进行软复位sleep(1);SysCtrlSystemReset();}}//休眠,等待下一个周期继续听RF_yield(rfHandle);Semaphore_pend(TxConfigSemaphoreHandle, BIOS_WAIT_FOREVER);}else{send_pend();Data.Crc16 = crc16((uint8_t *)&Data, sizeof(Data_Req) – 2);memcpy(txPacket.payload, &Data, sizeof(Data_Req));txPacket.len = sizeof(Data_Req);//18txPacket.dstAddr[0] = Add;txPacket.absTime = 0;
EasyLink_transmitCcaAsync(&txPacket, echoTxDoneCb);Semaphore_pend(echoDoneSem, BIOS_WAIT_FOREVER);
RF_yield(rfHandle);}}
}

void echoTask_init() {
/* Initialize TX semaphore */Semaphore_construct(&TxConfigSemaphore, 0, NULL);TxConfigSemaphoreHandle = Semaphore_handle(&TxConfigSemaphore);
Task_Params_init(&echoTaskParams);echoTaskParams.stackSize = RFEASYLINKECHO_TASK_STACK_SIZE;echoTaskParams.priority = RFEASYLINKECHO_TASK_PRIORITY;echoTaskParams.stack = &echoTaskStack;echoTaskParams.arg0 = (UInt)1000000;
Task_construct(&echoTask, rfEasyLinkEchoTxFnx, &echoTaskParams, NULL);
}

/**======== main ========*/
int main(void)
{/* Call driver init functions. */Board_initGeneral();pinHandle = PIN_open(&pinState, pinTable);NVS_Init();
//读寄存器存在两个全局变量中(频率和地址)NVS_read(nvsHandle, 0, (void *) Cnf_Buff, sizeof(Cnf_Buff));if(Cnf_Buff[0] == 0xFF && Cnf_Buff[1] == 0xFF && Cnf_Buff[2] == 0xFF){//如果NVS寄存器中没有内容,就用初始值作为配置时的通讯Frq= TX_Config.Data.Frequency;Add= TX_Config.Data.Address;Time= TX_Config.Data.Time_ms;Status_Flag= TX_Config.Data.Status;NVS_write(nvsHandle, 0, &TX_Config.Data,sizeof(Config_Data),\NVS_WRITE_PRE_VERIFY | NVS_WRITE_POST_VERIFY);}else{//将读取到的值存到对应的变量中memcpy(&TX_Config.Data, Cnf_Buff, sizeof(Config_Data));Frq= TX_Config.Data.Frequency;Add= TX_Config.Data.Address;Time= TX_Config.Data.Time_ms;Status_Flag= TX_Config.Data.Status;}
echoTask_init();if(Status_Flag){PIN_setOutputValue(pinHandle, Board_PIN_LED1, CC1310_LAUNCHXL_GPIO_LED_ON);TempTask_init();}
/* Start BIOS */BIOS_start();
return (0);
}

/*****************crc校验**********************************************/
//crc生成函数,并将crc存储在预先定于的数组中
//调用方式crc16(指向数据的指针,需要校验的数据长度)
uint16_t crc16(uint8_t *ptr,size_t len)
{unsigned long wcrc=0XFFFF;//预置16位crc寄存器,初值全部为1int i=0,j=0;//定义计数for(i=0;i<len;i++){//循环计算每个数据wcrc^=*ptr++;//将八位数据与crc寄存器亦或.指针地址增加,指向下个数据for(j=0;j<8;j++){//循环计算数据的{if(wcrc&0X0001){//判断右移出的是不是1,如果是1则与多项式进行异或。wcrc=wcrc>>1^0XA001;//先将数据右移一位再与上面的多项式进行异或}else{//如果不是1,则直接移出wcrc>>=1;//直接移出}}}return wcrc<<8|wcrc>>8;//低八位在前,高八位在后
}

void NVS_Init()
{NVS_Params nvsParams;
NVS_init();NVS_Params_init(&nvsParams);nvsHandle = NVS_open(Board_NVSINTERNAL, &nvsParams);
if (nvsHandle == NULL) {SysCtrlSystemReset();}else{NVS_getAttrs(nvsHandle, &regionAttrs);}
}

Kevin Qiu1:

SDK版本是多少,发送不成功具体是什么现象,是否有串口log信息

lin shi chang:

回复 Kevin Qiu1:

SDK版本:simplelink_cc13x0_sdk_3_20_00_23。

没有串口LOG信息,节点端不设置串口。

发送不成功具体现象:一直进入TX的回调函数中,不成功的那一项,翻转LED灯

void echoTxDoneCb(EasyLink_Status status)

{

   if (status == EasyLink_Status_Success)

   {

   }

   else

   {

       PIN_setOutputValue(pinHandle, Board_PIN_LED0,!PIN_getOutputValue(Board_PIN_LED0));

   }

   Semaphore_post(echoDoneSem);

}

Kevin Qiu1:

回复 lin shi chang:

//! \brief Sends a Packet with non blocking call if the channel is idle.
//!
//! This function is a non blocking call to send a packet. It will check for a
//! clear channel prior to transmission. If the channel is busy it will backoff
//! for a random period, in time units of EASYLINK_CCA_BACKOFF_TIMEUNITS, before
//! reassessing. It does this a certain number
//! (EASYLINK_MAX_CCA_BACKOFF_WINDOW - EASYLINK_MIN_CCA_BACKOFF_WINDOW)
//! of times before quitting unsuccessfully and running to the callback.
//! If the Tx is successfully scheduled then the callback will be called once
//! the Tx is complete.
//!
//! \param txPacket The descriptor for the packet to be Tx'ed.
//! \param cbThe tx done function pointer.
//!
//! \return ::EasyLink_Status
//
//*****************************************************************************
extern EasyLink_Status EasyLink_transmitCcaAsync(EasyLink_TxPacket *txPacket,EasyLink_TxDoneCb cb);

看起来应该是通道被占用,不是处于空闲状态

lin shi chang:

回复 Kevin Qiu1:

当前通道上,我只有一个设备在通信,应该不会被占用啊!
这个函数判断是否空闲有个阈值,默认是,没有更改。
//! \brief RSSI threshold for Clear Channel Assessment (CCA)
#define EASYLINK_CS_RSSI_THRESHOLD_DBM-80

1.为了避免在出现这种情况,发送的模式是否要更改为其他方式的发送?如EasyLink_transmitAsync()
2.如果我仍然使用EasyLink_transmitCcaAsync(),进行发送。我使用的是LRM5K模式,这个阈值设置的最佳值应该为多少?,会不会再次出现这种情况?

Kevin Qiu1:

回复 lin shi chang:

用例程不做修改会出现问题吗

lin shi chang:

回复 Kevin Qiu1:

我需要做这样的修改。程序做这样修改,之前跑也没出现这个问题。感觉使用EasyLink_transmitCcaAsync()函数,时不时会出现这个问题。
我使用EasyLink_transmitCcaAsync(),的主要目的是想避免多个设备发送数据时产生相互干扰。
看来,我应该更改使用EasyLink_transmitAsync().更稳定一点。

Kevin Qiu1:

回复 lin shi chang:

是,用EasyLink_transmitAsync不涉及通道占用的问题

赞(0)
未经允许不得转载:TI中文支持网 » RFEasyLinkEchoTX例程中,会出现发送不成功的问题
分享到: 更多 (0)