MSP430, learning to program and debug hardware (part 2)


    Hello, dear Habrauser.
    In a previous article, we began to consider programming under the MSP430.
    The material described in this article will provide an overview of interruptions and some of the intricacies of the MSP430.


    Introduction


    Interruption (English interrupt) - a signal that informs the processor about the occurrence of an event. In this case, the execution of the current sequence of commands is suspended and control is transferred to the interrupt handler, which responds to the event and serves it, after which it returns control to the interrupted code.
    The interrupt mechanism is designed to provide the most rapid response of the program to certain events. This is a very important part of getting to know any microcontroller.

    Interruptions


    Let's start with a small example.
    1. #include "msp430f2274.h"
    2.  
    3. void main ()
    4. {
    5.   WDTCTL = WDTPW + WDTHOLD;
    6.  
    7.   P1DIR & = ~ BIT2;
    8.   P1REN | = BIT2;
    9.  
    10.   P1IE | = BIT2; // Enable interrupts on P1.2
    11.   P1IES | = BIT2; // Interrupt occurs at 1/0 (release / press)
    12.   P1IFG & = ~ BIT2; // Clear interrupt flag for P1.2
    13.  
    14.   P1DIR | = BIT0 + BIT1;
    15.   P1OUT | = BIT0;
    16.   P1OUT & = ~ BIT1;
    17.   __bis_SR_register (GIE); // Set the flag for global interrupt resolution
    18.  
    19.   while (true);
    20. }
    21.  
    22. #pragma vector = PORT1_VECTOR
    23. __interrupt void P1INT () // Interrupt Handler
    24. {
    25.   P1IE & = ~ BIT2; // Disable interrupts on P1.2
    26.  
    27.   P1OUT ^ = BIT0; // P1.0 changes its state
    28.   P1OUT ^ = BIT1; // P1.1 changes its state
    29.  
    30.   for (volatile unsigned int i = 30000; i! = 0; i--); // Delay
    31.   P1IE | = BIT2; // Enable interrupts on P1.2
    32.   P1IFG & = ~ BIT2; // Clear interrupt flag for P1.2
    33. }
    34.  

    In this example, by pressing the button (P1.2), an interrupt occurs, which changes the state of two LEDs (P1.0 and P1.1). Let's see how this happens.

    PxIE enables interrupts for Px port pins. The value "1" written to a specific bit allows you to receive interrupts from a specific pin.

    PxIES determines at what signal level an interrupt will occur. In our case, this means that a unit placed in a specific category of this register will allow you to receive a button press event. Conversely, zero allows you to receive a button release event.
    Let me remind you that the button in this example is “pulled up” to one, which means that the pressed button has a value of zero.
    On the connection diagram, the resistor R1 is drawn illustratively, in fact, it is located inside the microcontroller and is turned on by the P1REN register.

    PxIFG is the interrupt flag. In the event of a button click event, it will be set to one, which will call the interrupt handler (__interrupt void P1INT ()). Accordingly, immediately after processing the event, the flag must be reset.
    Try to remove line 32 from the example at the end of the handler, and then, immediately after the first press of the button, the bulbs will switch as if you constantly press the button.

    __bis_SR_register (GIE)sets the Global Interrupt Enable flag to status register. In fact, this is equivalent to writing SR | = GIE, but we can only access the SR register using the __bis_SR_register and __get_SR_register functions.
    Below is the bit pattern in the SR register.

    0, 1, 2, and 8 bits are bits of mathematical operations.
    4, 5, 6, 7 - bits to control energy consumption levels, by reducing the frequency or turning off the ALU.
    Well, actually bit 3 is a global interrupt resolution. Until this bit is set to one, no interrupt will be processed.

    #pragma vector is a directive that determines that the following function is the handler for the specified interrupt.
    A list of all available interrupt vectors can be found in the header file for your controller. In this case, it is msp430f2274.h .

    Contact bounce


    You can read about this phenomenon in detail on Wikipedia . Contact bounce occurs when a button is pressed, so the interrupt handler will be called repeatedly. In this example, this was avoided as follows:
    1. Immediately after calling the handler, the interrupt ban is set (line 25);
    2. after switching the LEDs, a delay is made (line 30);
    3. interrupt resolution is set again (line 31).

    The volatile directive in line 30 of the code means that the variable i will not be optimized during compilation. If you remove it, then there will be no delay.

    Conclusion


    After reading the previous article, colleagues and friends reproached me for not paying enough attention to details. This time I tried to correct this shortcoming and make the article material even more accessible. However, this significantly increased the amount of information.
    Next time I will try to consider the transfer of data from the controller to a personal computer using the programmer and, depending on the amount received, watchdog.

    I hope this article has been helpful to you, reader.

    Also popular now: