Solution: BLE & PRF SAMPLE¶
1 功能概述¶
此例程演示BLE从机和 prf 2.4g (XN297 模式) 同时工作的双模例程。在蓝牙广播或连接的同时也能收发2.4g包。
2 环境要求¶
board: pan108xxb5_evb
uart (option): 显示例程log
手机app :nrf connect
PC工具: Panchip Serial Assistant V0.0.011(支持串口,波特率921600)
3 编译和烧录¶
例程位置:
zephyr\samples_panchip\solutions\ble_prf_sample_tx
zephyr\samples_panchip\solutions\ble_prf_sample_rx
使用 ZAL 工具可以对其进行编译、烧录、打开 VS Code 调试等操作。关于 ZAL 工具的详细介绍请参考:Zephyr APP Launcher 工具介绍。
4 演示说明¶
本项目演示是蓝牙从机发广播和连接与prf xn297模式下发射同时工作的功能,典型的操作方法是,手机app连接设备蓝牙同时设备保持150ms 的prf发射的功能。
prf 的配置和使用方法,请参考例程
zephyr\samples_panchip\proprietary_radio\prf_sample_tx
zephyr\samples_panchip\proprietary_radio\prf_sample_rx
蓝牙相关的功能,请参考例程
zephyr\samples_panchip\bluetooth\peripheral_hr
5 开发使用说明¶
5.1ble和prf初始化¶
ble和prf双模工作模式下,初始化有如下要求:
双模prf必须打开如下两个个宏
CONFIG_USE_BLE_PRF_DUAL_MODE=y
CONFIG_USE_PRF_ISR_RESUME_BT_CB=y
单独使用prf打开的宏,双模不能打开
# CONFIG_ENABLE_COMM_PRF=y
ble和prf初始化顺序
如下代码所示:
void ble_prf_init(void)
{
int err;
err = bt_enable(NULL); //第一步:ble ll和host初始化
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
return;
}
panchip_prf_init(&tx_config); //第二步:prf tx配置初始化,rx类似
PRI_RF_ChipModeSel(PRI_RF, PRF_CHIP_MODE_SEL_BLE);
bt_ready(); //第三步:ble开始广播,ble扫描类似
bt_conn_auth_cb_register(&auth_cb_display);
k_thread_create(&ble_hr_thread, ble_hr_thread_stack,
K_KERNEL_STACK_SIZEOF(ble_hr_thread_stack),
(k_thread_entry_t)ble_hr_main_thread, NULL, NULL, NULL,
3,
0, K_NO_WAIT);
k_thread_name_set(&ble_hr_thread, "ble hr");
}
初始化顺序需要遵循以上三个步骤,否则会出现ble或prf不能工作的情况。
5.2ble和prf工作¶
以”ble_prf_sample_tx”例程为例:
ble初始化完后直接开始广播或扫描,prf需要在ble广播间隔的空隙中执行,初始化代码如下:
g_ab_event_node.interval = MS_2_LP_CYCLES_32XX(150); g_ab_event_node.slot_duration = 6; g_ab_event_node.before_point = 0; g_ab_event_node.anchor_point = 0; g_ab_event_node.event = prf_event_handler; g_ab_event_node.priority = 2; g_ab_handle = ((abstract_ll_event_register)SVC_ABSTRACT_LLEVENT_REGISTER)(&g_ab_event_node);
“g_ab_event_node”结构体定义如下:
typedef struct __ab_event_node { uint32_t interval; //event 执行周期,单位32us uint32_t slot_duration; //event最大执行窗口时间,单位1.25ms uint32_t before_point; //event提前执行时间,单位32us,prf rx使用 uint32_t anchor_point; //设置event第一次同步上的时间,通常是当前时间+interval,prf rx使用 ab_event_come_t event; //event回调函数 uint32_t reserve; uint8_t priority; /* 0 - 5,event 优先级,最大0,最小5 */ uint8_t dy_scan; //unuse }ab_event_node_t; evnt_hndl_t abstract_ll_event_register(ab_event_node_t *event_node); //注册一个event
回调函数接口如下:
__ramfunc void prf_event_handler(uint32_t window, ble_time_t *time, evnt_hndl_t event_hand) { /****************fix code**********************/ uint32_t time_base, time_temp; llhwc_slptmr_get(&time_base); while (time_base < time->time_stamp_base) { llhwc_slptmr_get(&time_base); } llhwc_slptmr_get(&time_temp); env.time_stamp.time_stamp_base = time_temp; env.evnt_type = AB_EVENT; /****************fix code**********************/ panchip_prf_set_data(&tx_payload); panchip_prf_work_judge(&tx_config); }
回调函数接口前面一段是固定代码,获取event开始执行的时间戳。
panchip_prf_set_data(&tx_payload); panchip_prf_work_judge(&tx_config);
prf设置tx payload,设置频点、启动tx或rx。
prf tx结束后会产生tx中断,中断接口如下:
void event_tx_fun(void) { printk("tx done\n"); /* restart tx event*/ ((abstract_hw_completed)SVC_ABSTRACT_HW_COMPLETED)(&env); /* stop tx event*/ /* ((abstract_ll_event_unregister)SVC_ABSTRACT_LLEVENT_UNREGISTER)(g_ab_handle); */ }
6 RAM/Flash资源使用情况¶
TX:
Memory region Used Size Region Size %age Used
FLASH: 92064 B 384 KB 23.41%
SRAM: 33258 B 50 KB 64.96%
RX:
Memory region Used Size Region Size %age Used
FLASH: 91804 B 384 KB 23.35%
SRAM: 32970 B 50 KB 64.39%