承接上期的呼吸灯效贴,今天来分享一下,将开发板做为BLE从机,手机做为BLE主机,在手机端的蓝牙调试助手发送指定字符去控制板上的LED0、LED1。
基于SDK中提供的从机“Peripheral”例程,手机端应用市场安装好“BLE调试助手”app。编译“Peripheral”例程后,使用“WCHISPStudio”下载编译后的“Peripheral.hex”文件。然后打开手机端的蓝牙与GPS开关,打开“BLE调试助手”app,扫描连接“Simple Peripheral”设备。连接该设备后则可看到“Generic Access”、“Generic Attribute”、“设备信息”和“Unknown Service”所有服务项。

其中的Unknown Service服务是我们所需着重关注的,该服务是程序中自定义的一个通讯服务,UUID为0xFFE0,点击该条目,界面显示出0xFFE0服务下所有的characteristic,其包括“0xFFE1”、“0xFFE2”、“0xFFE3”、“0xFFE4”和“0xFFE5”,并显示出该服务的Properties。具体如下图所示:

根据图示可知,我们可通过“0xFFE1”,““0xFFE3”两个特征服务给开发进行写操作,也就是发送字符给开发板解析。然后回到例程中的“Peripheral_Init()”函数。
void Peripheral_Init()
{
Peripheral_TaskID = TMOS_ProcessEventRegister(Peripheral_ProcessEvent);
{
uint8_t initial_advertising_enable = TRUE;
uint16_t desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
uint16_t desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t), &desired_min_interval);
GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t), &desired_max_interval);
}
{
uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, advInt);
GAP_SetParamValue(TGAP_ADV_SCAN_REQ_NOTIFY, ENABLE);
}
{
uint32_t passkey = 0;
uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
uint8_t mitm = TRUE;
uint8_t bonding = TRUE;
uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
GAPBondMgr_SetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
GAPBondMgr_SetParameter(GAPBOND_PERI_PAIRING_MODE, sizeof(uint8_t), &pairMode);
GAPBondMgr_SetParameter(GAPBOND_PERI_MITM_PROTECTION, sizeof(uint8_t), &mitm);
GAPBondMgr_SetParameter(GAPBOND_PERI_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
GAPBondMgr_SetParameter(GAPBOND_PERI_BONDING_ENABLED, sizeof(uint8_t), &bonding);
}
GGS_AddService(GATT_ALL_SERVICES);
GATTServApp_AddService(GATT_ALL_SERVICES);
DevInfo_AddService();
SimpleProfile_AddService(GATT_ALL_SERVICES);
GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
{
uint8_t charValue1[SIMPLEPROFILE_CHAR1_LEN] = {1};
uint8_t charValue2[SIMPLEPROFILE_CHAR2_LEN] = {2};
uint8_t charValue3[SIMPLEPROFILE_CHAR3_LEN] = {3};
uint8_t charValue4[SIMPLEPROFILE_CHAR4_LEN] = {4};
uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = {1, 2, 3, 4, 5};
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, SIMPLEPROFILE_CHAR1_LEN, charValue1);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, SIMPLEPROFILE_CHAR2_LEN, charValue2);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, SIMPLEPROFILE_CHAR3_LEN, charValue3);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, SIMPLEPROFILE_CHAR4_LEN, charValue4);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN, charValue5);
}
peripheralInitConnItem(&peripheralConnList);
SimpleProfile_RegisterAppCBs(&Peripheral_SimpleProfileCBs);
GAPRole_BroadcasterSetCB(&Broadcaster_BroadcasterCBs);
tmos_set_event(Peripheral_TaskID, SBP_START_DEVICE_EVT);
}
代码注释// Register callback with SimpleGATTprofile,即是初始化注册的特征值变化回调接口。
static simpleProfileCBs_t Peripheral_SimpleProfileCBs = {
simpleProfileChangeCB
};
然后再根据实验需求,在“simpleProfileChangeCB()”函数中实现控制板上LED0,LED1的逻辑处理代码。
static void simpleProfileChangeCB(uint8_t paramID, uint8_t *pValue, uint16_t len)
{
switch(paramID)
{
case SIMPLEPROFILE_CHAR1:
{
uint8_t newValue[SIMPLEPROFILE_CHAR1_LEN];
tmos_memcpy(newValue, pValue, len);
if(newValue[0])
{
if(newValue[0]== 0x30)
{
GPIOA_SetBits(GPIO_Pin_0);
}
else if(newValue[0]==0x31)
{
GPIOA_ResetBits(GPIO_Pin_0);
}
else if(newValue[0]==0x32)
{
GPIOA_SetBits(GPIO_Pin_1);
}
else if(newValue[0]==0x33)
{
GPIOA_ResetBits(GPIO_Pin_1);
}
}
PRINT("profile ChangeCB CHAR1.. \n");
break;
}
case SIMPLEPROFILE_CHAR3:
{
uint8_t newValue[SIMPLEPROFILE_CHAR3_LEN];
tmos_memcpy(newValue, pValue, len);
PRINT("profile ChangeCB CHAR3..\n");
break;
}
default:
break;
}
}
实验在“0xFFE1”服务特征值下进行,因此添加逻辑代码在“SIMPLEPROFILE_CHAR1”,如果想在“0xFFE3”服务特征值下实验,则将逻辑代码添加到“SIMPLEPROFILE_CHAR3”下。
完成上述代码编写完后,当然记得在main函数中添加LED0、LED1的GPIO口初始化代码,默认关闭LED0、LED1。这里笔者LED0使用PA0,LED1使用PA1。main()函数中内容如下:
int main(void)
{
#if(defined(DCDC_ENABLE)) && (DCDC_ENABLE == TRUE)
PWR_DCDCCfg(ENABLE);
#endif
HSECFG_Capacitance(HSECap_18p);
SetSysClock(CLK_SOURCE_HSE_PLL_62_4MHz);
#if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
#endif
#ifdef DEBUG
GPIOA_SetBits(GPIO_Pin_14);
GPIOPinRemap(ENABLE, RB_PIN_UART0);
GPIOA_ModeCfg(GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
UART0_DefInit();
#endif
PRINT("%s\n", VER_LIB);
GPIOA_ModeCfg( GPIO_Pin_0, GPIO_ModeOut_PP_5mA );
GPIOA_ModeCfg( GPIO_Pin_1, GPIO_ModeOut_PP_5mA );
GPIOA_SetBits(GPIO_Pin_0);
GPIOA_SetBits(GPIO_Pin_1);
CH58x_BLEInit();
HAL_Init();
GAPRole_PeripheralInit();
Peripheral_Init();
Main_Circulation();
}
开发板的硬件实物连线如下:

工程编译、下载后,实验演示正如代码中一样。发送数字0或者16进制30则关闭LED0,发送数字1或者16进制31则打开LED0,发送数字2或者16进制32则关闭LED1,发送数字3或者16进制33则打开LED1,效果见底部视频。