My circuit was working exactly as I wanted until I realized that it was taking 25mA when it was sleeping. Turns out, the TX pin was back-powering an external RS422 driver through the pin. So I changed the code.
Right before going to sleep I know disable the UART and set the TX pin to an input. Then right after waking up, I do the opposite. It solved the problem with the extra current draw, but now the UART won't work after sleeping. It works the first time through the code but as soon as the part goes to sleep and wakes up then the UART stops working. So something is messed up on waking up I surmise.
Here is the code....
This code is run when the signal ANT_SWITCH is sampled and goes low. There is no interrupt here, just polled in the main loop.
SLPCTRL_set_sleep_mode( SLPCTRL_SMODE_PDOWN_gc ); // turn RS422 transceiver power off to save power when asleep RS422_PWR_EN_set_level( false ); // turn off UART and disable TX pin so we don't power RS422 transceiver through the I/O pin USART_0_disable(); PORTB_set_pin_dir(2, PORT_DIR_IN); // turn off NFC_IRQ interrupt and clear interrupt flag NFC_IRQ_set_isc( PORT_ISC_INTDISABLE_gc ); VPORTA_INTFLAGS = (1 << 1); // turn off timer interrupt TCA0.SINGLE.INTCTRL &= ~TCA_SINGLE_OVF_bm; // clear flag and turn on interrupt for ANT_SWITCH pin for rising edge to wake up VPORTA_INTFLAGS = (1 << 2); ANT_SWITCH_set_isc( PORT_ISC_RISING_gc ); // turn watchdog off or it will just wake up device ccp_write_io( (void *)&(WDT.CTRLA), WDT_PERIOD_OFF_gc | WDT_WINDOW_OFF_gc /* Window mode off */); // enable sleep mode SLPCTRL.CTRLA = 1 << SLPCTRL_SEN_bp; // go to sleep asm( "sleep" ); /* * * Device is now asleep and will wake up on pin interrupt and continue below * */ // short delay uint16_t ii; for( ii=0; ii<UINT16_MAX; ii++ ); // turn RS422 transceiver power back on RS422_PWR_EN_set_level( true ); // turn off interrupt for ANT_SWITCH pin for rising edge ANT_SWITCH_set_isc( PORT_ISC_INTDISABLE_gc ); // turn system interrupts back on TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm; NFC_IRQ_set_isc( PORT_ISC_RISING_gc ); // turn watchdog back on to ~4 second period ccp_write_io( (void *)&(WDT.CTRLA), WDT_PERIOD_4KCLK_gc /* 4K cycles (4.1s) */ | WDT_WINDOW_OFF_gc /* Window mode off */); // re-configure UART TX pin // Set pin direction to output UART_TX_set_dir(PORT_DIR_OUT); UART_TX_set_level( // <y> Initial level // <id> pad_initial_level // <false"> Low // <true"> High false); USART_0_enable(); // send wakeup message UART_SEND_CHAR( 0x07 );
Any ideas what I don't have set back up correctly?