nRF52832开发记录—-ble发送数据丢包

  • Post author:
  • Post category:其他

在发送大数据时,发现实际发送长度不对,数据没有发送完全。

发送逻辑为:
发送长度大于MTU时分包发送,第一次只发送MTU长度,
待发送完成后接着发送剩余数据,每次最大发送MTU长度

以下为实现:

1. 封装发送函数

发送长度不能超过MTU值

void myBleNusDataSend(uint8_t *pDat, uint32_t dataLength){
    uint16_t length = 0;
    uint32_t       err_code;

    do{
        length = (uint16_t)dataLength;
        err_code = ble_nus_data_send(&m_nus, pDat, &length, m_conn_handle); //SDK库函数             
        if ((err_code != NRF_ERROR_INVALID_STATE) &&
            (err_code != NRF_ERROR_RESOURCES) &&
            (err_code != NRF_ERROR_NOT_FOUND))
        {
    
            APP_ERROR_CHECK(err_code);
        }
    } while (err_code == NRF_ERROR_RESOURCES);   

}

2. 大数据发送函数

如果数据长度超过MTU,则只发送MTU长度数据

#define BLE_NUS_MAX_DATA_LEN        (244)   // MTU值
static int gSendDataLen = 0;                // 记录总共需要发送的数据长度
static int gSendDataCurrentLen = 0;         // 当前已发送的数据长度
static uint8_t *gpData = 0;                 // 待发送数据起始位置
void bleNusDataSend(uint8_t *pDat, uint32_t dataLength){
    uint16_t length = 0;

    if(dataLength > BLE_NUS_MAX_DATA_LEN){
        // 超过MTU长度的数据发送
        length = BLE_NUS_MAX_DATA_LEN;

        gSendDataLen = dataLength;
        gSendDataCurrentLen = length;
        gpData = pDat;

        myBleNusDataSend(pDat,length);

        while(gSendDataLen != 0){// 等待发送完毕
        
        }        
    }else{
        // 未超过MTU长度的数据直接一次性发送完毕
        length = dataLength;

        gSendDataLen = 0;
        gSendDataCurrentLen = 0;
        gpData = 0;
        myBleNusDataSend(pDat,length);
    }    

}

3. 剩余数据发送

static void nus_data_handler(ble_nus_evt_t * p_evt)
{
    if (p_evt->type == BLE_NUS_EVT_RX_DATA)
    {
            // 接收到数据
    }
    else if(p_evt->type == BLE_NUS_EVT_TX_RDY){

        uint32_t tmpLen = 0;
        if(gSendDataLen > 0){
            tmpLen = (gSendDataLen - gSendDataCurrentLen);
            tmpLen = (tmpLen > gBleSendImgSubpackageLen)?(gBleSendImgSubpackageLen):(tmpLen);
            myBleNusDataSend((uint8_t *)&gpData[gSendDataCurrentLen],  tmpLen);
            gSendDataCurrentLen += tmpLen;            

            if(gSendDataLen <= gSendDataCurrentLen){
                gSendDataLen = 0;
                gSendDataCurrentLen = 0;
                gpData = 0;
            }            
        }
	
    }

}

4. 错误原因及解决方法

原因:每次发送数据太长,数据发送不完整的原因是使用了全局中间变量,中间变量频率更改及读取时未被更新
解决:将全局变量加上volatile关键词,强制编译器不优化,每次更新全局变量
volatile static int gSendDataLen = 0; // 记录总共需要发送的数据长度
volatile static int gSendDataCurrentLen = 0; // 当前已发送的数据长度
volatile static uint8_t *gpData = 0; // 待发送数据起始位置


版权声明:本文为webuildthings原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。