This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] RTOS/CC1310:请帮助降低功耗

Guru**** 2540720 points
Other Parts Discussed in Thread: CC1190

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/606674/rtos-cc1310-please-help-decreassing-power-consumption

部件号:CC1310
主题:CC1190中讨论的其他部件

工具/软件:TI-RTOS

嗨! 您好,comunity。

我在过去的8个月里一直在开发一台设备,现在它快完工了,我遇到了一个功耗问题。 设备必须始终处于RX模式。 我尝试了无线电唤醒示例,但它增加了太多的发射器消耗,所以这不是一个好主意... 我想知道,在主核进入待机状态并通过来自射频核心的外部信号唤醒时,是否有办法让射频核心在Rx模式下保持"打开"状态...这将是完美的(只是想一点点),

问题是,我的设备在RX模式下的功耗为25 mA。 根据数据表中的信息,我做了一个计算:

RX内核:5.4 mA

射频增量:237 uA

ADC:0.75 mA

CC1190前端:3mA

所有这些都留下了大约9.3mA的总电流。但25 mA是我在测试中得到的... 所以我希望你们看看代码,也许可以找到一种减少消耗的方法。

谢谢!

代码(我不发布定义文件,因为我认为它不是必需的):

#define NUM_ROUTER 5/*****

包括***** /#include

<stdlib.h>
#include <xDC/stim.h>
#include <xDC/cfg/global.h>
#include <xDC/runrun/System.h>#include
<xdc/run/Error.h>

#include <ti/SysBIOS/bios.h/lib.h>
#sys/scnl/clock.h>#include <rf/power/semht/<rf/w/<w>










#line.l/w/w/w/<w><w><w>
包括<rf><rf></peti/peti/peti/pet/<w/</</<w><w><w><w><w><w></peti/peti/p/pet/pet/<w><w><w><w><w><w><w>包括<rf></</rf></rf></rf>#lin/p/p/pe./p/p/</</</</</p/





<simplemesh_definitions.h>
#include <ti/drivers/power/PowerCC26XX.h>

#include <ti/drivers/adc.h>/*


引脚驱动程序手柄*/
静态PIN_handle pinHandle;
static PIN_State pinState;

//引脚配置表
PIN_Config pinTable[]=
{
Board_SOL1A | PIN_GPIO输出_EN | PIN_GPIO低| PIN_PushPull | PIN_DRVSTR_MIN, /* SOL1A关闭 */
板_SOL1B | PIN_GPIO输出_EN | PIN_GPIO低| PIN_PushPull | PIN_DRVSTR_MIN, /* SOL1B关闭 */
Board_SOL2A | PIN_GPIO输出_EN | PIN_GPIO低| PIN_PushPull | PIN_DRVSTR_MIN, /* SOL2A关闭 */
Board_SOL2B | PIN_GPIO输出_EN | PIN_GPIO低| PIN_PushPull | PIN_DRVSTR_MIN, /* SOL2B关闭 */
Board_RXD | PIN_INPUT_EN | PIN_Pulldown, /* UART RX */
Board_TXD | PIN_GPIO输出_EN | PIN_GPIO _HIGH | PIN_PushPull, /* UART TX */
板_EN12V | PIN_GPIO输出_EN | PIN_GPIO低| PIN_PushPull | PIN_DRVSTR_MIN, /* RF放大器最初关闭 */
Board_RS485 | PIN_GPIO输出_EN | PIN_GPIO低| PIN_PushPull | PIN_DRVSTR_MIN, /* 555最初关闭 */
Board_PA_EN | PIN_GPIO输出_EN | PIN_GPIO低| PIN_PushPull | PIN_DRVSTR_MIN, /* 555最初关闭 */
Board_LNA_EN | PIN_GPIO输出_EN | PIN_GPIO低| PIN_PushPull | PIN_DRVSTR_MIN,
Board_HGM | PIN_GPIO输出_EN | PIN_GPIO _HIGH | PIN_PushPull | PIN_DRVSTR_MIN,
PIN_TERMINATE
};

