CH587蓝牙HID_Keyboard例程多通道配对修改示例
由于CH587的dataflash最小擦除单位上升到了4K字节,对于一个SNV块只有256字节的BLE来说,如果按照当前例程默认做法,SNV的擦写也被动变为了4K字节擦除;
如果加入多通道配对逻辑,比方说常见的蓝牙键盘含有4个BLE通道,那将是4K*4=16K,原本只需要256*4=1K的占用,白白浪费了15K空间;
对此,可衍生一个思路:划分1Kdataflash区域用于存储4个蓝牙通道SNV信息,每次切通道涉及配对存储动作时,先把1K数据全部读出来,根据当前的BLE_SNV_Index修改其中一个SNV块数据后,再写回去;
例程修改:
①MCU.c文件Lib_Write_Flash:
uint8_t BLE_SNV_Index = 1;//定义一个全局变量,用于通道序号管理,默认蓝牙通道1
#define SNV_NUM 4 //定义SNV块数量->蓝牙通道数量
/*******************************************************************************
* @fn Lib_Write_Flash
*
* @brief Callback function used for BLE lib.
*
* @param addr - Write start address
* @param num - Number of units to write (unit: 4 bytes)
* @param pBuf - Buffer with data to be written
*
* @return None.
*/
uint32_t Lib_Write_Flash(uint32_t addr, uint32_t num, uint32_t *pBuf)
{
#if 1
//兼容CH585的蓝牙切通道做法,用于多通道信息连续存储
uint32_t Temp_Buffer[256*SNV_NUM/4] = {0};//定义临时备份区,1K字节
EEPROM_READ(BLE_SNV_ADDR, Temp_Buffer,256*SNV_NUM);//读出4个块所有的1K字节,存储到临时备份区
EEPROM_ERASE(BLE_SNV_ADDR, 0x1000);//擦除4K区域,CH587中4K为最小擦除单位
tmos_memcpy(&Temp_Buffer[(BLE_SNV_Index - 1) * (256 / 4)],pBuf,num * 4);//拷贝回调写入的数据到临时备份区中的对应SNV块
EEPROM_WRITE(BLE_SNV_ADDR, Temp_Buffer, 0x400);//将拷贝完后的数据写入到dataflash,写入数量4*256=1K字节
#else
//原先例程做法,每次配对会固定擦除4K单位
EEPROM_ERASE(addr, num * 4);
EEPROM_WRITE(addr, pBuf, num * 4);
#endif
return 0;
}
②测试演示:定义了两个tmos任务:
1、可在任意时间点启动START_BLE_DISCON_EVT任务,发起断连用于切换新通道连接;
2、断连后根据当前通道号重新开启广播

广播参数重新配置并开启广播:
uint8_t BLE_IRK[KEYLEN]={0};
extern uint8_t BLE_SNV_Index;
extern bStatus_t tmos_snv_write( tmosSnvId_t id, tmosSnvLen_t len, void *pBuf );
extern void tmos_snv_notify( uint8_t enable );
extern bStatus_t tmos_snv_init( void );
void hidEmu_adv_enable(uint8_t enable)
{
uint8_t ownAddr[6];
uint8_t initial_advertising_enable = enable;
uint8_t adv_event_type;
if(initial_advertising_enable)
{
extern bleConfig_t ble;
ble.SNVAddr = (BLE_SNV_Index-1)* 0x100 + BLE_SNV_ADDR;//根据当前BLE通道号,切换至对应SNV块
/* 初始化SNV,用于获取IRK信息 */
tmos_snv_init();
if(tmos_snv_read(BLE_NVID_IRK,KEYLEN,BLE_IRK))//读取当前SNV块中是否存有IRK信息,没有则手动赋随机值,赋值一次之后不用再次赋值
{
uint32_t rand;
uint8_t j;
for(j=0; j<4; j++)
{
rand = tmos_rand();
BLE_IRK[0+4*j] = BREAK_UINT32(rand, 0);
BLE_IRK[1+4*j] = BREAK_UINT32(rand, 1);
BLE_IRK[2+4*j] = BREAK_UINT32(rand, 2);
BLE_IRK[3+4*j] = BREAK_UINT32(rand, 3);
}
tmos_snv_write(BLE_NVID_IRK,KEYLEN,BLE_IRK);
tmos_snv_notify(1);//存储至SNV中
}
GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddr);//获取当前BLE静态地址,唯一
ownAddr[3]=BLE_SNV_Index;//修改蓝牙地址,防止切通道index后被误连接(每个蓝牙通道地址必须唯一,否则会被主机误连)
PRINT("MAC %x %x %x %x %x %x\n",ownAddr[5],ownAddr[4],ownAddr[3],ownAddr[2],ownAddr[1],ownAddr[0]);//打印当前的广播地址
GAP_ConfigDeviceAddr(ADDRTYPE_STATIC, ownAddr);
PRINT("IRK %x %x %x %x %x %x\n",BLE_IRK[5],BLE_IRK[4],BLE_IRK[3],BLE_IRK[2],BLE_IRK[1],BLE_IRK[0]);//打印当前的部分IRK值
GAPRole_SetParameter(GAPROLE_IRK, KEYLEN, BLE_IRK);//配置IRK信息
}
{
PRINT("all adv\n");
uint8_t filter_policy = GAP_FILTER_POLICY_ALL;
adv_event_type = GAP_ADTYPE_ADV_IND;
GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof(uint8_t), &filter_policy);//配置普通广播,所有设备可发现
}
GAPRole_SetParameter( GAPROLE_ADV_EVENT_TYPE, sizeof(adv_event_type), &adv_event_type);
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);//根据ENABLE(开启) or DISABLE(不开/关闭) 广播
}
有需要自取:
通过网盘分享的文件:CH587EVT_HIDKeyboard.zip
链接: https://pan.baidu.com/s/1iRDtbRX6msCAdmJYW4NH4g?pwd=24nd 提取码: 24nd

浙公网安备 33010602011771号