51uwb.cn

标题: 关于LPL低功耗模式得疑问 [打印本页]

作者: Nero.qi    时间: 2022-3-17 11:15
标题: 关于LPL低功耗模式得疑问
现有设备在待机状态和接收状态时功耗在200ma左右,如果标签长时间处于接收状态则会让电池迅速的耗电,所以我设想使用Low_Power_Listening模式和帧过滤相互结合 标签长时间处于LPL模式 并定时唤醒检测信息 如果收到FCG则进入中断处理数据,我参照了官方提供的例程代码 原官方代码如下


作者: Nero.qi    时间: 2022-3-17 11:17
int main(void)
{
    uint32 lp_osc_freq, sleep_cnt;

    /* Start with board specific hardware init. */
    peripherals_init();

    /* Display application name on LCD. */
    lcd_display_str(APP_NAME);

    /* Install the low-power listening ISR handler.
     * This is an interrupt service routine part of the driver that is specific to correctly handling the low-power listening wake-up. */
    port_set_deca_isr(dwt_lowpowerlistenisr);

    /* Reset and initialise DW1000. See NOTE 8 and 9 below.
     * For initialisation, DW1000 clocks must be temporarily set to crystal speed. After initialisation SPI rate can be increased for optimum
     * performance. */
    reset_DW1000(); /* Target specific drive of RSTn line into DW1000 low for a period. */
    spi_set_rate_low();
    if (dwt_initialise(DWT_LOADNONE) == DWT_ERROR)
    {
        lcd_display_str("INIT FAILED");
        while (1)
        { };
    }
    spi_set_rate_high();

    /* This is put here for testing, so that we can see the receiver ON/OFF pattern using an oscilloscope. */
    dwt_setlnapamode(1, 1);

    /* Configure DW1000. See NOTE 10 below. */
    dwt_configure(&config);

    /* Calibrate and configure sleep count. This has to be done with DW1000 clocks set to crystal speed.
     * This will define the duration of the "long sleep" phase. */
    spi_set_rate_low();
    lp_osc_freq = (XTAL_FREQ_HZ / 2) / dwt_calibratesleepcnt();
    sleep_cnt = ((LONG_SLEEP_TIME_MS * lp_osc_freq) / 1000) >> 12;
    dwt_configuresleepcnt(sleep_cnt);
    spi_set_rate_high();

    /* Configure sleep mode to allow low-power listening to operate properly. */
    dwt_configuresleep(DWT_PRESRV_SLEEP | DWT_CONFIG | DWT_RX_EN, DWT_WAKE_SLPCNT | DWT_SLP_EN);

    /* Set snooze time. This will define the duration of the "short sleep" phase. */
    dwt_setsnoozetime(LPL_SHORT_SLEEP_SNOOZE_TIME);

    /* Set preamble detect timeout. This will define the duration of the reception phases. */
    dwt_setpreambledetecttimeout(LPL_RX_SNIFF_TIME);

    /* Register RX call-back. */
    dwt_setcallbacks(NULL, &rx_ok_cb, NULL, NULL);

    /* Enable wanted interrupts (RX good frames only). */
    dwt_setinterrupt(DWT_INT_RFCG, 1);

    /* Enable low-power listening mode. */
    dwt_setlowpowerlistening(1);

    /* Go to sleep to trigger low-power listening mode. */
    dwt_entersleep();

    /* Loop forever receiving frames. */
    while (1)
    {
        uint16 wus_end_frame_nb;
        uint32 wus_end_time_ms;

        /* Wait for a frame to be received.
         * The user should look at the "rx_ok_cb" function below to see the next piece of RX handling before reading on through the rest of the main
         * line code here. */
        while (!rx_frame)
        { };

        /* Configure DW1000 for next sleep phases so we can go to DEEPSLEEP and wake with SPI CS wake-up. */
        dwt_configuresleep(DWT_PRESRV_SLEEP | DWT_CONFIG, DWT_WAKE_CS | DWT_SLP_EN);

        /* Read received frame's countdown to the end of the wake-up sequence. */
        wus_end_frame_nb = (rx_buffer[DATA_FRAME_WUS_CNTDWN_IDX + 1] << 8) + rx_buffer[DATA_FRAME_WUS_CNTDWN_IDX];
        wus_end_time_ms = (wus_end_frame_nb * WUS_FRAME_TIME_US) / 1000;

        /* Check that the wake-up sequence is destined to this application. */
        if ((rx_buffer[DATA_FRAME_DEST_ADDR_IDX + 1] == 'R') && (rx_buffer[DATA_FRAME_DEST_ADDR_IDX] == 'X'))
        {
            /* TESTING BREAKPOINT LOCATION #1 */

            /* Put the DW1000 to sleep. */
            dwt_entersleep();

            /* Wait for the end of the wake-up sequence. */
            sleep_ms(wus_end_time_ms);

            /* Wake DW1000 up. See NOTE 7 below. */
            dwt_spicswakeup(dummy_buffer, DUMMY_BUFFER_LEN);

            /* Write interaction message data to DW1000 and prepare transmission. See NOTE 11 below. */
            dwt_writetxdata(sizeof(interaction_msg), interaction_msg, 0); /* Zero offset in TX buffer. */
            dwt_writetxfctrl(sizeof(interaction_msg), 0, 0); /* Zero offset in TX buffer, no ranging. */

            /* Start transmission. */
            dwt_starttx(DWT_START_TX_IMMEDIATE);

            /* Poll DW1000 until TX frame sent event set. See NOTE 12 below.
             * STATUS register is 5 bytes long but we are not interested in the high byte here, so we read a more manageable 32-bits with this API
             * call. */
            while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS))
            { };

            /* Clear TX frame sent event. */
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);

            /* Increment the frame sequence number (modulo 256). */
            interaction_msg[DATA_FRAME_SEQ_NB_IDX]++;
        }
        else
        {
            /* TESTING BREAKPOINT LOCATION #2 */

            /* Compute the time until the end of the interaction period (after end of the wake-up sequence). */
            uint32 sleep_time_ms = wus_end_time_ms + INTERACTION_PERIOD_MAX_TIME_MS;

            /* Put the DW1000 to sleep. */
            dwt_entersleep();

            /* Wait for the end of the interaction period. */
            sleep_ms(sleep_time_ms);

            /* Wake DW1000 up. See NOTE 7 below. */
            dwt_spicswakeup(dummy_buffer, DUMMY_BUFFER_LEN);
        }

        /* Go back to low-power listening.
         * Sleep mode must be reconfigured to allow low-power listening to operate properly as it has been modified earlier. */
        dwt_configuresleep(DWT_PRESRV_SLEEP | DWT_CONFIG | DWT_RX_EN, DWT_WAKE_SLPCNT | DWT_SLP_EN);
        dwt_setlowpowerlistening(1);
        dwt_entersleep();
        rx_frame = 0;
    };
}