/***** 定义***** /

//任务定义
#define RX_TASK_STACK_SIZE 1024 //las prioridades se han defido empíricamente
#define RX_TASK_PRIORY 2

#define TX_TASK_STACK_SIZE 1024
#define TX_TASK_STACK_SIZE

1024
#define DISP_TASK_PRIORY 3/*


Packet RX Configuration */
#define DATA_Entry_HEADER_SIZE 8/*常规数据条目的常量标头大小*_NUM
20 /*用于分配RX队列空间*/
#define NUM_appended_bytes 3 /*数据条目数据字段将包含:
* 1标头字节(RF_cmdProprx.rxConf.bIncludeHdr = 0x1)
有效载荷
* 1个RSSI INT8_t字节
* 1状态字节(RF_cmdProprx.rxConf.bAppendStatus = 0x1)*/*****

原型***** /
静态void回调(RF_handle h,RF_CmdHandle ch,RF_EventMask e);
静态void回叫2 (RF_handle h,RF_CmdHandle ch,RF_EventMask e);
静态void rxTaskFunction (UArg arg0,UArg arg1);
静态void TaskFunctr (UArg arg0,UArg
,Uptr,rp,rp,rp,rp,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p

变量声明***** ///task

变量
static Task_Params rxTaskParams,txTaskParams;
Task_Struct rxTask,txTask;/*不静态,因此您可以在ROV *中看到
静态uint8_t rxTaskStack[RX_task_stack_size];
静态uint_tssi静态

变量[TX_task_stack_size];//mesh =


静态0;rint =静态0;rint =静态0 //在任何TX
静态uint8_t已确认= 0之前等待随机时间;

静态RF_Object rfObject; //RF句柄变量
static RF_handle rfHandle;
RF_Params rfParams;
RF_CmdHandle rxHandle;

Power_NotifyObj powerobj;

static ADC_handle adcHandle;


/*缓冲区,包含用于接收数据的所有数据条目。
*需要pragma以确保此缓冲区是4字节对齐的(RF内核的要求)*/
#if defined(__TI_Compiler_version__)
#pragma data_align (rxDataEntryBuffer, 4);
静态uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_Entry_BUFFER_SIZE (NUM_DATA_entries,
Payload_length,
num_appended_bytes)];
静态uint8_t rxDataEntryBuffer2[RF_QUEUE_DATA_Entry_BUFFER_SIZE (NUM_DATA_entries,
Payload_length,
num_appended_bytes)];
#Elif defined (__IAR_systems_icc__)
#pragma data_alignment = 4
静态uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_Entry_BUFFER_SIZE (NUM_DATA_entries,
Payload_length,
num_appended_bytes)];
#Elif已定义(__Gnudi__)
静态uint8_t rxDataEntryBuffer [RF_QUEUE_DATA_Entry_BUFFER_SIZE (NUM_DATA_entries,
Payload_length,NUM_appended_bytes)]__attribute__(已对齐(4));
#else
错误不支持此编译器。
#endif


//packets
static tpaquete packettx,packetRX;


//rx变量
static dataQueue_t dataQueue2, dataQueue2;
static RFC_dataEntryGeneral _t* currentDataEntry;
static uint8_t packetLength;
static uint8_t* packetDataPointer;

//pin变量
static PIN_handle pinHandle;

int powerfunction (unsigned int eventType,uintptr_t eventArg, uintptr_t clientArg){
switch (eventType){
CASE PowerCC26XX_Entering_standby:
system_printf ("正在进入待机状态\n");
system_flush();
中断;
机箱PowerCC26XX_Awake待机:
system_printf ("唤醒待机\n");
system_flush();
中断;
CASE PowerCC26XX_Entering_shutdown:
system_printf ("正在输入关闭\n");
system_flush();
中断;
CASE PowerCC26XX_awake待机延迟:
system_printf ("唤醒待机延迟\n");
system_flush();
中断;
CASE PowerCC26XX_XOSC HH_SWITCHED:
system_printf ("xosc hf switched\n");
system_flush();
中断;
}
返回Power_NOTIFFYDONE;
}


