前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CH579实现一个最小外围设备(Peripheral)

CH579实现一个最小外围设备(Peripheral)

作者头像
ManInRoad
发布2021-11-04 10:07:34
1.2K0
发布2021-11-04 10:07:34
举报
文章被收录于专栏:物联网思考

本文基于CH579实现一个最小外围设备,在官方历程Peripheral的基础上精简。

1、main函数

代码语言: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("%s\n",VER_LIB);
  CH57X_BLEInit( );//协议栈相关初始化
  HAL_Init( );//硬件初始化
  GAPRole_PeripheralInit( );//GAP角色初始化,初始化为外围设备,协议栈API函数
  Peripheral_Init( ); //外围设备,自定义参数初始化,自定义函数
	while(1){
		TMOS_SystemProcess( );//TMOS系统运行,协议栈API函数
	}
}

其中函数 GAPRole_PeripheralInit( ),用于GAP角色初始化,初始化为外围设备,属于协议栈提供的API。

2、Peripheral_Init函数

代码语言:javascript
复制
void Peripheral_Init( )
{
  Peripheral_TaskID = TMOS_ProcessEventRegister( Peripheral_ProcessEvent );
  //注册事件回调函数,TMOS是基于时间回调的,一个任务下,最多可以有16个事件,1个用于系统,另外15个用于用户
  
  // 设置GAP角色参数
  {
    uint8 initial_advertising_enable = TRUE;
    uint16 desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
    uint16 desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
    
    // Set the GAP Role Parameters
    GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &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 ), &desired_min_interval );//最小连接间隔
    GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &desired_max_interval );//最大连接间隔
  }
  // Set the GAP Characteristics
  GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName );//GAP特征,设备名称

  // Set advertising interval
  {
    uint16 advInt = DEFAULT_ADVERTISING_INTERVAL;

    GAP_SetParamValue( TGAP_DISC_ADV_INT_MIN, advInt );//最小广播间隔
    GAP_SetParamValue( TGAP_DISC_ADV_INT_MAX, advInt );//最大广播间隔
  }
  // Initialize GATT attributes
  GGS_AddService( GATT_ALL_SERVICES );            // GAP
  GATTServApp_AddService( GATT_ALL_SERVICES );    // GATT attributes
  //GAP和GATT这两个服务是协议栈自带的,如上调用即可。
  // Init Connection Item
  peripheralInitConnItem( &peripheralConnList );//连接参数初始化
  // Setup a delayed profile startup
  tmos_set_event( Peripheral_TaskID, SBP_START_DEVICE_EVT );
  //启动Peripheral_TaskID任务下的SBP_START_DEVICE_EVT事件,其中tmos_set_event函数用于立刻执行某个事件
}

3、Peripheral_ProcessEvent任务回调函数

注册了任务回调函数之后,通过函数tmos_set_event或者tmos_start_task启动某个事件,会回调到这个函数中,任务中有4个事件,其中SBP_READ_RSSI_EVT是周期性执行的事件,其他事件在特定情况下才会执行。

代码语言:javascript
复制
uint16 Peripheral_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( Peripheral_TaskID )) != NULL ){
      Peripheral_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 ){//GAP外围设备启动事假
	// Start the Device
    GAPRole_PeripheralStartDevice( Peripheral_TaskID, &Peripheral_BondMgrCBs, &Peripheral_PeripheralCBs );
    return ( events ^ SBP_START_DEVICE_EVT );
  }
  if ( events & SBP_PARAM_UPDATE_EVT )//连接参数更新事件
  {
    // Send connect param update request
    GAPRole_PeripheralConnParamUpdateReq( peripheralConnList.connHandle,
                                          DEFAULT_DESIRED_MIN_CONN_INTERVAL,
                                          DEFAULT_DESIRED_MAX_CONN_INTERVAL,
                                          DEFAULT_DESIRED_SLAVE_LATENCY,
                                          DEFAULT_DESIRED_CONN_TIMEOUT,
                                          Peripheral_TaskID);
    
    return (events ^ SBP_PARAM_UPDATE_EVT);
  }
  
  if ( events & SBP_READ_RSSI_EVT )//读取RSSI事假
  {
    GAPRole_ReadRssiCmd(peripheralConnList.connHandle);
    tmos_start_task( Peripheral_TaskID, SBP_READ_RSSI_EVT, SBP_READ_RSSI_EVT_PERIOD );      
    return (events ^ SBP_READ_RSSI_EVT);
  }   

  // Discard unknown events
  return 0;
}

GAPRole_PeripheralStartDevice( uint8 taskid, gapBondCBs_t *pCB,gapRolesCBs_t *pAppCallbacks );用于启动外围设备; taskid:任务ID; pCB:绑定回调函数; pAppCallbacks :Gap角色回调函数; 其中pAppCallbacks本身是一个结构体,包含三个函数指针,如下

代码语言:javascript
复制
typedef struct
{
  gapRolesStateNotify_t    pfnStateChange;  //!< Whenever the device changes state
  //设备状态改变函数指针
  gapRolesRssiRead_t       pfnRssiRead;     //!< When a valid RSSI is read from controller
  //RSSI读取函数指针
  gapRolesParamUpdateCB_t  pfnParamUpdate;  //!< When the connection parameteres are updated
 //连接参数更新函数指针
} gapRolesCBs_t;

4、peripheralStateNotificationCB状态改变回调函数

如果GAP层设备状态发生了变化,协议栈会回调到这个函数中,用于在这个函数里面处理各种状态。

代码语言:javascript
复制
static void peripheralStateNotificationCB( gapRole_States_t newState, gapRoleEvent_t * pEvent )
{
  switch ( newState )
  {
    case GAPROLE_STARTED://启动
      PRINT( "Initialized..\n" );
      break;
    case GAPROLE_ADVERTISING://广播
      if( pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT )
      {
        Peripheral_LinkTerminated( pEvent );
        PRINT( "Disconnected.. Reason:%x\n",pEvent->linkTerminate.reason );
      }
      PRINT( "Advertising..\n" );
      break;
    case GAPROLE_CONNECTED://连接
      if( pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT )
      {
        Peripheral_LinkEstablished( pEvent );//在这个函数中启动读取rssi事件、更新连接参数事件
      }
      PRINT( "Connected..\n" );
      break;
    case GAPROLE_CONNECTED_ADV://连接+广播
      PRINT( "Connected Advertising..\n" );
      break;      
    case GAPROLE_WAITING://等待
      if( pEvent->gap.opcode == GAP_END_DISCOVERABLE_DONE_EVENT )//等待广播
      {
        PRINT( "Waiting for advertising..\n" );
      }
      else if( pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT )//连接断开
      {
        Peripheral_LinkTerminated( pEvent );//在这个函数在,重新启动广播,关闭读取rssi
        PRINT( "Disconnected.. Reason:%x\n",pEvent->linkTerminate.reason );
      }
      else if( pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT )
	  {
		if( pEvent->gap.hdr.status != SUCCESS )
		{
			PRINT( "Waiting for advertising..\n" );
		}
		else
		{
			PRINT( "Error..\n" );
		}
	  }
	  else
	  {
		 PRINT( "Error..%x\n",pEvent->gap.opcode );
	  }
      break;
    case GAPROLE_ERROR:
		PRINT( "Error..\n" );
      break;

    default:
      break;
  }
}

5、peripheralParamUpdateCB连接参数更新回调

代码语言:javascript
复制
static void peripheralParamUpdateCB( uint16 connHandle, uint16 connInterval, 
                                      uint16 connSlaveLatency, uint16 connTimeout )
{
  if( connHandle == peripheralConnList.connHandle )
  {
    peripheralConnList.connInterval = connInterval;
    peripheralConnList.connSlaveLatency = connSlaveLatency;
    peripheralConnList.connTimeout = connTimeout;

    PRINT("Update %x - Int %x \n", connHandle, connInterval);
  }
  else
  {
    PRINT("ERR..\n");
  }
}

6、peripheralRssiCBRSSI读取回调

代码语言:javascript
复制
static void peripheralRssiCB( uint16 connHandle, int8 rssi )
{
  PRINT( "RSSI -%d dB Conn  %x \n", -rssi, connHandle);
}

7、手机app连接设备

可以看到,通过以上代码就构成了最小外围设备。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 物联网思考 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本文基于CH579实现一个最小外围设备,在官方历程Peripheral的基础上精简。
  • 1、main函数
  • 2、Peripheral_Init函数
  • 3、Peripheral_ProcessEvent任务回调函数
  • 4、peripheralStateNotificationCB状态改变回调函数
  • 5、peripheralParamUpdateCB连接参数更新回调
  • 6、peripheralRssiCBRSSI读取回调
  • 7、手机app连接设备
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档