4.1.1.5 Bluetooth®LE Transparent UART
This section explains how to create a central device and send/receive characters between two connected BLE devices over Microchip proprietary Transparent UART Profile. The central and peripheral devices in this tutorial are two PIC32WM-BW1 devices. The following instructions are applicable for a BLE Central device.
Users can choose to either run the precompiled Application Example hex file provided on the PIC32WM-BW1 Curiosity Board or follow the steps to develop the application from scratch.
It is recommended to follow the examples in sequence to understand the basic concepts before progressing to the advanced topics.
Hardware Requirement
| S. No. | Tool | Quantity |
|---|---|---|
| 1 | PIC32WM-BW1 Curiosity Board | 2 |
| 2 | USB Type-C™ cable | 2 |
Software Requirement
- To install Tera Term tool, refer to the Tera Term web page listed in the Reference Documentation from Related Links.
Programming the Precompiled Hex File or Application Example
Using MPLAB® X IPE:
- Central Device – Precompiled
.hexfile is located in “<Harmony Content Path>\wireless_apps_pic32_bw1\apps\ble\central\central_trp_uart\hex” folder. - Peripheral Device – Precompiled
.hexfile is located in “<Harmony Content Path>\wireless_apps_pic32_bw1\apps\ble\peripheral\peripheral_trp_uart\hex” folder. - For detailed steps, refer to
Programming a Device in MPLAB® IPE in Reference
Documentation from Related Links.Note: Ensure to choose the correct Device and Tool information.
Using MPLAB® X IDE:
- Perform the following the steps mentioned in Running a Precompiled Example. For more information, refer to Running a Precompiled Application Example from Related Links.
- Central Device – Open and program the
application
central_trp_uart.Xlocated in “<Harmony Content Path>\wireless_apps_pic32_bw1\apps\ble\central\central_trp_uart\firmware”. - Peripheral Device – Open and program the
application
peripheral_trp_uart.Xlocated in “<Harmony Content Path>\wireless_apps_pic32_bw1\apps\ble\peripheral\peripheral_trp_uart\firmware”. -
For more details on finding the Harmony content path, refer to Installing the MCC Plugin from Related Links.
Testing
- Users must use two PIC32WM-BW1 Curiosity Board configured as Peripheral and Central device, to experience this demo.
- Board 1 – PIC32WM-BW1 Curiosity Board Programmed with “peripheral_trp_uart”. Open TeraTerm
and configure as mentioned below:
Terminal Settings:
- Baud Rate/Speed – 115200
- Parity – None
- Data Bits – 8
- Stop Bits – 1
- Flow Control – None
- Reset the board, Upon reset, “BW1-Advertising” message is displayed on the Tera Term.
- Board 2 – PIC32WM-BW1 Curiosity Board Programmed with “central_trp_uart”. Open Tera Term and
configure as mentioned below: Terminal Settings:
- Baud Rate/Speed – 115200
- Parity – None
- Data Bits – 8
- Stop Bits – 1
- Flow Control – None
- Reset the board. Upon reset, “Scanning” message is displayed on the Tera Term.
- Central device (Board 2) will start scanning for nearby peripheral devices to connect. Upon finding peripheral device with public address {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6} message “Found Peer Node” will be displayed and a connection request will be initiated “Initiating connection”.
- After connection establishment, both the
peripheral device (Board 1) and central device (Board 2) displays “Connected!” message on
respective terminal windows.
Figure 4-37. Tera Term - Users can now start sending data back and forth between the central and peripheral device using the terminal emulator. Characters entered on either terminals will immediately be sent to the peer devices
- The Central device (Board 2) scans for approximately 1 minute 40 seconds and displays “Scan Completed” message on terminal window when it finishes.
Project Graph
- Verify if the Project Graph window has
all the expected configuration as illustrated in the following figure.
Figure 4-38. Project Graph
Verifying Scan, Connection and Transparent Profile Configuration
-
Select BLE Stack component in project graph, to open component configuration and configure as illustrated in the following figure.
Figure 4-39. BLE Stack Configuration -
Select Transparent Profile component in project graph, to open component configuration and configure as illustrated in the following figure.
Figure 4-40. Transparent Profile Configuration
Generating Code
For more details on code generation, refer to MPLAB Code Configurator (MCC) Code Generation from Related Links.
Files and Routines Automatically generated by the MCC
The OSAL, RF System and BLE System initialization routine executed during program initialization can be found in the project file. This initialization routine is automatically generated by the MCC.
initialization.capp_ble.c| Source Files | Usage |
|---|---|
app.c | Application State machine, includes calls for Initialization of all BLE stack (GAP,GATT, SMP, L2CAP) related component configurations |
app_ble\app_ble.c | Source code for the BLE stack related component configurations,
code related to function calls from app.c |
app_ble\app_ble_handler.c | GAP, GATT, SMP and L2CAP event handlers |
app_ble\app_trspc_handler.c | All transparent UART client related event handlers |
ble_trspc.c | All transparent client functions for user application |
app.c is auto generated and has a state machine based Application code
sample. Users can use this template to develop their application.Header Files
-
ble_gap.h: This header file contains BLE GAP functions and is automatically included in theapp.cfile -
ble_trspc.h: This header file associated with API’s and structures related to BLE Transparent Client functions for application user.
Function Calls
MCC generates and adds the code to initialize the BLE Stack GAP, GATT, L2CAP and SMP in
APP_BleStackInit() function.
-
APP_BleStackInit()is the API that will be called inside the Applications Initial State (APP_STATE_INIT) inapp.c
User Application Development
-
Include
- Include the user action. For more information, refer to User Action from Related Links.
-
ble_trspc.hinapp.c, BLE Transparent UART Server related API's are available here -
osal/osal_freertos_extend.hinapp_trsps_handler.c, OSAL related API's are available here -
definitions.hin all the files where UART will be used to print debug informationNote:definitions.his not specific to just UART peripheral, instead it must be included in all application source files where peripheral functionality will be exercised.
-
In
app_ble_handler.c, Scan Results and initiating a BLE ConnectionBLE_GAP_EVT_ADV_REPORTevent is generated upon finding Advertisements on legacy channels-
BLE connection can be initiated by using the API
BLE_GAP_CreateConnection(&createConnParam_t;
// Filter Devices based of Address, for this example address checking only 2 bytes if ((p_event->eventField.evtAdvReport.addr.addr[0] == 0xA1 && p_event->eventField.evtAdvReport.addr.addr[1] == 0xA2) || (p_event->eventField.evtAdvReport.addr.addr[0] == 0xB1 && p_event->eventField.evtAdvReport.addr.addr[1] == 0xB2) || (p_event->eventField.evtAdvReport.addr.addr[0] == 0xC1 && p_event->eventField.evtAdvReport.addr.addr[1] == 0xC2)) { SERCOM0_USART_Write((uint8_t *)"Found Peer Node\r\n", 17); BLE_GAP_CreateConnParams_T createConnParam_t; createConnParam_t.scanInterval = 0x3C; // 37.5 ms createConnParam_t.scanWindow = 0x1E; // 18.75 ms createConnParam_t.filterPolicy = BLE_GAP_SCAN_FP_ACCEPT_ALL; createConnParam_t.peerAddr.addrType = p_event->eventField.evtAdvReport.addr.addrType; memcpy(createConnParam_t.peerAddr.addr, p_event->eventField.evtAdvReport.addr.addr, GAP_MAX_BD_ADDRESS_LEN); createConnParam_t.connParams.intervalMin = 0x10; createConnParam_t.connParams.intervalMax = 0x10; createConnParam_t.connParams.latency = 0; createConnParam_t.connParams.supervisionTimeout = 0x48; SERCOM0_USART_Write((uint8_t *)"Initiating Connection\r\n", 23); BLE_GAP_CreateConnection(&createConnParam_t); }
Figure 4-44. app_ble_handler.c - Scan Timeout Event
-
In
app_ble_handler.c“BLE_GAP_EVT_SCAN_TIMEOUT” event is generated when BLE Scan duration expires.SERCOM0_USART_Write((uint8_t *)"Scan Completed \r\n", 17);
Figure 4-45. Scan Timeout -
- Connected and Disconnected Events
-
In
app_ble_handler.c "BLE_GAP_EVT_CONNECTED"event will be generated when a BLE connection is completed.
-
- Connection Handler
-
Connection handle associated with the peer peripheral device needs to be saved for data exchange after a BLE connection
-
p_event->eventField.evtConnect.connHandlehas this information#include "peripheral/sercom/usart/plib_sercom0_usart.h" extern uint16_t conn_hdl;
-
In
APP_BleGapEvtHandler()caseBLE_GAP_EVT_CONNECTED:SERCOM0_USART_Write((uint8_t *)"Connected\r\n",11); conn_hdl = p_event->eventField.evtConnect.connHandle;
-
In case
BLE_GAP_EVT_DISCONNECTED.SERCOM0_USART_Write((uint8_t *)"Disconnected\r\n",14);
Figure 4-46. app_ble_handler.c In
app.c#include "peripheral/sercom/usart/plib_sercom0_usart.h" #include "ble_trspc/ble_trspc.h"
Add following code snippet in
app.cto implement Transmitting the received data over UART usingBLE_TRSPC_SendData()API:uint16_t conn_hdl;// connection handle info captured @BLE_GAP_EVT_CONNECTED event uint8_t uart_data; void uart_cb(SERCOM_USART_EVENT event, uintptr_t context) { APP_Msg_T appMsg; // If RX data from UART reached threshold (previously set to 1) if( event == SERCOM_USART_EVENT_READ_THRESHOLD_REACHED ) { // Read 1 byte data from UART SERCOM0_USART_Read(&uart_data, 1); appMsg.msgId = APP_MSG_UART_CB; OSAL_QUEUE_Send(&appData.appQueue, &appMsg, 0); } } void APP_UartCBHandler() { // Send the data from UART to connected device through Transparent service BLE_TRSPC_SendData(conn_hdl, 1, &uart_data); }
This API is called in the Applications initial state –APP_STATE_INITinapp.cand scan duration is 100 seconds.// Scanning Enabled BLE_GAP_SetScanningEnable(true, BLE_GAP_SCAN_FD_ENABLE, BLE_GAP_SCAN_MODE_OBSERVER, 1000); // Output the status string to UART SERCOM0_USART_Write((uint8_t *)"Scanning \r\n", 11);
-
In case
APP_STATE_INIT, add following:// Enable UART Read SERCOM0_USART_ReadNotificationEnable(true, true); // Set UART RX notification threshold to be 1 SERCOM0_USART_ReadThresholdSet(1); // Register the UART RX callback function SERCOM0_USART_ReadCallbackRegister(uart_cb, (uintptr_t)NULL);
-
In case
APP_STATE_SERVICE_TASKS, add following:else if(p_appMsg->msgId==APP_MSG_UART_CB) { // Transparent UART Client Data transfer Event APP_UartCBHandler(); }Example implementation:Figure 4-47. app.cFigure 4-48. app.c -
In
app.hAddAPP_MSG_UART_CBinAPP_MsgId_Tenum.BLE_TRSPC_SendDat(conn_hdl,1,&data)is the API used to send data forward towards the central device.Figure 4-49. Transmit Data -
In
app_trspc_handler.c, Receive DataBLE_TRSPC_EVT_RECEIVE_DATAis the event generated when data is sent from central device- Users need to use the
BLE_TRSPC_GetDataLength(&data_len)API to extract the length of application data received BLE_TRSPC_GetData(&conn_hdl, data); API is used to retrieve the data, conn_hdl is the value obtained from Connection Handler sectionNote:BLE_TRSPC_Event_Tp_event structure stores the information about BLE transparent UART callback functions.#include <string.h> #include <stdint.h> #include "ble_trspc/ble_trspc.h" #include "definitions.h"
-
In case
BLE_TRSPC_EVT_RECEIVE_DATA:uint16_t data_len; uint8_t *data; // Retrieve received data length BLE_TRSPC_GetDataLength(p_event->eventField.onReceiveData.connHandle, &data_len); // Allocate memory according to data length data = OSAL_Malloc(data_len); if(data == NULL) break; // Retrieve received data BLE_TRSPC_GetData(p_event->eventField.onReceiveData.connHandle, data); // Output received data to UART SERCOM0_USART_Write(data, data_len); // Free memory OSAL_Free(data);
Example Implementation for printing the received data from peripheral device over UART:Figure 4-50. app_trspc_handler.c
-