作废RADIOTask_init(PIN_Handle PinHandle){ //inicializa los drivers y las tasks


PinHandle = PinHandle; //convierte la variable local en global

rf_params_init(&rfParams); //inicializa el RF内核
rfParams.n无效超时=1000;
rfHandle = RF_OPEN (&rfObject,&RF_prop,(RF_RadioSetup*)&RF_cmdPropRadioDivSetup,&rfParams);
RF_postCmd (rfHandle,(RF_Op*)&RF_cmdF,RF_PriorityNormal,NULL,0); //inicializa el frecuency sinthetizer

PINCC26XX_setMux (pinHandle,Board_PA_EN,PINCC26XX_MUX_RFC_GPO1);
PINCC26XX_setMux (pinHandle,Board_LNA_EN,PINCC26XX_MUX_RFC_GPO0);

//配置ADC驱动器
ADC_Params adcParams;
ADC_PARAM_INIT (&adcParams);
adcHandle = ADC_OPEN (Board_ADC_BATTERY,&adcParams);

Task_Params_init(&rxTaskParams);
rxTaskParams.STACKSIZE = RX_TASK_STACK_SIZE;
rxTaskParams.priority = RX_TASK_Priority;
rxTaskParams.stack =&rxTaskStack;
rxTaskParams.arg0 =(UINT) 100万;

task_construct (&rxTask,rxTaskFunction,&rxTaskParams,NULL);

Task_Params_init(&txTaskParams);
txTaskParams.STACKSIZE = TX_TASK_STACK_SIZE;
txTaskParams.priority = TX_TASK_PRIORITE;
txTaskParams.stack =&txTaskStack;
txTaskParams.arg0 =(UINT) 100万;

task_construct (&txTask,txTaskFunction,&txTaskParams,NULL);

}

静态void rxTaskFunction (UArg arg0,UArg arg1) //配置Los Comandos RF和abre引物RX操作
{

system_printf("rxtask iniciada\n"); //mensaje de consola
system_flush();


//配置el comando TX
RF_cmdPropTx.pktLen =有效载荷长度; // tamaño del paquete en bytes
RF_cmdPropTx.pPKT =(uint8_t*)&packetTX; //puntero al paquete a enviar
RF_cmdPropTx.startrigger.triggerType = trig_now; // condición ó n de inicio de la operación ó n -> inmediatamente.
RF_cmdPropTx.startrigger.PastTrig =1; //un rigger en el pasado se ejecuta lo antes potible
RF_cmdPropTx.StartTime = 0; //tiempo de inicio de la operación ó n (sin relevancia)

rf_cmdPropTX2.pktLen =有效载荷长度; // tamaño del paquete en bytes
rf_cmdPropTx2.pPKT =(uint8_t*)&packetTX; //puntero al paquete
RF_cmdPropTX2.startrigger.triggerType = trig_now; // operación empezará 绝对值(valor de rat defido)
RF_cmdPropTX2.startrigger.PastTrig = 1; //过去的触发器在可能时立即触发
RF_cmdPropTX2.pNextOp =(RFC_radioOp_t*)&RF_cmdPropRx2; // Operación ó n encadenada al final de esta.
RF_cmdPropTx2.condition.rule = cond_always; // condición para Correr siguiente operación -> siempre.


IF( RFQueue_DefineQueue(&dataQueue, //分配RX队列空间
rxDataEntryBuffer,
sizeof(rxDataEntryBuffer),
num_data_entries,
Payload_length + NUM_appended_bytes)))
{
/*无法为所有数据条目分配空间*/
system_printf ("error rx in allocating space\n");
system_flush();
while (1);
}

IF( RFQueue_DefineQueue2(&dataQueue2, //分配RX队列空间
rxDataEntryBuffer2,
sizeof(rxDataEntryBuffer2),
num_data_entries,
Payload_length + NUM_appended_bytes)))
{
/*无法为所有数据条目分配空间*/
system_printf ("error rx in allocating space\n");
system_flush();
while (1);
}


/*configure RX command*/

