请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
部件号: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();
/*处理分组数据,位于¤tDataEntry -> data:
*-长度是当前配置的第一个字节
*-数据从第二个字节*/开始
//RSSI字节是有效负载的下一个字节
PacketLength =*(uint8_t*)(¤tDataEntry->data);
packetDataPointer =(uint8_t*)(¤tDataEntry -> 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 ();
/*处理分组数据,位于¤tDataEntry -> data:
*-长度是当前配置的第一个字节
*-数据从第二个字节*/开始
//RSSI字节是有效负载的下一个字节
PacketLength =*(uint8_t*)(¤tDataEntry->data);
packetDataPointer =(uint8_t*)(¤tDataEntry -> data +1);
RSSI =*(INT8_t*)(¤tDataEntry -> 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);
}