I just started playing with TI’s MSP430 LaunchPad (MSP-EXP430G2) a few weeks ago and have found it surprisingly capable so far. But having to remember all those register names is not an easy task, especially if you do not use it often. So, inspired by this article (Header file brings Arduino sketches to the TI Launchpad) on Hack A Day, I decided to write a few functions that can simplify some of the more mundane tasks.

Here are some of the most used functions I have come up so far. Even though these functions were written specifically for the MSP430G2231 chip I have at hand, they can work with any MSP430G2 value line chips that support the specified functionality.

Here is the code listing for MSP430G2231Library.h (compiled using TI’s Code Composer Studio 5.1):

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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#ifndef MSP430G2231LIBRARY_H_
#define MSP430G2231LIBRARY_H_
 
#include <msp430.h>
 
#define HIGH 1
#define LOW  0
#define OUTPUT 1
#define INPUT 0
 
#define REF_INT_1_5 0
#define REF_INT_2_5 1
#define REF_EXT_VCC 2
 
/**
 * Stop the Watch Dog Timer
 */
void inline stopWatchDogTimer() {
    WDTCTL = WDTPW + WDTHOLD;
}
 
/**
 * Initialize DCO to the calibrated 1Mhz
 */
void inline initDCO1Mhz() {
    BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0;
 
    if (CALBC1_1MHZ != 0xFF) {
        DCOCTL = 0x00;
        BCSCTL1 = CALBC1_1MHZ;
        DCOCTL = CALDCO_1MHZ;
    }
 
    BCSCTL1 |= XT2OFF + DIVA_0;
    BCSCTL3 = XT2S_0 + LFXT1S_0 + XCAP_1;
}
 
/**
 * Initialize DCO according to DCO and RSEL
 * Example: DCO = DCO1 + DCO2 + DCO3
 *          RSEL= RSEL0 + RSEL1 + RSEL2 + RSEL3
 */
void inline initDCO(int DCO, int RSEL) {
    DCOCTL = DCO;
    BCSCTL1 = XT2OFF + DIVA_0 + RSEL;
    BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0;
    BCSCTL3 = XT2S_0 + LFXT1S_0 + XCAP_1;
}
 
/**
 * Initialize the external crystal oscillator
 * (32768 Hz)
 */
void inline initCrystalOSC() {
    BCSCTL2 = SELM_3 + DIVM_0 + SELS + DIVS_0;
    BCSCTL1 = XT2OFF + DIVA_0;
    BCSCTL3 = XT2S_0 + LFXT1S_0 + XCAP_1;
}
 
/**
 * Set the pin mode
 * portNo: port (1 or 2)
 * pinNo: pin number in the port specified
 * pinMode: INPUT/OUTPUT
 */
void pinMode(int portNo, int pinNo, int pinMode) {
    if (portNo == 1) {
        if (pinMode)
            P1DIR |= (1 << pinNo);
        else
            P1DIR &= ~(1 << pinNo);
    } else if (portNo == 2) {
        if (pinMode)
            P2DIR |= (1 << pinNo);
        else
            P2DIR &= ~(1 << pinNo);
    }
}
 
/**
 * Write HIGH or LOW to a pin previously set as output
 * portNo: port (1 or 2)
 * pinNo: pin number in the port specified
 * value: HIGH/LOW
 */
void digitalWrite(int portNo, int pinNo, int value) {
    if (portNo == 1) {
        if (value)
            P1OUT |= 1 << pinNo;
        else
            P1OUT &= ~(1 << pinNo);
    } else if (portNo == 2) {
        if (value)
            P2OUT |= 1 << pinNo;
        else
            P2OUT &= ~(1 << pinNo);
    }
}
 
/**
 * Read logic level from pin
 * portNo: port (1 or 2)
 * pinNo: pin number in the port specified
 */
int digitalRead(int portNo, int pinNo) {
    int result;
 
    result = 0;
 
    if (portNo == 1) {
        result = (P1IN & (1 << pinNo)) >> pinNo;
    } else if (portNo == 2) {
        result = (P2IN & (1 << pinNo)) >> pinNo;
    }
 
    return result;
}
 
/**
 * Initialize ADC10 for continues sampling
 * referenceType: REF_INT_1_5, REF_INT_2_5 or REF_EXT_VCC
 * ADCPin: the pin number for ADC operations
 */
void initADC10(int referenceType, int ADCPin) {
    int refType, refSelect;
 
    if (referenceType == REF_INT_2_5) {
        refType = REF2_5V;
        refSelect = SREF_1;
    } else if (referenceType == REF_INT_1_5) {
        refType = 0;
        refSelect = SREF_1;
    } else if (referenceType == REF_EXT_VCC) {
        refType = 0;
        refSelect = SREF_0;
    }
 
    ADC10CTL0 &= ~ENC;
    ADC10CTL0 = ADC10ON + REFON + refType + ADC10SHT_0 + refSelect;
    ADC10CTL1 = CONSEQ_2 + ADC10SSEL_0 + ADC10DIV_0 + SHS_0 + ADCPin * 0x1000u;
    ADC10AE0 = 0x2;
    __delay_cycles(30000);
    ADC10CTL0 |= ENC;
}
 
/**
 * Get the ADC result from ADCPin defined in
 * initADC10.
 */
int readADC() {
    int t;
 
    ADC10CTL0 |= ENC + ADC10SC;
    while ((ADC10CTL0 & ADC10IFG) == 0);
    t = ADC10MEM;
 
    ADC10CTL0 &= ~ADC10SC;
    ADC10CTL0 |= ADC10IFG;
 
    return t;
}
#endif /* MSP430G2231LIBRARY_H_ */

The code above includes DCO/Crystal initialization routines. It also includes a few Arduino like functions (pinMode, digitalRead and digitalWrite). But I decided to go with the Port.Bit format instead of just a pin number since the Port.Bit information is printed on the launchpad itself and it is easier to reference that way. Finally, I included a couple of ADC routines that work with both the internal and external voltage references. The ADC routines shown above handles only one channel at a time for the time being.

I am planning on expanding this code to include more features in the near future.

Be Sociable, Share!