Last active
March 9, 2024 04:20
-
-
Save shabaz123/ca3e76b55e292d316417e87d4ae74719 to your computer and use it in GitHub Desktop.
MSP430 code (MSP430G2452) to implement a push-button power on/off system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*********************************************** | |
* Button Power Control | |
* | |
* rev 1 - shabaz - December 2023 | |
* This code expects a push-button wired to GPIO pin P1.2 and VCC. | |
* The output is on pin P2.3 | |
* The delays for turn-on and turn-off are separately configurable | |
* (see the definitions below) | |
* *********************************************/ | |
// includes | |
#include <msp430.h> | |
// ******** defines ******** | |
// change to suit requirements | |
// times are in multiples of 10msec, so 100 means 1000 msec. | |
#define PUSH_ON_INTERVAL 100 | |
#define PUSH_OFF_INTERVAL 100 | |
#define DEBOUNCE_INTERVAL 10 | |
#define PWR_ENABLE P2OUT |= (0x01 << 3) | |
#define PWR_DISABLE P2OUT &= ~(0x01 << 3) | |
// PUSH_BTN_B input is normally low | |
#define PUSH_BTN_B_PRESSED ((P1IN & 0x04)!=0) | |
#define PUSH_BTN_B_UNPRESSED ((P1IN & 0x04)==0) | |
#define BTN_B_EVENT 1 | |
#define BTN_B_NOEVENT 0 | |
#define TOGGLE_NONE 0 | |
#define TOGGLE_WAIT_ON_DEBOUNCE 1 | |
#define TOGGLE_ON_REL_DEBOUNCE 2 | |
#define TOGGLE_ON 3 | |
#define TOGGLE_WAIT_OFF_DEBOUNCE 4 | |
#define TOGGLE_OFF_REL_DEBOUNCE 5 | |
// global vars | |
unsigned int mtick; | |
unsigned char timer_status; | |
// other | |
unsigned char pwrstate; | |
// push-button B | |
unsigned char btn_b_event; | |
unsigned char toggle_state; | |
// function prototypes | |
// ********* interrupt service routines ********* | |
// Timer A0 interrupt service routine | |
#pragma vector=TIMER0_A0_VECTOR | |
__interrupt void Timer_A (void) | |
{ | |
if (mtick < 65535) { | |
mtick++; | |
} | |
__bic_SR_register_on_exit(LPM3_bits); | |
} | |
// Port 1 interrupt service routine | |
#pragma vector=PORT1_VECTOR | |
__interrupt void port1_isr(void) | |
{ | |
if ((P1IFG & 0x04) != 0) { | |
// P1.2 interrupt occurred | |
btn_b_event = BTN_B_EVENT; | |
} | |
P1IFG = 0; // reset interrupt | |
__bic_SR_register_on_exit(LPM3_bits); | |
} | |
// functions | |
void enable_timer(void) | |
{ | |
timer_status = 1; | |
mtick=0; | |
CCR0 = 120; // 120 = 10msec (approx) | |
TACTL = TASSEL_1 | MC_1 | TACLR; // ACLK, upmode, and clear the counter | |
CCTL0 |= CCIE; // enable CCRO interrupt | |
} | |
void disable_timer(void) | |
{ | |
CCTL0 &= ~CCIE; // disable CCRO interrupt | |
timer_status = 0; | |
} | |
// function to handle push-on and push-off functionality | |
void process_btn_b(void) | |
{ | |
switch(toggle_state) { | |
case TOGGLE_NONE: | |
if (btn_b_event==BTN_B_EVENT) { | |
toggle_state = TOGGLE_WAIT_ON_DEBOUNCE; | |
enable_timer(); | |
} | |
break; | |
case TOGGLE_WAIT_ON_DEBOUNCE: | |
if(PUSH_BTN_B_PRESSED) { | |
if (mtick>=PUSH_ON_INTERVAL) { | |
// button was held down long enough, so we can power up! | |
PWR_ENABLE; | |
mtick=0; | |
toggle_state = TOGGLE_ON_REL_DEBOUNCE; | |
} else { | |
// continue to wait to see if the button is pressed long enough | |
} | |
} else { | |
// button was prematurely released! abort. | |
toggle_state = TOGGLE_NONE; | |
disable_timer(); | |
} | |
break; | |
case TOGGLE_ON_REL_DEBOUNCE: | |
if (PUSH_BTN_B_PRESSED) { | |
// keep waiting for the user to release the button | |
} else { | |
if (mtick>=DEBOUNCE_INTERVAL) { | |
toggle_state = TOGGLE_ON; | |
} else { | |
// keep waiting | |
} | |
} | |
break; | |
case TOGGLE_ON: | |
// do nothing unless the button is pressed | |
disable_timer(); | |
//if (btn_b_event==BTN_B_EVENT) { | |
if (PUSH_BTN_B_PRESSED) { | |
toggle_state = TOGGLE_WAIT_OFF_DEBOUNCE; | |
enable_timer(); | |
} else { | |
// do nothing, we are powered up, and no button event to power off. | |
} | |
break; | |
case TOGGLE_WAIT_OFF_DEBOUNCE: | |
if (PUSH_BTN_B_PRESSED) { | |
if (mtick>=PUSH_OFF_INTERVAL) { | |
// button was held down long enough, so we can power off! | |
PWR_DISABLE; | |
mtick=0; | |
toggle_state = TOGGLE_OFF_REL_DEBOUNCE; | |
} else { | |
// continue to wait to see if button is pressed long enough | |
} | |
} else { | |
// button was prematurely released! abort back to the ON state. | |
toggle_state = TOGGLE_ON; | |
disable_timer(); | |
} | |
break; | |
case TOGGLE_OFF_REL_DEBOUNCE: | |
if (PUSH_BTN_B_PRESSED) { | |
// keep waiting for the user to release the button | |
} else { | |
if (mtick>=DEBOUNCE_INTERVAL) { | |
toggle_state = TOGGLE_NONE; | |
disable_timer(); | |
} else { | |
// keep waiting | |
} | |
} | |
default: | |
break; | |
} | |
btn_b_event=BTN_B_NOEVENT; | |
} | |
// ************* main function ****************** | |
void main (void) | |
{ | |
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer | |
BCSCTL3 = LFXT1S_2; // use VLO for ACLK | |
// global var initialization | |
mtick=0; | |
timer_status = 0; | |
btn_b_event = BTN_B_NOEVENT; | |
toggle_state = TOGGLE_NONE; | |
// input/output initialization | |
P1OUT = 0; | |
P2OUT = 0; | |
P1DIR = 0xF8; // Set P1.3, 1.4, 1.5, 1.6, 1.7 as outputs | |
P2DIR = 0x2f; // Set P2.0, 2.1, 2.2, 2.3, 2.5 as outputs | |
P1REN |= 0x07; // resistor enabled for P1.0, 1.1, 1.2 (to act as pull-down) | |
P2REN |= 0x10; // resistor enabled for P2.4 (to act as pull-down) | |
P1IES &= ~0x04; // interrupt on low-to-high transition of P1.2 | |
P1IE |= 0x04; // interrupt enable for P1.2 | |
PWR_DISABLE; // start with the power disabled | |
__bis_SR_register(GIE); // enable interrupts | |
while(1) { | |
// enter a power mode depending on if button detection or clock interrupt is needed | |
if (timer_status) { | |
__bis_SR_register(LPM3_bits); // enter LPM3, clock will be updated | |
} else { | |
__bis_SR_register(LPM3_bits); // don't know why LPM4_bits here doesn't work | |
} | |
process_btn_b(); | |
_NOP(); // set breakpoint here if desired to see operation | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment