简体   繁体   中英

controlling motor speed in MSP430

#include <msp430.h> 

int forward_cnt = 0;
int reverse_cnt = 0;
void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    
    P1DIR |= BIT0;
    P1OUT &= ~BIT0; //LED 1.0
    
    P1REN |= BIT1;
    P1OUT |= BIT1;
    P2REN |= BIT1;
    P2OUT |= BIT1; //switches
    
    P1IE |= BIT1;
    P1IES |= BIT1; //falling edge(when button is pushed)
    P1IFG &= ~BIT1;
    
    P2IE |= BIT1;
    P2IES |= BIT1;
    P2IFG &= ~BIT1;
    
    //PWM Settings
    P2DIR |= (BIT5 | BIT4);
    P2SEL |= (BIT5 | BIT4); //SET TO 1
    
    TA2CTL = TASSEL_2 + MC_1 + TACLR;
    TA2CCR0 = 1000;
    
    TA2CCTL2 = OUTMOD_6;
    TA2CCR2 = 0;
    TA2CCTL1 = OUTMOD_6;
    TA2CCR1 = 0;
    
    __bis_SR_register(GIE);
    
    while(1)
    {
      
    }
}

#pragma vector = PORT2_VECTOR
__interrupt void Port_2_1(void)
{
    
    forward_cnt++;
    switch(forward_cnt % 3){
    
    case 0 : 
        TA2CCR2 = 400;
        TA2CCR1 = 0;
        P1OUT |= BIT0;
    break;
    
    case 1 :
        TA2CCR2 = 800;
        TA2CCR1 = 0;
        P1OUT |= BIT0;
    break;
    
    case 2 : 
        TA2CCR2 = 0;
        TA2CCR1 = 0;
        P1OUT &= ~BIT0;
    break;
    }
    
    P2IFG &= ~BIT1; //interrupt end, so go back with IFG clear
}

#pragma vector = PORT1_VECTOR
__interrupt void Port_1_1(void)
{
    TA2CCR2 = 0;
    TA2CCR1 = 0;
    forward_cnt = 0;
    
    P1IFG &= ~BIT1;
}

I want to control motor speed by slow, fast, stop with clicking switch P2.1(external interrupt) and keep turned on LED when motor is working.

But some problem is coming out. It seems like forward_cnt value is changing while I release button sometimes. It works different while I keep hold on button sometimes.

For example, It should change its speed once when I click button once with my expectation but sometimes it changes its speed when I push, and also changes when I release button. I think interrupt is not working well. How can I fix this clearly?

The interrupt may be working as intended the issue is more likely with the button itself. It seems you are running into the classic switch bouncing problem. When a button is clicked it is not a clean transition from one logic state to the next. Referencing the picture posted below a single press of the button can cause multiple rising and falling edges. Which in the case of your code will cause multiple interrupts to occur changing your forward_cnt variable almost unpredictably.

There are many different solutions to this problem but the most straightforward is to add in a delay after the button is pressed to allow for the bouncing of the switch to settle. After the bouncing has settled you can then increment you forward_cnt variable.

scope capture of button when pressed

Push buttons are noisy by nature, so you need to deal with that. For example, if you were to sample the input pin from the push button, you would find it will toggle many times before settling down on the pressed value. To deal with the noise, you should add a debouce function to the button press event.

The easiest way to do this is as mmeadwell mentioned, which is to add some delay. Normally, a good design would use hardware timer for this, but in a pinch, you can just implement a software delay. For example, in your Port_2_1(void) interrupt routine, add this code:

#pragma vector = PORT2_VECTOR
__interrupt void Port_2_1(void)
{
    // Variable for button state
    int button_now = 0;
    int button_last = 0;
    // Implement a debounce delay for 150 ms
    for (int delay = 0; delay < 150; delay++)
    {
        // Sample the current button state
        button_now = (P2IN & BIT1) ? 1 : 0;
        // Reset delay when state of button changes
        if (button_now != button_last) delay = 0;
        // delay 1 ms (must know your CPU clock rate)
        // using MSP430 compiler intrinsic function
        __delay_cycles(CPU_CLOCKS_PER_US * 1000);
        button_last = button_now;
    }
    // Only continue if button is currently pressed
    if (button_now == 0) return;
    // now process the button press event
    // remaining code is unchanged
    forward_cnt++;
    switch(forward_cnt % 3){

Since the button P1.1 is only used to stop the PWM, then no debounce is necessary. This noise will not change the outcome once stopped.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM