juky1983 发表于 2020-5-28 16:01:36

STM32WB55 如何一次性发送和接收超过100字节的数据包?

   大家好,我使用的开发板是“STM32WB55 Nucleo”开发板,想实现一次性发送和接收超过100个字节的数据包(数据包字节数越多越好,如果能达到250个字节就最好了)。蓝牙底层数据包默认大小大概是20字节。蓝牙协议提到的包格式中的PDU大小为2~257字节。   软件库:STM32Cube_FW_WB_V1.7.0, 使用例程:BLE_p2pServer。
   该例程主要是实现蓝牙控制LED1的亮灭。蓝牙调试助手发送0x00 0x01 --> LED1亮,0x00 0x00-->LED1灭。
但是不能接收超过2个字节的数据,蓝牙调试助手发送时显示“成功写入”,但是没有触发P2PS_STM_App_Notification()函数中的事件P2PS_STM_WRITE_EVT<blockquote>void P2PS_STM_App_Notification(P2PS_STM_App_Notification_evt_t *pNotification)然后我将P2PS_STM_Init() 中的 aci_gatt_add_char()函数中的Char_Value_Length改为150,请看注释。蓝牙助手发送64个字节,P2PS_STM_WRITE_EVT触发4次,每个包最大20字节。
void P2PS_STM_Init(void)
{

Char_UUID_tuuid16;

/**
   *      Register the event handler to the BLE controller
   */
SVCCTL_RegisterSvcHandler(PeerToPeer_Event_Handler);

    /**
   *Peer To Peer Service
   *
   * Max_Attribute_Records = 2*no_of_char + 1
   * service_max_attribute_record = 1 for Peer To Peer service +
   *                              2 for P2P Write characteristic +
   *                              2 for P2P Notify characteristic +
   *                              1 for client char configuration descriptor +
   *                              
   */
    COPY_P2P_SERVICE_UUID(uuid16.Char_UUID_128);
    aci_gatt_add_service(UUID_TYPE_128,
                      (Service_UUID_t *) &uuid16,
                      PRIMARY_SERVICE,
                      8,
                      &(aPeerToPeerContext.PeerToPeerSvcHdle));

    /**
   *Add LED Characteristic
   */
    COPY_P2P_WRITE_CHAR_UUID(uuid16.Char_UUID_128);
    aci_gatt_add_char(aPeerToPeerContext.PeerToPeerSvcHdle,
                      UUID_TYPE_128, &uuid16,
                      150,//2,//由2改为150
                      CHAR_PROP_WRITE_WITHOUT_RESP|CHAR_PROP_READ,
                      ATTR_PERMISSION_NONE,
                      GATT_NOTIFY_ATTRIBUTE_WRITE, /* gattEvtMask */
                      10, /* encryKeySize */
                      1, /* isVariable */
                      &(aPeerToPeerContext.P2PWriteClientToServerCharHdle));

    /**
   *   Add Button Characteristic
   */
    COPY_P2P_NOTIFY_UUID(uuid16.Char_UUID_128);
    aci_gatt_add_char(aPeerToPeerContext.PeerToPeerSvcHdle,
                      UUID_TYPE_128, &uuid16,
                      150,//2,//由2改为150
                      CHAR_PROP_NOTIFY,
                      ATTR_PERMISSION_NONE,
                      GATT_NOTIFY_ATTRIBUTE_WRITE, /* gattEvtMask */
                      10, /* encryKeySize */
                      1, /* isVariable: 1 */
                      &(aPeerToPeerContext.P2PNotifyServerToClientCharHdle));

#if(BLE_CFG_OTA_REBOOT_CHAR != 0)      
    /**
   *Add Boot Request Characteristic
   */
    aci_gatt_add_char(aPeerToPeerContext.PeerToPeerSvcHdle,
                      BM_UUID_LENGTH,
                      (Char_UUID_t *)BM_REQ_CHAR_UUID,
                      BM_REQ_CHAR_SIZE,
                      CHAR_PROP_WRITE_WITHOUT_RESP,
                      ATTR_PERMISSION_NONE,
                      GATT_NOTIFY_ATTRIBUTE_WRITE,
                      10,
                      0,
                      &(aPeerToPeerContext.RebootReqCharHdle));
#endif   

   
return;
}将发送函数改为发送50个字节,请看注释,STM32WB55只能发送20个字节数据(数据:0x01~0x14)。
tBleStatus P2PS_STM_App_Update_Char(uint16_t UUID, uint8_t *pPayload)
{
tBleStatus result = BLE_STATUS_INVALID_PARAMS;
switch(UUID)
{
    case P2P_NOTIFY_CHAR_UUID:
      
   result = aci_gatt_update_char_value(aPeerToPeerContext.PeerToPeerSvcHdle,
                           aPeerToPeerContext.P2PNotifyServerToClientCharHdle,
                              0, /* charValOffset */
                               50,//2, /* charValueLen //改为50个字节
                           (uint8_t *)pPayload);
   
      break;

    default:
      break;
}

return result;
}/* end P2PS_STM_Init() */void P2PS_Send_Notification(void)
{
uint8_t data;
for (int i=0; i<50; i++)
{
    data = i+1;
}

if(P2P_Server_App_Context.ButtonControl.ButtonStatus == 0x00){
    P2P_Server_App_Context.ButtonControl.ButtonStatus=0x01;
} else {
    P2P_Server_App_Context.ButtonControl.ButtonStatus=0x00;
}

   if(P2P_Server_App_Context.Notification_Status){
    APP_DBG_MSG("-- P2P APPLICATION SERVER: INFORM CLIENT BUTTON 1 PUSHED \n ");
    APP_DBG_MSG(" \n\r");
    P2PS_STM_App_Update_Char(P2P_NOTIFY_CHAR_UUID, data);//改为发送50个字节数据
   我还发现程序运行一段时间(大概5分钟),就提示“Fatal error:ST-Link USB communication error, Session abort!”,我调试的其他的STM32单片机很少出现过ST Link断开连接的问题。




奏奏奏 发表于 2020-5-29 06:51:24

如果没办法,只能长数据包分拆为多包处理
之前用CAN总线传输就是这样,标准CAN总线(不算FD-CAN能到64字节每包)每包最多8个字节
设备上报MCU的(准确来说是STM32的)UID序列号,只能分拆为3包传:'(
接收设备端再按照协议拼包,注意丢了其中1包或者包顺序错乱的容错处理
协议中必须包含一共多少包、当前是第几包、拼包后完整性校验信息

juky1983 发表于 2020-5-29 10:11:11

奏奏奏 发表于 2020-5-29 06:51
如果没办法,只能长数据包分拆为多包处理
之前用CAN总线传输就是这样,标准CAN总线(不算FD-CAN能到64字节 ...
谢谢您的回复。
如果分包的话,不足之处就是接收到的数据包之间的间隔是不定的。有时候是1ms,有时候会达到30ms以上了。CAN的多个数据包之间的延时小于5ms,能很好判断数据帧的成帧时间。
实际使用过程中,数据包大小在100到250字节之间。如果能不分包的话,那传输的效率就有了很大的提升,大大减小了软件设计的复杂性了。

butterflyspring 发表于 2020-6-8 11:49:04

单次接收应该不能超过247bytes,参考如下结构体, 从AN5270 Table 365. ACI_GATT_READ_EXT_EVENT event parameters,可以读取超过247Bytes,但是数据可能通过多个ACI_GATT_READ_EXT_EVENT上报,是否有更多数据,需通过offset的bit 15来判断。

可以参考下面的例程
C:\Users\min du\STM32Cube\Repository\STM32Cube_FW_WB_V1.7.0\Projects\P-NUCLEO-WB55.Nucleo\Applications\BLE\BLE_DataThroughput

juky1983 发表于 2020-6-10 09:45:16

STM32Cube_FW_WB_V1.7.0\Projects\P-NUCLEO-WB55.Nucleo\Applications\BLE\BLE_DataThroughput:

使用该例程,手机端蓝牙助手不能发现“DT_SERVER”
STM32Cube_FW_WB_V1.3.0\Projects\P-NUCLEO-WB55.Nucleo\Applications\BLE\BLE_DataThroughput:

使用该例程,手机端蓝牙助手可以发现“DT_SERVER”。


按下开发板上的SW1键后,设备一直发送数据。直到再次按下SW1键后停止发送,SendData()--》DTS_STM_UpdateChar()返回BLE_STATUS_SUCCESS后一直请求发送,UTIL_SEQ_SetTask(1 << CFG_TASK_DATA_TRANSFER_UPDATE_ID, CFG_SCH_PRIO_0);。
但是请求发送的字节数为240字节。DataTransferServerContext.TxData.Length = DATA_NOTIFICATION_MAX_PACKET_SIZE; (240)
发送流程如下:
SendData()-》DTS_STM_UpdateChar()-》TX_Update_Char()--》
ret = aci_gatt_update_char_value(
                                 aDataTransferContext.DataTransferSvcHdle,
                                 aDataTransferContext.DataTransferTxCharHdle,
                                 0, /* charValOffset */
                                 pDataValue->Length, /* charValueLen */这里的Length=240,调试时确定。
                                 (uint8_t *) pDataValue->pPayload);


页: [1]
查看完整版本: STM32WB55 如何一次性发送和接收超过100字节的数据包?