Low Power Application on SAM L10 Using MPLAB® Harmony v3 Peripheral Libraries: Step 6
Add Application Code to the Project
The application is already partially developed and is available in the main_l10.c file under <your unzip folder>/saml10_low_power/dev_files/sam_l10_xpro. The main_l10.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 saml10_low_power/dev_files/sam_l10_xpro folder and copy the pre-developed main_l10.c file.
- Replace (over-write) the main_l10.c file of your project available at <Your project folder>/saml10_low_power/firmware/src with the copied file.
- Open main_l10.c in MPLAB® X IDE and add the application code by following the steps below:
Under the main_l10.c file, in the main() function, notice the call to the SYS_Initialize function. The generated SYS_Initialize function initializes all the peripheral modules used in the application, configured through MPLAB Harmony Configurator (MHC).
In the int main (void) function, below the SYS_Initialize() function call, add the following code to register callback event handlers, enable the Analog-to-Digital Converter (ADC), start the Real-Time Clock (RTC) timer, display the message, and enter Standby mode.
SERCOM1_I2C_CallbackRegister (i2cEventHandler, 0);
DMAC_ChannelCallbackRegister (DMAC_CHANNEL_0, dmaChannel0Handler, 0);
ADC_CallbackRegister (adcEventHandler, 0);
ADC_Enable ();
RTC_Timer32Start ();
printf ("\n\n\r---------------------------------------------------------");
printf ("\n\r Low-power Application on SAM L10 Xpro ");
printf ("\n\r---------------------------------------------------------\n\n\r");
printf ("Enter Standby sleep mode\n\n\r");
PM_StandbyModeEnter ();
Implement the registered callback interrupt handlers for DMA, I²C, ADC, and EIC PLIBs by adding the following code before the int main (void) function in main_l10.c.
static void dmaChannel0Handler (DMAC_TRANSFER_EVENT event, uintptr_t contextHandle)
{
if(event == DMAC_TRANSFER_EVENT_COMPLETE)
{
isDMATransferComplete = true;
}
}
/* Handler for I²C interrupt */
static void i2cEventHandler (uintptr_t contextHandle)
{
if(SERCOM1_I2C_ErrorGet() == SERCOM_I2C_ERROR_NONE)
{
isTemperatureRead = true;
}
else
{
printf ("There were an error during I2C Transmit. Please ensure that the I/O1 Xplained Pro is connected to the board.\n\n\r");
}
}
/* Handler for ADC Window Monitor Interrupt */
static void adcEventHandler (ADC_STATUS status, uintptr_t context)
{
isADCWinMonitorEvent = true;
}
/* Handler for button switch interrupt using EIC peripheral */
static void EIC_User_Handler (uintptr_t context)
{
sleepMode = true;
}
Inside the while loop, add the following code to unset the isADCWinMonitorEvent flag, turn on the LED0, print the message, and submit an I²C transfer to read the temperature sensor value. When the submitted request is completed, the i2cEventHandler callback function declared in step 2 is called.
{
isADCWinMonitorEvent = false;
LED0_Clear ();
printf ("ADC_WINMON Interrupt Detected. Wake-up from sleep mode.\n\r");
SERCOM1_I2C_WriteRead (TEMP_SENSOR_SLAVE_ADDR, &i2cWrData, 1, i2cRdData, 2);
}
Inside the while loop, add the following code to unset the isTemperatureRead flag, store the temperature read into the temperatureVal variable, fill uartTxBuffer with the converted temperature value in degrees Fahrenheit and transmit this value to the terminal through the SERCOM0 USART peripheral by using the DMA.
{
isTemperatureRead = false;
temperatureVal = getTemperature (i2cRdData);
sprintf ((char*)uartTxBuffer, "Temperature = %02d F \r\n", temperatureVal);
while (!SERCOM0_USART_TransmitterIsReady());
DMAC_ChannelTransfer (DMAC_CHANNEL_0, uartTxBuffer, (const void*)&(SERCOM0_REGS->USART_INT.SERCOM_DATA), sizeof(uartTxBuffer));
}
Inside the while loop, add the following code to unset the isDMATransferComplete flag, print the message, turn off the LED0, and put the device in Standby mode by using the PM_StandbyModeEnter () function.
{
isDMATransferComplete = false;
printf("DMA transfer completed. Enter Standby sleep mode.\n\n\r");
LED0_Set ();
PM_StandbyModeEnter ();
}
Inside the while loop, add the following code to unset the sleepMode flag, toggle pin PA06, print the message, turn off the LED0, and put the device in Idle mode by using the PM_IdleModeEnter () function.
{
sleepMode = false;
printf ("SW0 button pressed. Enter Idle sleep mode.\n\n\r");
LED0_Set ();
PM_IdleModeEnter ();
}
In the plib_eic.c file, add #include "definitions.h" at the top and scroll down to the EIC_OTHER_InterruptHandler function and add the following code at the top of it. This GPIO is toggled in the Interrupt Service Routine (ISR) of the SW0 press interrupt to measure wake-up time. The time between the switch press and the GPIO toggle in the ISR is the wake-up time.
You are now ready to build the code and observe the results!