作者: Nero.qi    时间: 2022-3-17 11:19
官方的例程如果收到正确得FCG 会进入到中断服务函数 static void rx_ok_cb(const dwt_cb_data_t *cb_data)
程序如下
/*! ------------------------------------------------------------------------------------------------------------------
* @fn rx_ok_callback()
*
* @brief Call-back to process RX good frames events
*
* @param  cb_data  call-back data
*
* @return  none
*/
static void rx_ok_cb(const dwt_cb_data_t *cb_data)
{
    if (cb_data->datalength == WUS_FRAME_LEN)
    {
        /* A frame of correct length to be a wake-up message has been received, copy it to our local buffer. */
        dwt_readrxdata(rx_buffer, cb_data->datalength, 0);

        /* Validate the frame is addressed to us from the expected sender and has the encoding of one of the wake-up sequence messages we expect.
         * Then signal the arrival of the wake-up message to the background main loop by setting the rx_frame event flag. */
        if ((rx_buffer[DATA_FRAME_PAN_ID_IDX + 1] == 0xDE) && (rx_buffer[DATA_FRAME_PAN_ID_IDX] == 0xCA)
            && (rx_buffer[DATA_FRAME_SRC_ADDR_IDX + 1] == 'T') && (rx_buffer[DATA_FRAME_SRC_ADDR_IDX] == 'X')
            && (rx_buffer[DATA_FRAME_APP_FCODE_IDX] == 0xE0))
        {
            rx_frame = 1;
        }
    }

    /* If the frame is not from the expected wake-up sequence, go back to low-power listening. */
    if (!rx_frame)
    {
        dwt_setlowpowerlistening(1); /* No need to reconfigure sleep mode here as it has not been modified since wake-up. */
        dwt_entersleep();
        non_wus_frame_rx_nb++;
    }
}

作者: Nero.qi    时间: 2022-3-17 11:21
现在我的问题是  我将程序移植到我的代码里 不能进入到  rx_ok_callback()中断内
作者: Nero.qi    时间: 2022-3-17 11:26
以下是我设置的相关的代码
        reset_DW1000(); /* RSTn低电平一段时间 */
       
        //if (dwt_initialise(DWT_LOADNONE) == DWT_ERROR)
        if (dwt_initialise(DWT_LOADUCODE) == DWT_ERROR)
        {
                Display_8x16_ASCII_Str("INIT FAILED",2,0);
                while (1)
                        ;
        }
       
        //设置发送功率
        dwt_write32bitreg(TX_POWER_ID,0x3e3e3e3e);
        status_reg = dwt_read32bitreg(TX_POWER_ID);
        if(status_reg != 0x3e3e3e3e)
        {
                dwt_write32bitreg(TX_POWER_ID,0x3e3e3e3e);
        }
       
        hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
        {
    Error_Handler();
  }
       
        dwt_configure(&config_idle);
               
        /* Apply default antenna delay value. See NOTE 1 below. */
        dwt_setrxantennadelay(RX_ANT_DLY);
        dwt_settxantennadelay(Station_Ant_Dly[0]);

        dwt_setrxaftertxdelay(POLL_TX_TO_RESP_RX_DLY_UUS);
        dwt_setrxtimeout(RESP_RX_TIMEOUT_UUS);
//        dwt_setpreambledetecttimeout(PRE_TIMEOUT);
//        UWB_Message_Config();
       
        dwt_setlnapamode(1, 1);

        /* Calibrate and configure sleep count. This has to be done with DW1000 clocks set to crystal speed.
         * This will define the duration of the "long sleep" phase. */
        spi_set_rate_low();
        lp_osc_freq = (XTAL_FREQ_HZ / 2) / dwt_calibratesleepcnt();
        sleep_cnt = ((LONG_SLEEP_TIME_MS * lp_osc_freq) / 1000) >> 12;
        dwt_configuresleepcnt(sleep_cnt);
        spi_set_rate_high();

        /* Configure sleep mode to allow low-power listening to operate properly. */
        dwt_configuresleep(DWT_PRESRV_SLEEP | DWT_CONFIG | DWT_RX_EN, DWT_WAKE_SLPCNT | DWT_SLP_EN);

        /* Set snooze time. This will define the duration of the "short sleep" phase. */
        dwt_setsnoozetime(LPL_SHORT_SLEEP_SNOOZE_TIME);

        /* Set preamble detect timeout. This will define the duration of the reception phases. */
        dwt_setpreambledetecttimeout(LPL_RX_SNIFF_TIME);

        /* Register RX call-back. */
        dwt_setcallbacks(NULL, &rx_ok_cb, NULL, NULL);

        /* Enable wanted interrupts (RX good frames only). */
        dwt_setinterrupt(DWT_INT_RFCG, 1);

        /* Enable low-power listening mode. */
        dwt_setlowpowerlistening(1);

        /* Go to sleep to trigger low-power listening mode. */
        dwt_entersleep();
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
               
               
     uint16 wus_end_frame_nb;
     uint32 wus_end_time_ms;
               
     while (!rx_frame)
    { };
     dwt_configuresleep(DWT_PRESRV_SLEEP | DWT_CONFIG, DWT_WAKE_CS | DWT_SLP_EN);
}
作者: Nero.qi    时间: 2022-3-17 11:27
有人对LPL模式比较了解么?是我哪里参数设置的错误了么?
作者: Nero.qi    时间: 2022-3-18 10:22
测试的程序代码

链接:https://pan.baidu.com/s/1EoVsvn9jIQBiYpLGhvcToA
提取码:1234
作者: 蓝点无限    时间: 2022-3-19 21:42
Nero.qi 发表于 2022-3-18 10:22
测试的程序代码

链接:https://pan.baidu.com/s/1EoVsvn9jIQBiYpLGhvcToA

官方程序实在难懂不想看,你联系客服,提供订单号,要一份 我们自研带中断的程序吧
目前所有版型,均有支持中断的代码。
在我们的板子上调用官方api实现你的功能




欢迎光临 51uwb.cn (http://51uwb.cn/) Powered by Discuz! X3.3