實現參考相關文章:
https://blog.csdn.net/wuwovicky/article/details/88675021
https://www.docin.com/p-2116477780.html
基於最新SDK有幾個相關文件需要修改如下:
1、timeslot.c文件修改:
#include <stdint.h>
#include <stdbool.h>
#include "nrf.h"
#include "app_error.h"
#include "nrf_gpio.h"
#include "boards.h"
#include "nrf_sdh.h" //新的SDK採用 nrf_sdh.h
#include "my_esb.h"
#include "nrf_esb.h"
/**Constants for timeslot API
*/
static nrf_radio_request_t m_timeslot_request;
static uint32_t m_slot_length;
static nrf_radio_signal_callback_return_param_t signal_callback_return_param;
/**@brief Request next timeslot event in earliest configuration
*/
uint32_t request_next_event_earliest(void)
{
m_slot_length = 10000;
m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
m_timeslot_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
m_timeslot_request.params.earliest.priority = NRF_RADIO_PRIORITY_NORMAL;
m_timeslot_request.params.earliest.length_us = m_slot_length;
m_timeslot_request.params.earliest.timeout_us = 1000000;
return sd_radio_request(&m_timeslot_request);
}
/**@brief Configure next timeslot event in earliest configuration
*/
void configure_next_event_earliest(void)
{
m_slot_length = 10000;
m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
m_timeslot_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
m_timeslot_request.params.earliest.priority = NRF_RADIO_PRIORITY_NORMAL;
m_timeslot_request.params.earliest.length_us = m_slot_length;
m_timeslot_request.params.earliest.timeout_us = 1000000;
}
/**@brief Configure next timeslot event in normal configuration
*/
void configure_next_event_normal(void)
{
m_slot_length = 15000;
m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_NORMAL;
m_timeslot_request.params.normal.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
m_timeslot_request.params.normal.priority = NRF_RADIO_PRIORITY_HIGH;
m_timeslot_request.params.normal.distance_us = 100000;
m_timeslot_request.params.normal.length_us = m_slot_length;
}
/**@brief Timeslot signal handler
*/
void nrf_evt_signal_handler(uint32_t evt_id)
{
uint32_t err_code;
switch (evt_id)
{
case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN:
//No implementation needed
break;
case NRF_EVT_RADIO_SESSION_IDLE:
//sd_radio_session_close();
//No implementation needed
break;
case NRF_EVT_RADIO_SESSION_CLOSED:
//No implementation needed, session ended
break;
case NRF_EVT_RADIO_BLOCKED:
//Fall through
case NRF_EVT_RADIO_CANCELED:
err_code = request_next_event_earliest();
APP_ERROR_CHECK(err_code);
break;
default:
break;
}
}
/**@brief Timeslot event handler
*/
nrf_radio_signal_callback_return_param_t * radio_callback(uint8_t signal_type)
{
switch(signal_type)
{
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
printf("NRF_RADIO_CALLBACK_SIGNAL_TYPE_START\r\n");
//Start of the timeslot - set up timer interrupt
signal_callback_return_param.params.request.p_next = NULL;
signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
NRF_TIMER0->CC[0] = m_slot_length - 500;
//射頻這部分一定要打開,不然rf發送不成功
NRF_RADIO->POWER = (RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos);
NVIC_EnableIRQ(TIMER0_IRQn);
nrf_gpio_pin_toggle(20); //Toggle LED4
esb_init();
esb_test_tx();
break;
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO:
RADIO_IRQHandler();
printf("NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO\r\n");
signal_callback_return_param.params.request.p_next = NULL;
signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
break;
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0:
printf("NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0\r\n");
//Timer interrupt - do graceful shutdown - schedule next timeslot
configure_next_event_normal();
signal_callback_return_param.params.request.p_next = &m_timeslot_request;
signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
//發送完清除
NRF_RADIO->POWER = (RADIO_POWER_POWER_Disabled << RADIO_POWER_POWER_Pos);
break;
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED:
printf("NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED\r\n");
//No implementation needed
break;
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED:
printf("NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED\r\n");
//Try scheduling a new timeslot
configure_next_event_earliest();
signal_callback_return_param.params.request.p_next = &m_timeslot_request;
signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
break;
default:
//No implementation needed
break;
}
return (&signal_callback_return_param);
}
/**@brief Function for initializing the timeslot API.
*/
uint32_t timeslot_sd_init(void)
{
uint32_t err_code;
err_code = sd_radio_session_open(radio_callback);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = request_next_event_earliest();
if (err_code != NRF_SUCCESS)
{
(void)sd_radio_session_close();
return err_code;
}
nrf_gpio_cfg_output(20);
return NRF_SUCCESS;
}
2、main函數需要修改:
第一步:添加timeslot函數
int main(void)
{
.....
timeslot_sd_init();
.....
}
第二步:協議棧添加事件函數
static void time_slot_soc_evt_handler(uint32_t evt_id, void * p_context)
{
nrf_evt_signal_handler(evt_id);
}
static void ble_stack_init(void)
{
......
NRF_SDH_SOC_OBSERVER(m_time_slot_soc_observer, 0, time_slot_soc_evt_handler, NULL);
}
實驗步驟:
準備兩塊開發板:
1、一塊開發板,裸機燒錄官方歷程esb
2、第二塊開發板燒錄帶藍牙協議棧的,移植好timeslot的程序(我是基於ble串口歷程),如下:
3、實驗現象:
既可以正常廣播藍牙數據,也可以實現接收開發板的流水燈效果。