0%

蓝牙BLE调试记录

蓝牙SOC芯片

国产芯片PAN1020,M0带蓝牙收发器的SOC只要2.5r/pcs,可以用来做一些低成本的小产品,带上蓝牙控制的功能。参考资料:PAN1020_Public_SDK_V2.0.8

  • RF
    - 2.4GHz 射频收发机(兼容 BLE4.2)
    - 接收灵敏度:-90 dBm@1Mbps
    - 最大接收信号:0 dBm
    - 可编程发射输出功率:最大为 13 dBm,一般为 8 dBm
    - 单线天线:无需 RF 匹配或 RX/TX 切换
  • 内核
    - MCU 内核运行速度高达 26 MHz
    - 一个 24 位系统定时器
    - 支持低功耗空闲模式
    - 单周期 32 位硬件乘法器
    - 支持串行线调试(SWD)接口和两个观察点/四个断点
  • 内存
    - 256 KB 闪存用于程序存储器
    - 16 KB SRAM

低功耗说明

NO Mode Interval Average Current Description
1 Advertising 100ms 545uA 32K RC
2 Advertising 1000ms 66uA 32K RC
3 Connected 100ms 301uA 32K RC
4 Connected 1000ms 55uA 32K RC
5 Advertising 100ms 400uA 32K XO
6 Connected 100ms 230uA 32K XO

产品需求

蓝牙温度计,能记录历史数据,手机app显示温度波形,40mah纽扣电池供电,使用5天。

软件开发记录

代码已上传 GIthub:BLE_APP 源码

启用中断回调

我配置了 ADC 并开启中断,测试程序会卡死,最后发现与 ADC 中断是否开启相关。在 BLE 协议栈接口那发现了注册中断的接口。

使用如下代码将 ADC_IRQ 的中断回调 mcu_adc_isr 注册到协议栈后,问题解决。

1
2
// 注册中断处理函数到协议栈,否则中断会卡死。
((interrupt_register_handler)SVC_interrupt_register)(ADC_IRQ, mcu_adc_isr);

开启低功耗模式

如需开启低功耗模式,只需在 panip_config.h#define SLEEP_EN (1)

PAN1020 SDK 定义的全局变量在使用前都必须要在函数中初始化,如果定义的时候就初始化,当前初始化的值是不生效的。

因为开启低功耗模式需配置编译器将 RAM 设置为 NoInit,如图所示:

img

设为 NoInit 后,全局变量定义后的值为随机值,没有被初始化,需要自己手动初始化。此处是为了在 PAN1020 休眠唤醒后 RAM 不被重新初始化,唤醒后的 RAM 值依旧保持为休眠前的值。

配置软件定时器

按照 SDK 用户手册配置软件定时器后遇到奇怪的问题,但测试发现解决方法,如下注释说明:

1
2
3
4
5
6
7
8
9
10
11
void app_proj_template_init(void)
{
memset(&app_proj_template_env, 0, sizeof(app_proj_template_env));

temper_resetInit();
/* 注意:配置定时器放在此函数里没问题,放在appm_init()外部有问题,会导致无法进定时回调!
函数调用关系:ble_normal_reset_init() -> user_code_start() -> appm_init() -> app_init_ind_func()
设置定时器放在appm_init()内部没问题,但是放在appm_init()外部就不行,
甚至把设置定时器放在appm_init()内部的最后一行可以,放在appm_init()执行完出来的下一行不行!*/
((ke_timer_set_handler)SVC_ke_timer_set)(APP_SAMPLE_TEMPER_TIMER, TASK_APP, 60*100);
}

配置ATT数据库

配置att数据库后发现只有数据库的前13条配置生效,后面的att没有生效,在配置att的接口调试发现有条件为满足导致的后面一些att数据库配置没配置进协议栈,一层层向上查后是以下代码,db_cfg->features = 0x1fff; 导致的,如下配置为 db_cfg->features = 0xffffffff; 后问题解决。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void app_proj_template_add_server(void)
{

struct proj_template_server_db_cfg* db_cfg;

// Allocate the BASS_CREATE_DB_REQ
struct gapm_profile_task_add_cmd *req = KE_MSG_ALLOC_DYN(GAPM_PROFILE_TASK_ADD_CMD,
TASK_GAPM, TASK_APP,
gapm_profile_task_add_cmd,sizeof(struct proj_template_server_db_cfg));
// Fill message
req->operation = GAPM_PROFILE_TASK_ADD;
req->sec_lvl = (PERM(SVC_AUTH, DISABLE)| PERM(SVC_UUID_LEN, UUID_16)| PERM(SVC_EKS, DISABLE)|PERM(SVC_DIS, DISABLE));

req->prf_task_id = TASK_ID_PROJ_TEMPLATE_SERVER;
req->app_task = TASK_APP;
req->start_hdl = 0;

// Set parameters
db_cfg = (struct proj_template_server_db_cfg* ) req->param;
db_cfg->features = 0xffffffff; // 注意:配置了gatt数据库,要配置这个掩码使能,32位都是1可以使能32个数据库配置

// Send the message
((ke_msg_send_handler)SVC_ke_msg_send)(req);
}

电池输出电流不足不问

电池40mah,放点倍率0.1C,输出电流最大就4ma,射频瞬间最大电流有30多ma,adc采集会开启ldo和运放,最大电流有90ma。

adc采集的时候电流过大会将电压拉低导致单片机复位,正在通过加电容解决。

射频需求只需要5m范围内,所以射频的功率也可以配置低一些。

后面测试解决完这个问题更新……