#include #include #include volatile uint8_t button; // flag "button" volatile uint8_t indicate; // flag "indicate" volatile uint8_t tcb; // TCB SW flag uint16_t adc_bat; // battery voltage ADC Value ISR(PORTA_PORT_vect) // button { button = 1; // set "button" flag indicate = 1; // set "indicate" flag PORTA.INTFLAGS = PORT_INT2_bm; // clear PA2 interrupt flag } ISR(TCB0_INT_vect) // 50ms after button pressed { tcb = 1; // set TCB SW flag TCB0.CTRLA = 0; // disable TCB TCB0.CNT = 0; // clear TCB TCB0.INTFLAGS = TCB_CAPT_bm; // clear TCB interrupt flag } int main(void) { _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, CLKCTRL_PDIV_10X_gc | CLKCTRL_PEN_bm); // 2MHz Main Clock PORTA.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc; // disable PA3 digital input buffer PORTA.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc; // disable PA6 digital input buffer PORTA.PIN7CTRL = PORT_ISC_INPUT_DISABLE_gc; // disable PA7 digital input buffer PORTA.DIRSET = PIN1_bm; // PA1 output PORTA.PIN2CTRL = PORT_PULLUPEN_bm | PORT_ISC_LEVEL_gc; // PA2 pull-up, low level sense interrupt VREF.CTRLA = VREF_ADC0REFSEL_2V5_gc; // 2.5V ADC voltage reference ADC0.CTRLC = ADC_REFSEL_VDDREF_gc | ADC_PRESC_DIV8_gc; // VDD as reference, 250kHz ADC clock ADC0.MUXPOS = ADC_MUXPOS_INTREF_gc; // internal reference VREF as ADC input ADC0.CTRLD = ADC_INITDLY_DLY64_gc; // initialization/start-up delay (256µs) ADC0.CTRLB = ADC_SAMPNUM_ACC4_gc; // accumulate 4 ADC sampling results ADC0.CTRLA = ADC_ENABLE_bm; // enable ADC TCB0.CCMP = 0xC350; // timeout value (50ms @ 1MHz TCB clock) TCB0.INTCTRL = TCB_CAPT_bm; // enable TCB capture or timeout interrupt SLPCTRL.CTRLA = SLPCTRL_SMODE_STDBY_gc; // select STANDBY sleep mode sei(); // enable global interrupts while(1) { if(button) { button = 0; // clear the flag ADC0.COMMAND = ADC_STCONV_bm; // start conversion while(!(ADC0.INTFLAGS & ADC_RESRDY_bm)){} // wait until conversion done adc_bat = ADC0.RES; // read accumulated result adc_bat >>= 2; // divide by 4 if(adc_bat > 730) // if V_bat < 3.5V { PORTA.OUTSET = PIN1_bm; // PA1 on } TCB0.CTRLA = TCB_CLKSEL_CLKDIV2_gc | TCB_ENABLE_bm; // 1MHz TCB clock, enable TCB } if(tcb) // TCB for debouncing without delay { if(PORTA.IN & PIN2_bm) // if PA2 button released { PORTA.OUTCLR = PIN1_bm; // PA1 off tcb = 0; // clear the flag indicate = 0; // clear the flag } } if(!indicate) { PORTA.PIN2CTRL = PORT_PULLUPEN_bm | PORT_ISC_LEVEL_gc; // PA2 pull-up, low level sense interrupt sleep_mode(); PORTA.PIN2CTRL = PORT_PULLUPEN_bm; // PA2 pull-up, disable interrupt } } }