rf_cmdProprx.pQueue =数据队列; /*设置接收数据的数据实体队列*/
rf_cmdProprx.rxConf.bAutoFlushIgnored =1;/*丢弃Rx队列中忽略的数据包*/
rf_cmdProprx.rxConf.bAppendRssi = 1; /*在队列条目中包括RSSI */
rf_cmdProprx.rxConf.bAutoFlushCrcErr =1;/*丢弃Rx队列中带有CRC错误的数据包*/
RF_cmdProprx.maxPktLen =有效载荷长度;/*实施数据包长度过滤以避免PROP_ERROR_RXBUF */
RF_cmdProprx.pktConf.bRepeatOk = 1; //尽管接收到的接收不正确
RF_cmdProprx.pktConf.bRepeatNok = 1; //尽管接收到的信息不正确


RF_cmdPropRX2.pQueue =&dataQueue2; /*设置接收数据的数据实体队列*/
rf_cmdPropRX2.rxConf.bAutoFlushIgnored =1;/*丢弃Rx队列中忽略的数据包*/
rf_cmdPropRX2.rxConf.bAutoFlushCrcErr =1;/*丢弃Rx队列中带有CRC错误的数据包*/
RF_cmdPropRX2.maxPktLen =有效载荷长度;/*实施数据包长度过滤以避免PROP_ERROR_RXBUF */
RF_cmdPropRx2.pktConf.bRepeatOk = 1; //repetrr收到的paquetes buenos
RF_cmdPropRx2.pktConf.bRepeatNok = 1; //repetrx al recibir paquetes malos
RF_cmdPropRX2.endTrigger.triggerType = trig_REL_start;// operación terminará despu é s de un tiempo relativo al comienzo de la operación ó n
RF_cmdPropRX2.EndTime = Conf_waiting_Time_router; //tiempo de duración ó n de la operación ó n

rxHandle = RF_postCmd (rfHandle,(RF_Op*)&RF_cmdPropRx,RF_PriorityNormal,&callback,IRQ_RX_Entry_Done); //pone en cola la operación ó n de Rx, al ser RF_postCmd, pasa a la siguiente línea inmediatamente, el rxHandle es necesario para poder cancelar la operación ó n cuando sea necesario
} //activa la interrupción ó n que llama a "callback" cada que se recipe un paquete

void callback (RF_handle h,RF_CmdHandle ch,RF_EventMask e){ // función ó n llamada cada que se recipe un paquete en Rx,'e' es la mascara de eventos que activó ó n la función ó n
如果(e和RF_EventRxEntryDone){ //si se activó la función ó n por paquete recibido (sin relevancia por ser la unica condicio)
/*切换引脚以指示RX */
system_printf("paquete recibido\n"); //mensaje de consola
system_flush();
paqreccola++; //contador de paquetes en cola de Reception //contador de paquetes recividos totales para display
}
}

void callback2 (RF_handle h,RF_CmdHandle ch,RF_EventMask e){ // función ó n llamada cada que se recipe un paquete en Rx,'e' es la mascara de eventos que activó ó n la función ó n
如果(e和RF_EventRxEntryDone){ //si se activó la función ó n por paquete recibido (sin relevancia por ser la unica condicio)
/*切换引脚以指示RX */
system_printf ("poible confirmación recibida\n"); //mensaje de consola
system_flush();

/*获取当前未处理的数据输入*/
currentDataEntry = RFQueue_getDataEntry2();
/*处理分组数据,位于&currentDataEntry -> data:
*-长度是当前配置的第一个字节
*-数据从第二个字节*/开始
//RSSI字节是有效负载的下一个字节
PacketLength =*(uint8_t*)(&currentDataEntry->data);
packetDataPointer =(uint8_t*)(&currentDataEntry -> data +1);

if(packetLength != PAYLOAD长度){ //verifica que el paquete sea de la longitud establecida
system_printf ("recibido paquete de longitud\n不正确");
system_flush();
RFQueue_nextEntry2();
返回;
}

memcpy(&packetRX, packetDataPointer, payload_length); //copia la data de la payload en nuestra varaible de paquete de recepción ó n //contador de paquetes en cola de Reception //contador de paquetes recividos totales para display
IF (packetRX.type == simle_4CONTROLLER_CONF && numsensor == packetRX.sensor && NUM_router == packetRX.router){
已确认= 1;
system_printf (" confirmación identificada\n");
system_flush();
rf_flushCmd (rfHandle,rf_CMDHANDLE_flush_all,0);
}
RFQueue_nextEntry2();
}
}

