The Rusty Spike

A Railroad Fan's Website

By

Example Use #1 Of The LP4MRR.h Header File

As I have been working with the TI Launchpad and MSP430G2 series of microcontrollers, I have been slowly creating a set of macros and functions that make programming the Launchpad easier. The header file for this is available here, but I wanted to create a simple example of how and why it’s useful.

Drawing upon the example by TI about using a 74HC595 ShiftRegister, we see that in order to have the LEDs perform this pingpong effect:

Bit Shift Register on TI Launchpad from claymore1977 on Vimeo.

we must use this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//***************************************************************************************
// MSP430 Driver for 74HC595 Shift Register
//
// Description; Drives 8 LED's with 3 digital pins of the MSP430, via a shift register
//
// MSP430x2xx
//
//***************************************************************************************
#include <msp430x20x2.h>
 
//Define our pins 
#define DATA BIT0 // DS -> 1.0
#define CLOCK BIT4 // SH_CP -> 1.4
#define LATCH BIT5 // ST_CP -> 1.5
 
// Declare functions
void delay ( unsigned int );
void pulseClock ( void );
void shiftOut ( unsigned char );
void init ( void );
void pinWrite ( unsigned int, unsigned char );
 
 
int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD; 
  P1DIR |= (DATA + CLOCK + LATCH);  // Setup pins as outputs
  enable(); // Enable output (pull OE low)
 
  int i;
  //Do a "ping-pong" effect back and forth
  for(;;){
    for ( i = 0 ; i < 8 ; i++ ){
      shiftOut(1 << i);
      delay(50); 
    }
    for ( i = 7 ; i >= 0 ; i-- ){
      shiftOut(1 << i);
      delay(50);
    }
  }
}
 
// Delays by the specified Milliseconds
// thanks to:
// http://www.threadabort.com/archive/2010/09/05/msp430-delay-function-like-the-arduino.aspx
void delay(unsigned int ms)
{
 while (ms--)
    {
        __delay_cycles(1000); // set for 16Mhz change it to 1000 for 1 Mhz
    }
}
 
// Writes a value to the specified bitmask/pin. Use built in defines
// when calling this, as the shiftOut() function does.
// All nonzero values are treated as "high" and zero is "low"
void pinWrite( unsigned int bit, unsigned char val )
{
  if (val){
    P1OUT |= bit;
  } else {
    P1OUT &= ~bit;
  }
}
 
// Pulse the clock pin
void pulseClock( void )
{
  P1OUT |= CLOCK;
  P1OUT ^= CLOCK;
 
}
 
// Take the given 8-bit value and shift it out, LSB to MSB
void shiftOut(unsigned char val)
{
  //Set latch to low (should be already)
  P1OUT &= ~LATCH;
 
  char i;
 
  // Iterate over each bit, set data pin, and pulse the clock to send it
  // to the shift register
  for (i = 0; i < 8; i++)  {
      pinWrite(DATA, (val & (1 << i)));
      pulseClock();
  }
 
  // Pulse the latch pin to write the values into the storage register
  P1OUT |= LATCH;
  P1OUT &= ~LATCH;
}

However, the desire to reduce that code to something much more manageable and easier to read led me to the creation of some ShiftRegister related C Macros. I included them into version 1.1 of the LP4MRR Header file. Using these macros from the LP4MRR header results in the code below. It is 100% functionally equivalent to the TI example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/******************************************
 * MSP430 Driver for 74HC595 Shift Register using LP4MRR
 *
 * COPYRIGHT 2013 Dave Loman
 *
 * Provided  under a:
 *    Creative Commons Attribution,
 *    Non-Commercial
 *    Share-Alike,
 *    3.0 Unported License
 *
 ******************************************/
#include <msp430x20x2.h>
#include "lp4mrr.h"
 
/* Define our pins */
#define DATA BIT0  // DS    -> 1.0
#define LATCH BIT4 // ST_CP -> 1.4
#define CLOCK BIT5 // SH_CP -> 1.5
 
int main(void) {
	DISABLE_WATCHDOG();
	P1_DIR_OUT(DATA);
	P1_DIR_OUT(CLOCK);
	P1_DIR_OUT(LATCH);
 
	char i = 0;
	//Do a "ping-pong" effect back and forth
	for (;;) {
		i = 0;
		for (i = 0; i < 8; ++i) {
			P1_SHIFT_OUT_8((1 << i), LATCH, CLOCK, DATA);
			DELAY_MS(50);
		}
		for (i = 8; i > 0; --i) {
			P1_SHIFT_OUT_8((1 << (i-1)), LATCH, CLOCK, DATA);
			DELAY_MS(50);
		}
	}
}

The reduction is pretty drastic: the lines of code are cut in half. If you exclude the comments and extra line returns, the reduction is even more profound. Personally, I can read the LP4MRR version much easier. (Of course, I wrote the darn thing, so my vote doesn’t count. 🙂 )

Leave a Reply

Your email address will not be published. Required fields are marked *