This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Sending string data over NUS

Hello,

I am trying to modify the ble_app_uart code so that my peripheral can send data automatically to the central, which in turn can print it on a computer through UART. What I mean is that instead of the ble_nus_string_send() command being called when I press enter, I want the peripheral to send a number automatically from the main.

This is the code I'm using for sending the number in the peripheral, which prints the value of number correct starting at 1:

    uint8_t number = 0;
    uint8_t data[20]; 

    for (;;)
    {

        number = number + 1;

        sprintf((char *)data, "%d", number); 

        ble_nus_string_send(&m_nus, data, sizeof(data));
    }

This is the code in the central, in the case that BLE_NUS_C_EVT_NUS_TX_EVT happens it calls this function:

static void ble_nus_chars_received_uart_print(uint8_t * p_data, uint16_t data_len)
{
    ret_code_t ret_val;

    NRF_LOG_DEBUG("Receiving data.");
    NRF_LOG_HEXDUMP_DEBUG(p_data, data_len);

    for (uint32_t i = 0; i < data_len; i++)
    {
        do
        {
            ret_val = app_uart_put(p_data[i]);
            if ((ret_val != NRF_SUCCESS) && (ret_val != NRF_ERROR_BUSY))
            {
                NRF_LOG_ERROR("app_uart_put failed for index 0x%04x.", i);
                APP_ERROR_CHECK(ret_val);
            }
        } while (ret_val == NRF_ERROR_BUSY);
    }
    if (p_data[data_len-1] == '\r')
    {
        while (app_uart_put('\n') == NRF_ERROR_BUSY);
    }
}

As far as I know, with the ble_nus_string_send the central should receive and print the number on the other PC. From what I know, the central enters ble_nus_c_evt_handler to establish connection but the NUS_TX_EVT is not being called.

How can I fix this? Or is there a better way to send a number from the peripheral and have the central simply print it to UART?

I'm using NRF52832 and S132.

Parents
  • A few hints you might consider:

    sizeof(SomeString) for ascii data transmission is bad, use instead strlen(SomeString). The former includes all the crap on the stack after useful data when used with printf etc and might work but is not reliable. The second attempts to transmit only the ascii data you put in the string

    sprintf() is unsafe, use instead snprintf()

    "\r" may not be the same as '\r" or snprintf( ... "..\r"); be safe, use snprintf()

    Here is an example which might be useful; Central is showing additional information and it works with the Nordic Uart service you are using

    static void ReportVersion(void)
    {
        char     InfoPacket[120];
        const uint16_t sdMajor  =  SD_VERSION / 1000000;
        const uint16_t sdMinor  = (SD_VERSION - (sdMajor*1000000)) / 1000;
        const uint16_t sdBugfix = (SD_VERSION - ((sdMajor*1000000) + (sdMinor*1000)));
        ble_version_t sdVersion = {0,0,0};
        ble_version_t *p_version = &sdVersion;
        // Get actual installed SoftDevice version (may be different from header file)
        sd_ble_version_get(p_version);
    
        // Sign on
        // "Central (66906325295D586C) SD Ver. [5.1.0] [59 A5 9]"
        snprintf(InfoPacket, sizeof(InfoPacket), "Central (%08X%08X) SD Ver. [%u.%u.%u] [%X %X %X]\r",
                             NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0], sdMajor, sdMinor, sdBugfix,
                             p_version->company_id, p_version->subversion_number, p_version->version_number);
        SendViaHardwareUart(InfoPacket);
    }
    

    Here is a typical uart function expected by the code above

    void SendViaHardwareUart(char * InfoPacket)
    {
       uint32_t err_code;
       uint32_t txIndex;
    
       txIndex = strlen(InfoPacket);
       for (uint32_t i = 0; i < txIndex; i++)
       {
          do
          {
             err_code = app_uart_put(InfoPacket[i]);
          } while (err_code == NRF_ERROR_BUSY) ;
       }
       if (InfoPacket[txIndex-1] == '\r')
       {
          while (app_uart_put('\n') == NRF_ERROR_BUSY) ;
       }
    }
    

Reply
  • A few hints you might consider:

    sizeof(SomeString) for ascii data transmission is bad, use instead strlen(SomeString). The former includes all the crap on the stack after useful data when used with printf etc and might work but is not reliable. The second attempts to transmit only the ascii data you put in the string

    sprintf() is unsafe, use instead snprintf()

    "\r" may not be the same as '\r" or snprintf( ... "..\r"); be safe, use snprintf()

    Here is an example which might be useful; Central is showing additional information and it works with the Nordic Uart service you are using

    static void ReportVersion(void)
    {
        char     InfoPacket[120];
        const uint16_t sdMajor  =  SD_VERSION / 1000000;
        const uint16_t sdMinor  = (SD_VERSION - (sdMajor*1000000)) / 1000;
        const uint16_t sdBugfix = (SD_VERSION - ((sdMajor*1000000) + (sdMinor*1000)));
        ble_version_t sdVersion = {0,0,0};
        ble_version_t *p_version = &sdVersion;
        // Get actual installed SoftDevice version (may be different from header file)
        sd_ble_version_get(p_version);
    
        // Sign on
        // "Central (66906325295D586C) SD Ver. [5.1.0] [59 A5 9]"
        snprintf(InfoPacket, sizeof(InfoPacket), "Central (%08X%08X) SD Ver. [%u.%u.%u] [%X %X %X]\r",
                             NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0], sdMajor, sdMinor, sdBugfix,
                             p_version->company_id, p_version->subversion_number, p_version->version_number);
        SendViaHardwareUart(InfoPacket);
    }
    

    Here is a typical uart function expected by the code above

    void SendViaHardwareUart(char * InfoPacket)
    {
       uint32_t err_code;
       uint32_t txIndex;
    
       txIndex = strlen(InfoPacket);
       for (uint32_t i = 0; i < txIndex; i++)
       {
          do
          {
             err_code = app_uart_put(InfoPacket[i]);
          } while (err_code == NRF_ERROR_BUSY) ;
       }
       if (InfoPacket[txIndex-1] == '\r')
       {
          while (app_uart_put('\n') == NRF_ERROR_BUSY) ;
       }
    }
    

Children
No Data
Related