静态void txTaskFunction(UArg arg0, UArg arg1 ){ //comprueba si hay paquetes en cola y acta en consecuencia
Int_fast16_t adcRes;
UINT16_t adcValue;
UINT32_t adcMicrovolts;
uINT8_t i;

而(1){
如果(paqreccola >0){
paqreccola --;

//genera el número aleatorio que se usará para el delay antes de cualquier TX mediante el driver TRNG (真实随机数生成器)
POWER_setDependency (PowerCC26XX_Periph_TRNG); //Evita que el MCU entre en standby mientras se genera el número aleatorio mediante una dependencia entre el power driver y el TRNG
TRNGConfigure(0x40,0x100,0); //configura el TRNG
TRNGEnable(); //activa el TRNG
while (!(TRNGStatusGET()& TRNG_NUMBER_READY )); //espera que est é disponible el número í a aleatorio
随机=((uint8_t)(TRNGNumberGet (TRNG_low_word)))/6 + 8); // Lee el número aleatorio generado
TRNGDisable(); //去激活
Power_releaseDependency (PowerCC26XX_Periph_TRNG); //quita la dependencia del power driver con el TRNG

//System_printf ("empezando tx task\n");
//System_flush();

/*获取当前未处理的数据输入*/
currentDataEntry = RFQueue_getDataEntry ();
/*处理分组数据,位于&currentDataEntry -> data:
*-长度是当前配置的第一个字节
*-数据从第二个字节*/开始
//RSSI字节是有效负载的下一个字节
PacketLength =*(uint8_t*)(&currentDataEntry->data);
packetDataPointer =(uint8_t*)(&currentDataEntry -> data +1);
RSSI =*(INT8_t*)(&currentDataEntry -> data+1+packetLength);

if(packetLength != PAYLOAD长度){ //verifica que el paquete sea de la longitud establecida
system_printf ("recibido paquete de longitud\n不正确");
system_flush();
RFQueue_nextEntry();
返回;
}

memcpy(&packetRX, packetDataPointer, payload_length); //copia la data de la payload en nuestra varaible de paquete de recepción ó n

Switch(packetRX.type){ //ejecuta diferentes tareas deependiendo del tipo de mensaje identificado.
Case simone_4ROUTER:

if (packetRX.router == NUM_router){ //si no se ha sobre repasado el número máximo ó n de saltos

system_printf ("mensaje para router identificado\n"); //mensaje de consola
system_flush();

adcMicrovolts = Codigo _错误_BATERIA;
adcRes = adc_convert (adcHandle,&adcValue);
IF (adcRes == ADC_STATUS_SUCCESS)
adcMicrovolts = adc_convertRawToMicrovolts (adcHandle,adcValue);

packettx = packetRX; //copia el paquete en la variable de transmisión ó n
packetTX.sensorRSSI = RSSI; //poner RSSI en ultimo espacio
packetTX.type = simle_4CONTROLLER;
memcpy((&packetTX.routerBattery[0]),&adcMicrovolts, 4);


TASK_SLEEP (RANDOM *(1000/Clock_tickPeriod)); //espera un tiempo aleatorio antes de enviar el paquete

已确认= 0;
numsensor = packetRX.sensor;

rf_cancelCmd (rfHandle,rxHandle,1); //Cerrar RX
对于(i = 0;i < MAX_CONF_intentos;I++){

system_printf ("4router repetdo,esperando confirmación \n");
system_flush();
RF_runCmd (rfHandle,(RF_Op*)&RF_cmdPropTx2,RF_PriorityNormal,&callback2,IRQ_RX_Entry_Done);
IF (已确认== 1) Break;
}
rxHandle = RF_postCmd (rfHandle,(RF_Op*)&RF_cmdPropRx,RF_PriorityNormal,&callback,IRQ_RX_Entry_Done); //pone en cola la operación ó n de Rx, al ser RF_postCmd, pasa a la siguiente línea inmediatamente, el rxHandle es necesario para poder cancelar la operación ó n cuando sea necesario
}
中断;
Case simone_4阀: //mensaje para valvula
if (packetRX.router == NUM_router){
system_printf ("mensaje para válvula identificado\n");
system_flush();
packettx = packetRX;
packetTX.type = simple 4 Valve_Conf;
rf_cancelCmd (rfHandle,rxHandle,1); //Cerrar RX
RF_runCmd (rfHandle,(RF_Op*)&RF_cmdPropTx,RF_PriorityNormal,0,NULL);
system_printf (" confirmación环境\n"); //mensaje de consola
system_flush();
rxHandle = RF_postCmd (rfHandle,(RF_Op*)&RF_cmdPropRx,RF_PriorityNormal,&callback,IRQ_RX_Entry_Done); //pone en cola la operación ó n de Rx,al ser RF_postCmd,pasa a la siguiente línea ó n inmediatamente,el rxHandle es necesario para poder cancelar la operación ó n cuando sea necesario
switch (packetRX.data[0]){
案例1: //瓣膜1
PIN_setOutputValue (pinHandle,Board_SOL1A,PacketRX.DATA[1]?1:0);
PIN_setOutputValue (pinHandle,Board_SOL1B,PacketRX.DATA[1]?0:1);
PIN_setOutputValue (pinHandle,Board_SOL2A,0);
PIN_setOutputValue (pinHandle,Board_SOL2B,0);
中断;
案例2: //valvula 2.
PIN_setOutputValue (pinHandle,Board_SOL1A,0);
PIN_setOutputValue (pinHandle,Board_SOL1B,0);
PIN_setOutputValue (pinHandle,Board_SOL2A,PacketRX.DATA[1]?1:0);
PIN_setOutputValue (pinHandle,Board_SOL2B,PacketRX.DATA[1]?0:1);
中断;
默认:
中断;
}

PIN_setOutputValue (pinHandle,Board_EN12V,1);
TASK_SLEEP (200*(1000/Clock_tickPeriod));
Pin_setOutputValue (pinHandle,Board_EN12V,0);
}
中断;

默认: //mensaje no identificado
中断;
}

RFQueue_nextEntry(); //quita último ó n paquete de la cola de recepción ó n
//System_printf ("terminando txTask\n");
//System_flush();
}
}
}/*


==== 主====
*/
int main (void)
{

IF (sizeof(packetTX)!= PAYLOAD长度) System_ABORT ("Error in PAYLOAD长度\n"); //faro en la varaible payload_length defida en "mesh_definitions.h"。no fappel con el tamaño ó n Real de la estructura defida para los paquetes

/*呼叫板初始化功能。 */
Board_initGeneral ();
Board_initADC();

// PIN打开
pinHandle = PIN_OPEN (&pinState,pinTable); //配置PIN驱动程序
IF (!pinHandle)
{
system_abort("初始化板LED针脚时出错\n");}


system_printf("router iniciado\n");
system_flush();

/*初始化驱动程序和任务*/
RADIOTask_init (pinHandle);

POWER_registerNotify(&powerobj, 25,&powerfunction, 0);

/*启动BIOS */
BIOS_START();

返回(0);


}


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在查找代码之前:
    如果开箱运行packetrx示例(在主板上运行时略有更改),您会得到什么? 我想排除硬件对当前消耗的任何贡献。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    不要在paqreccola为零时旋转,而是使用信号。

    当前,您的系统内核正在运行100 % of the time,而不是在等待数据包时空闲。

    信号可以是二进制或计数,我认为二进制信号足够-一旦semaphore_pend返回,循环直到缓冲区耗尽,然后返回到pend。

    对讲机运行时,系统内核不可能进入休眠状态,因为对讲机需要XOSC。 但是,系统内核可以空闲,这将比持续检查变量消耗的功率更少。

    另外,请检查硬件的其余部分的消耗情况,我不确定这些针脚的用途是什么,或者您是否有任何LED指示灯亮起或类似情况。