CH579实现不可连接的非定向广播包

2021-10-09 14:23:08 浏览数 (1)

点击上方[物联网思考],点击关注,第一时间查看物联网精彩分享!

前面的十来篇文章,都是关于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包

0 人点赞