MPLAB® Harmony v3 Peripheral Libraries on PIC32MX 470: Step 5
Add Application Code to the Project
The application is already partially developed and is available in the main_pic32mx470.c file under
<your unzip folder>/pic32mx470_getting_started/dev_files/pic32mx470_curiosity. The bme280_driver.c file contains the driver code to read temperature from the BME280 sensor. The main_pic32mx470.c file contains the application logic. It also contains placeholders that you will populate with the necessary code in the next step.
- Go to the pic32mx470_getting_started/dev_files/pic32mx470_curiosity folder and copy the pre-developed main_pic32mx470.c file.
- Replace the main_pic32mx470.c file of your project available at <Your project folder>/pic32mx470_getting_started/firmware/src by overwriting it with the copied file.
- Open main_pic32mx470.c in MPLAB® X IDE and add the application code by following the steps below:
Add bme280_driver.c file into Source Files, located in the Projects tab.
In the Projects tab, right-click on Source Files to add the existing pre-developed bme280_driver.c file.
- Select the bme280_driver.c file from the <Your project folder>/pic32mx470_getting_started/firmware/src folder.
Click Select and the bme280_driver.c file will be added into the project source files.
Add bme280_driver.h, and bme280_definitions.h files into project header files.
In the Projects tab, right-click on Header Files to add the existing pre-developed bme280_driver.h and bme280_definitions.h files.
Select the bme280_driver.h file from the <Your project folder>/pic32mx470_getting_started/firmware/src folder.
Select the bme280_definitions.h file from the <Your project folder>/pic32mx470_getting_started/firmware/src folder.
Click Select then bme280_driver.h and bme280_definitions.h file will be added into the project header files.
Under the main_pic32mx470.c file, in function main, notice the call to function SYS_Initialize. The generated function SYS_Initialize initializes all the peripheral modules used in the application, which is configured through MPLAB Code Configurator (MCC).
In the main() function, below SYS_Initialize(), add the following code to register callback event handlers.
DMAC_ChannelCallbackRegister(DMAC_CHANNEL_0, UARTDmaChannelHandler, 0);
TMR2_CallbackRegister(tmr2EventHandler, 0);
GPIO_PinInterruptCallbackRegister(S1_PIN, S1_User_Handler, 0);
GPIO_PinInterruptEnable(S1_PIN);
Following the addition of the code above, add the function call to initialize the BME280 sensor.
Following the addition of the code above, add the function call.
Implement the registered callback event handlers for TMR2, I²C, Universal Asynchronous Receiver Transmitter (UART), and General Purpose Input/Output (GPIO) PLIBs by adding the following code before the main() function in main_pic32mx470.c.
{
if(S1_Get() == SWITCH_PRESSED_STATE)
{
changeTempSamplingRate = true;
}
}
static void tmr2EventHandler (uint32_t intCause, uintptr_t context)
{
isTmr2Expired = true;
}
static void I2CBufferEventHandler(uintptr_t contextHandle)
{
if (I2C1_ErrorGet() == I2C_ERROR_NONE)
{
BME280SensorData.isBufferCompleteEvent = true;
}
}
static void UARTDmaChannelHandler(DMAC_TRANSFER_EVENT event, uintptr_t contextHandle)
{
if (event == DMAC_TRANSFER_EVENT_COMPLETE)
{
isUARTTxComplete = true;
}
}
Implement the BME280Sensor_Initialize() function after callback event handler functions in main_pic32mx470.c.
{
BME280SensorData.temperature = 0;
BME280SensorData.slaveID = BME280_I2C_ADDRESS;
BME280SensorData.isBufferCompleteEvent = false;
/* Register with BME280 sensor */
BME280_RegisterDrvWriteReg(BME280Sensor_WriteReg);
BME280_RegisterDrvReadReg(BME280Sensor_ReadReg);
BME280_RegisterDrvRead(BME280Sensor_Read);
BME280_SoftReset();
/* 100 m.sec delay */
CORETIMER_DelayMs(100);
if (BME280_CHIP_ID != BME280_ID_Get())
{
while(1); /* Error Occurred */
}
BME280_CalibParams_Get();
BME280_SetOversampling(BME280_PARAM_TEMP, BME280_OVERSAMPLING_1X);
BME280_PowerMode_Set(BME280_NORMAL_MODE);
}
Implement the BME280Sensor_WriteReg(), BME280Sensor_ReadReg(), and BME280Sensor_Read() functions before the BME280Sensor_Initialize() function in main_pic32mx470.c.
{
BME280SensorData.txBuffer[0] = wrAddr;
BME280SensorData.txBuffer[1] = wrData;
BME280SensorData.isBufferCompleteEvent = false;
I2C1_Write(BME280SensorData.slaveID, BME280SensorData.txBuffer, 2);
while(false == BME280SensorData.isBufferCompleteEvent);
return true;
}
static uint8_t BME280Sensor_ReadReg(uint8_t rAddr)
{
BME280SensorData.txBuffer[0] = rAddr;
BME280SensorData.isBufferCompleteEvent = false;
I2C1_WriteRead(BME280SensorData.slaveID, BME280SensorData.txBuffer, 1, BME280SensorData.rxBuffer, 1);
while(false == BME280SensorData.isBufferCompleteEvent);
return BME280SensorData.rxBuffer[0];
}
static bool BME280Sensor_Read(uint8_t rAddr, uint8_t* const pReadBuffer, uint8_t nBytes)
{
BME280SensorData.txBuffer[0] = rAddr;
BME280SensorData.isBufferCompleteEvent = false;
I2C1_WriteRead(BME280SensorData.slaveID, BME280SensorData.txBuffer, 1, pReadBuffer, nBytes);
while(false == BME280SensorData.isBufferCompleteEvent);
return true;
}
Using the screenshot below, add the code to submit a temperature read transfer request to read temperature sensor values when the configured time period (default 500 milliseconds) has elapsed. It will read uncompensated temperature values from the sensor when the submitted request is complete.
BME280_ReadRawWeatherData();
Using the screenshot below, add the code to calculate compensated temperature value. The compensated temperature is in DegC (°C) while the resolution is 0.01 °C.
Using the screenshot below, add the code to convert from Celcius to Fahrenheit (°C to °F) (°F = (°C × 9/5) + 32).
Using the screenshot below, add the code to prepare the received temperature value from the sensor to be shown on the serial terminal.
LED1_Toggle();
Using the accompanying screenshot, add the code to implement the change in sampling rate and prepare a message for the change on the serial terminal when the user presses the S1 switch.
TMR2_Stop();
if(tempSampleRate == TEMP_SAMPLING_RATE_500MS)
{
tempSampleRate = TEMP_SAMPLING_RATE_1S;
sprintf((char*)uartTxBuffer, "Sampling Temperature every 1 second \r\n");
TMR2_PeriodSet(PERIOD_1S);
}
else if(tempSampleRate == TEMP_SAMPLING_RATE_1S)
{
tempSampleRate = TEMP_SAMPLING_RATE_2S;
sprintf((char*)uartTxBuffer, "Sampling Temperature every 2 seconds \r\n");
TMR2_PeriodSet(PERIOD_2S);
}
else if(tempSampleRate == TEMP_SAMPLING_RATE_2S)
{
tempSampleRate = TEMP_SAMPLING_RATE_4S;
sprintf((char*)uartTxBuffer, "Sampling Temperature every 4 seconds \r\n");
TMR2_PeriodSet(PERIOD_4S);
}
else if(tempSampleRate == TEMP_SAMPLING_RATE_4S)
{
tempSampleRate = TEMP_SAMPLING_RATE_500MS;
sprintf((char*)uartTxBuffer, "Sampling Temperature every 500 ms \r\n");
TMR2_PeriodSet(PERIOD_500MS);
}
else
{
;
}
TMR2_Start();
Using the accompanying screenshot, add the code to transfer the buffer containing either:
- the latest temperature value in the format “Temperature = XX F\r\n”, or
- the message mentioning the change of sampling rate over UART using DMA.
You are now ready to build the code!