点击上方[物联网思考],点击关注,第一时间查看物联网精彩分享!
前面的十来篇文章,都是关于ble的理论,本文开始实战,基于CH579学习蓝牙。
1、广播包
格式参考ble4.2不可连接的非定向广播包详解(ADV_NONCONN_IND)一文。
2、交互过程
可以看出,ADV_NONCONN_IND过程只有广播,不会有其他包。
3、代码实现
3.1、主框架
代码语言:javascript复制int main( void )
{
#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(bTXD1);
GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
UART1_DefInit( ); //串口初始化
#endif
PRINT("%sn",VER_LIB);
CH57X_BLEInit( ); //协议栈配置
HAL_Init( ); //硬件配置
GAPRole_BroadcasterInit( ); //GAP层广播角色初始化
Broadcaster_Init( ); //广播初始化
while(1){
TMOS_SystemProcess( );//循环调度TMOS
}
}
3.2、BLE协议栈初始化
bleConfig_t 结构体描述了,需要的参数。
代码语言:javascript复制void CH57X_BLEInit( void )
{
uint8 i;
bleConfig_t cfg; //ble协议栈变量
if( tmos_memcmp( VER_LIB,VER_FILE,strlen(VER_FILE)) == FALSE ){
PRINT("head file error...n");
while(1);
}
R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
R16_CLK_SYS_CFG = RB_CLK_OSC32M_XT|(2<<6)|0x08; // 32M -> Fsys
//时钟配置,使用外部32M
R8_SAFE_ACCESS_SIG = 0;
SysTick_Config( SysTick_LOAD_RELOAD_Msk );
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk ; /* disable SysTick IRQ */
tmos_memset(&cfg,0,sizeof(bleConfig_t));
cfg.MEMAddr = (u32)MEM_BUF;//ble协议栈所需要的缓存,默认8K字节
cfg.MEMLen = (u32)BLE_MEMHEAP_SIZE;
cfg.BufMaxLen = (u32)BLE_BUFF_MAX_LEN;//ble数据包大小,默认为27字节
cfg.BufNumber = (u32)BLE_BUFF_NUM;
cfg.TxNumEvent = (u32)BLE_TX_NUM_EVENT;
cfg.TxPower = (u32)BLE_TX_POWER;
#if (defined (BLE_SNV)) && (BLE_SNV == TRUE)
cfg.SNVAddr = (u32)BLE_SNV_ADDR;
#endif
#if( CLK_OSC32K )
cfg.SelRTCClock = (u32)CLK_OSC32K;
#endif
cfg.ConnectNumber = (PERIPHERAL_MAX_CONNECTION&3)|(CENTRAL_MAX_CONNECTION<<2);
cfg.srandCB = SYS_GetSysTickCnt;
#if (defined TEM_SAMPLE) && (TEM_SAMPLE == TRUE)
cfg.tsCB = HAL_GetInterTempValue; // 温度校准回调函数
#if( CLK_OSC32K )
cfg.rcCB = Lib_Calibration_LSI; // 内部LSI校准回调函数
#endif
#endif
#if (defined (HAL_SLEEP)) && (HAL_SLEEP == TRUE)
cfg.WakeUpTime = WAKE_UP_RTC_MAX_TIME;
cfg.sleepCB = CH57X_LowPower; // 低功耗处理回调函数
#endif
#if (defined (BLE_MAC)) && (BLE_MAC == TRUE)
for(i=0;i<6;i ) cfg.MacAddr[i] = MacAddr[5-i];
//MAC地址配置
#endif
if( !cfg.MEMAddr || cfg.MEMLen < 4*1024 )while(1);
#if (defined HAL_SLEEP) && (HAL_SLEEP == TRUE)
if( (u32)MEM_BUF < (u32)0x20003800 ){
PRINT("RAM config error...n");
while(1);
}
#endif
i = BLE_LibInit( &cfg );
if(i){
PRINT("LIB init error code: %x ...n",i);
while(1);
}
}
3.3、硬件初始化
代码语言:javascript复制 void HAL_Init( )
{
halTaskID = TMOS_ProcessEventRegister( HAL_ProcessEvent );
//注册一个任务,halTaskID 为任务ID,一个任务下最多可以有16个事件,其中系统保留了一个事件,所以用户只能使用15个事件
HAL_TimeInit( );
#if (defined HAL_SLEEP) && (HAL_SLEEP == TRUE)
HAL_SleepInit( );
#endif
#if (defined HAL_LED) && (HAL_LED == TRUE)
HAL_LedInit( );
#endif
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
HAL_KeyInit( );
#endif
__enable_irq();
#if (defined BLE_CALIBRATION_ENABLE) && (BLE_CALIBRATION_ENABLE == TRUE)
tmos_start_task( halTaskID , HAL_REG_INIT_EVENT ,MS1_TO_SYSTEM_TIME(BLE_CALIBRATION_PERIOD) );
// 启动校准事件,最后一个参数为时间,从启动开始,到MS1_TO_SYSTEM_TIME(BLE_CALIBRATION_PERIOD)后执行校准。
#endif
}
3.4、GAP广播角色初始化
GAP规定了四种角色,广播者、观察者、外围设备(也叫从机)、中心设备(也叫主机)。
代码语言:javascript复制GAPRole_BroadcasterInit( );
这个函数是官方的API,直接调用即可。
3.5、广播初始化
代码语言:javascript复制void Broadcaster_Init( )
{
Broadcaster_TaskID = TMOS_ProcessEventRegister(Broadcaster_ProcessEvent);
//注册回调函数,分配任务ID
// Setup the GAP Broadcaster Role Profile
{
// Device starts advertising upon initialization
uint8 initial_advertising_enable = TRUE;
uint8 initial_adv_event_type = GAP_ADTYPE_ADV_NONCONN_IND;
// Set the GAP Role Parameters
GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable );//使能广播
GAPRole_SetParameter( GAPROLE_ADV_EVENT_TYPE, sizeof( uint8 ), &initial_adv_event_type );//设置广播类型
GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData );//设置广播数据
}
// Set advertising interval
{
uint16 advInt = DEFAULT_ADVERTISING_INTERVAL;
GAP_SetParamValue( TGAP_DISC_ADV_INT_MIN, advInt );
GAP_SetParamValue( TGAP_DISC_ADV_INT_MAX, advInt );
}//广播间隔设置
tmos_set_event( Broadcaster_TaskID, SBP_START_DEVICE_EVT );
//立即启动一个事件,这个事件用于启动广播
}
3.6、广播回调函数
代码语言:javascript复制uint16 Broadcaster_ProcessEvent( uint8 task_id, uint16 events )
{
//VOID task_id; // TMOS required parameter that isn't used in this function
if ( events & SYS_EVENT_MSG ){
uint8 *pMsg;
if ( (pMsg = tmos_msg_receive( Broadcaster_TaskID )) != NULL ){
Broadcaster_ProcessTMOSMsg( (tmos_event_hdr_t *)pMsg );
// Release the TMOS message
tmos_msg_deallocate( pMsg );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
//系统事件,用于接收消息
}
if ( events & SBP_START_DEVICE_EVT ){
// Start the Device
GAPRole_BroadcasterStartDevice( &Broadcaster_BroadcasterCBs );//3.5中启动的事件,开始广播
return ( events ^ SBP_START_DEVICE_EVT );
}
// Discard unknown events
return 0;
}
3.7、广播数据
代码语言:javascript复制static uint8 advertData[] =
{
0x02, // length of this data
GAP_ADTYPE_FLAGS,
GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED|GAP_ADTYPE_FLAGS_GENERAL,
// Broadcast of the data
0x04, // length of this data including the data type byte
GAP_ADTYPE_MANUFACTURER_SPECIFIC, // manufacturer specific advertisement data type
'b',
'l',
'e',
0x06,
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
'm',
'y',
'b',
'l',
'e',
};
可以看出是一个uint8 类型的数组,数据按照Length、Type、Data的形式组成。关于广播类型可参考ble4.2广播数据类型一文。
4、APP查看广播数据
本文使用BLE调试助手APP。
——————END——————
相关文章推荐:
ble 40个射频通道
ble4.2 ATT层包详解(Attribute Protocol)
ble4.2 L2CAP层信令通道包详解(SIGNALING PACKET FORMATS)
非定向可连接广播、扫描请求、扫描回复、连接请求之间的关系
ble4.2连接请求包详解(CONNECT_REQ)
ble4.2扫描回复包详解(SCAN_RSP)
ble4.2扫描请求包详解(SCAN_REQ)
ble4.2可连接的非定向广播包详解(ADV_IND)
ble4.2不可连接的非定向广播包详解(ADV_NONCONN_IND)
ble4.2空口包详解(air interface packets)
一文学会使用nRF Sniffer、Wireshark抓蓝牙ble包