Programming Digital I/O

Configuring a Pin as Output and Driving It

If the processor is driving a pin and sending signals to it, then the pin has to be configured as an output. The example we have seen so far is a pin connected to an LED. According to Table 12-1, in such cases, we need to set the direction bit to 1. The important thing here is that to only affect the direction bit corresponding to the pin we are interested in. Let’s take LED1, which is connected to P1.0. We need to set PyDIR.x to 1 without affecting the other bits in the register. Since y corresponds to the port number and x corresponds to the pin, we’re looking at modifying Bit 0 of P1DIR. Given the condition that we must set Bit 0 to 1 without modifying the other bits in the register, a bitmask can get the job done. Creating a bitmask for Bit 0 (let’s call it BIT0) and bitwise ORing it with P1DIR (in other words, P1DIR = P1DIR | BIT0) will accomplish the task, setting Bit 0 of P1DIR to 1 without changing Bits 1 through 7. With the direction configured, we can now turn LED1 on or off by manipulating Bit 0 of P1OUT (again, using bitmasks).

// LED1 is connected to P1.0 

// Therefore, bit 0 of P1DIR register should be set to 1

P1DIR = P1DIR | BIT0;

// To turn on LED1, bit 0 of P1OUT should be set to 1

P1OUT = P1OUT | BIT0;

// To turn off LED 1, bit 0 of P1OUT should be reset to 0

P1OUT = P1OUT & ~BIT0;

// To toggle LED1, bit 0 of P1OUT should be toggled

P1OUT = P1OUT ^ BIT0;

LED2 follows a similar story. To enable all three colors as outputs, Bits 0, 1, and 2 of P2DIR need to be set to 1. Once again, using bitmasks for the three bits (let’s call them BIT0, BIT1, and BIT2, respectively) and bitwise ORing them with P2DIR (P2DIR = P2DIR | (BIT0 | BIT1 | BIT2)) will configure the three colors as outputs. Each color can be activated or deactivated by manipulating the respective bit. Red is mapped to P2.0, so red corresponds to Bit 0, green is mapped to P2.1 thus it corresponds to Bit 1, and blue is mapped to P2.2 thus it corresponds to Bit 2. Suppose you wanted to produce a yellow color with LED2. You’ll need to turn on (1) the red and green lights while keeping the blue one off (0). To accomplish this, we bitwise OR P2OUT with the bitmasks for Bits 0 and 1, then bitwise AND the result with the complement of Bit 2’s bitmask (P2OUT = (P2OUT | (BIT0 | BIT1)) & ~BIT2). 


Configuring a Pin as Input and Reading It

Configuring a pin as input is somewhat more complicated. The reason is that in addition to the direction register, we need to configure the pull resistor and its type if needed. Consider S2 button on the Launchpad which is wired to P1.4 pin. This means it is connected to Port 1 and all its registers, but only Bit 4 is dedicated to this button. 

// S2 is connected to P1.4 

// Therefore, bit 4 of P1DIR register should be reset to 0

P1DIR = P1DIR & ~BIT4;


// To enable the pull resistor we should set the bit 4 of P1REN to 1

P1REN = P1REN | BIT4;


// To make the pull resistor a pull-up, we need to set the bit 4 of P1OUT to 1

P1OUT = P1OUT | BIT4;


// To read the status of S2, we need to check bit 4 of P1IN

// masking all other bits leaves a value that it is either zero, or non-zero. 

int status = P1IN & BIT4;


// If status is zero, it means S2 reading is 0; and if the status is non-zero, it means the S2 reading is 1. This is because all other bits are zeroed by masking.

if (status)

   do_something();

  

Putting It Together

The following program uses the concepts described above and builds a simple program. In this project, pressing the button 1 turns LED1 on the Launchpad on and releasing it turns it off.



#include <ti/devices/msp432p4xx/driverlib/driverlib.h>


#define BUTTON1 0b00000010

#define LED1 0b00000001



// This function initializes all the peripherals

void initialize();


int main(void)

{


    initialize();


    while (1) {

     //if the button1 is pressed,

     if  ((P1IN & BUTTON1) == 0)

         //  turn the LED1 on

         P1OUT |= LED1;

     else

         // Otherwise, turn it off

         P1OUT &= ~LED1;

    }

}


void initialize()

{


    // step 1: Stop watchdog timer

    WDT_A_hold(WDT_A_BASE);


    // step 2: Initializing LED1

    P1DIR = P1DIR | LED1;

  

    // step 3: Initializing S1 (switch 1 or button 1)

    P1DIR = P1DIR & ~BUTTON1;

    P1REN |= BUTTON1;

    P1OUT |= BUTTON1;


}