Low Power Application on SAMC2x using MPLAB® Harmony v3 Peripheral Libraries: Step 6
Add application code to the project
The application is already developed and is available in the main.c file under <your unzip folder>/samc21_low_power/dev_files/sam_c21_xpro. The main.c file contains the application logic. It also contains placeholders that you will populate with necessary code in the next step.
- Go to the samc21_low_power/dev_files/sam_c21_xpro folder and copy the pre-developed main.c file.
- Replace (over-write) the main.c file of your project available at < Your project folder>/samc21_low_power/firmware/src with the copied file.
- Open main.c in MPLAB® X IDE and add the application code by following the steps below:
Under main.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 (configured through the MPLAB Harmony Configurator (MHC)).
In the main.c function, below SYS_Initialize(), add the following code to register callback event handlers.
EIC_CallbackRegister(EIC_PIN_8,EIC_User_Handler, 0); SERCOM2_I2C_CallbackRegister(i2cEventHandler,0); DMAC_ChannelCallbackRegister(DMAC_CHANNEL_0,dmaChannel0Handler,0); ADC1_CallbackRegister(adcEventHandler,0);
Add below lines of code to enable the Analog-to-Digital Converter (ADC), start Timer, and to move the device from Standby to Sleep mode.
RTC_Timer32Start();
PM_StandbyModeEnter();
Implement the registered callback event handlers for ADC, I²C, Universal Synchronous Asynchronous Receiver Transmitter (USART), and EIC PLIBs by adding the following code before main() function in main.c.
if(event == DMAC_TRANSFER_EVENT_COMPLETE)
{
isDMATransferComplete = true;
}
}
static void i2cEventHandler(uintptr_t contextHandle){
if(SERCOM2_I2C_ErrorGet() == SERCOM_I2C_ERROR_NONE)
{
isTemperatureRead = true;
}
}
static void adcEventHandler(ADC_STATUS status, uintptr_t context)
{
if(status & ADC_STATUS_WINMON){
adcResult = ADC1_ConversionResultGet();
isADCWinMonitorEvent = true;
}
}
static void EIC_User_Handler(uintptr_t context)
{
sleepMode = true;
}
Inside the while loop, add the code below to submit an I²C transfer to read temperature sensor value when the ADC triggers an interrupt (i.e when the user covers the light sensor). The I²C PLIB calls back the callback event handler (registered in Step 2 above) when the submitted request is complete.
isADCWinMonitorEvent = false;
SERCOM2_I2C_WriteRead(TEMP_SENSOR_SLAVE_ADDR,&i2cWrData,1,i2cRdData,2 );
}
Add the below code to prepare the received temperature value from the sensor to be printed on the serial terminal and code to transfer the buffer containing either the latest temperature value in the format Temperature = XX F\r\n below ADC window monitor event if loop.
{
isTemperatureRead = false;
temperatureVal = getTemperature(i2cRdData);
sprintf((char*)uartTxBuffer,"Temperature = %02d F \r\n",temperatureVal);
DMAC_ChannelTransfer(DMAC_CHANNEL_0,uartTxBuffer,(const void*)&(SERCOM4_REGS->USART_INT.SERCOM_DATA),strlen((const char*)uartTxBuffer));
LED_Toggle();
}
Add the code below to enter into Standby mode once DMA completes the transfer and add the code snippet to enter into Idle Sleep mode when the user presses switch SW0.
if(isDMATransferComplete == true){
isDMATransferComplete = false;
LED_Set();
PM_StandbyModeEnter();
}
if(sleepMode == true)
{
sleepMode = false;
PM_IdleModeEnter();
}
In plib_eic.c, add #include definitions.h at the top and in EIC_InterruptHandler function add WAKEUP_TEST_Toogle() function. This General Purpose Input/Output (GPIO) is toggled in the Interrupt Service Routine (ISR) of the switch press event 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!