msp430f2013 I2C frustrations

display

UPDATE: See this post which shows how I finally got it working.

I’ve been trying to get a ST7032i based display working with a msp430f2013 on a EZ430-F2013. Unfortunately without much success. After hours of debugging I discovered that the glass on the display was fractured… guess I’ll be ordering some more.

Anyway, it did get as far as acknowledging my commands. And I found a working I2C sample. It was hidden pretty well on the TI site, I think in a zip called slac080l.zip. The file I was working from was msp430x20x3_usi_07.c. My hacked version is reproduced below, you can almost feel the frustration I’m sure (it’s an absolute mess). But it does work with the MSP430GCC compiler, and produce working I2C output.

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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/* --COPYRIGHT--,BSD_EX
 * Copyright (c) 2012, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *******************************************************************************
 *
 *                       MSP430 CODE EXAMPLE DISCLAIMER
 *
 * MSP430 code examples are self-contained low-level programs that typically
 * demonstrate a single peripheral function or device feature in a highly
 * concise manner. For this the code may rely on the device's power-on default
 * register values and settings such as the clock configuration and care must
 * be taken when combining code from several examples to avoid potential side
 * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
 * for an API functional library-approach to peripheral configuration.
 *
 * --/COPYRIGHT--*/
//******************************************************************************
//  MSP430F20xx Demo - I2C Master Transmitter, single byte
//
//  Description: I2C Master communicates with I2C Slave using
//  the USI. Master data is sent and increments from 0x00 with each transmitted
//  byte which is verified by the slave.
//  LED off for address or data Ack; LED on for address or data NAck.
//  ACLK = n/a, MCLK = SMCLK = Calibrated 1MHz
//
//  ***THIS IS THE MASTER CODE***
//
//                  Slave                      Master
//          (msp430x20x3_usi_08.c)
//               MSP430F20x2/3              MSP430F20x2/3
//             -----------------          -----------------
//         /|\|              XIN|-    /|\|              XIN|-
//          | |                 |      | |                 |
//          --|RST          XOUT|-     --|RST          XOUT|-
//            |                 |        |                 |
//      LED <-|P1.0             |        |                 |
//            |                 |        |             P1.0|-> LED
//            |         SDA/P1.7|<-------|P1.7/SDA         |
//            |         SCL/P1.6|<-------|P1.6/SCL         |
//
//  Note: internal pull-ups are used in this example for SDA & SCL
//
//  Z. Albus
//  Texas Instruments Inc.
//  May 2006
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.41A
//******************************************************************************
#include <msp430.h>
 
 
// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
#define LCD_EX_SETBIASOSC 0x10 // Bias selection / Internal OSC frequency adjust
#define LCD_EX_SETICONRAMADDR 0x40 // Set ICON RAM address
#define LCD_EX_POWICONCONTRASTH 0x50 // Power / ICON control / Contrast set(high byte)
#define LCD_EX_FOLLOWERCONTROL 0x60 // Follower control
#define LCD_EX_CONTRASTSETL 0x70 // Contrast set(low byte)
// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00
// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00
// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
#define LCD_EX_INSTRUCTION 0x01 // IS: instruction table select
// flags for Bias selection
#define LCD_BIAS_1_4 0x08 // bias will be 1/4
#define LCD_BIAS_1_5 0x00 // bias will be 1/5
// flags Power / ICON control / Contrast set(high byte)
#define LCD_ICON_ON 0x08 // ICON display on
#define LCD_ICON_OFF 0x00 // ICON display off
#define LCD_BOOST_ON 0x04 // booster circuit is turn on
#define LCD_BOOST_OFF 0x00 // booster circuit is turn off
#define LCD_OSC_122HZ 0x00 // 122Hz@3.0V
#define LCD_OSC_131HZ 0x01 // 131Hz@3.0V
#define LCD_OSC_144HZ 0x02 // 144Hz@3.0V
#define LCD_OSC_161HZ 0x03 // 161Hz@3.0V
#define LCD_OSC_183HZ 0x04 // 183Hz@3.0V
#define LCD_OSC_221HZ 0x05 // 221Hz@3.0V
#define LCD_OSC_274HZ 0x06 // 274Hz@3.0V
#define LCD_OSC_347HZ 0x07 // 347Hz@3.0V
// flags Follower control
#define LCD_FOLLOWER_ON 0x08 // internal follower circuit is turn on
#define LCD_FOLLOWER_OFF 0x00 // internal follower circuit is turn off
#define LCD_RAB_1_00 0x00 // 1+(Rb/Ra)=1.00
#define LCD_RAB_1_25 0x01 // 1+(Rb/Ra)=1.25
#define LCD_RAB_1_50 0x02 // 1+(Rb/Ra)=1.50
#define LCD_RAB_1_80 0x03 // 1+(Rb/Ra)=1.80
#define LCD_RAB_2_00 0x04 // 1+(Rb/Ra)=2.00
#define LCD_RAB_2_50 0x05 // 1+(Rb/Ra)=2.50
#define LCD_RAB_3_00 0x06 // 1+(Rb/Ra)=3.00
#define LCD_RAB_3_75 0x07 // 1+(Rb/Ra)=3.75
 
 
 
char MST_Data = 0x40;                     // Variable for transmitted data
char SLV_Addr = 0x7C;                  // Address is 0x48 << 1 bit + 0 for Write
int I2C_State = 0;                     // State variable
 
int main(void)
{
  volatile unsigned int i;             // Use volatile to prevent removal
 
  WDTCTL = WDTPW + WDTHOLD;            // Stop watchdog
                __delay_cycles(250000);
  if (CALBC1_1MHZ==0xFF)         // If calibration constants erased
  {                    
    while(1);                          // do not load, trap CPU!!
  }
  DCOCTL = 0;                               // Select lowest DCOx and MODx settings
  BCSCTL1 = CALBC1_1MHZ;               // Set DCO
  DCOCTL = CALDCO_1MHZ;
 
  P1OUT = 0xC0;                        // P1.6 & P1.7 Pullups, others to 0
  P1REN |= 0xC0;                       // P1.6 & P1.7 Pullups
  P1DIR = 0xFF;                        // Unused pins as outputs
  P2OUT = 0;
  P2DIR = 0xFF;
 
  USICTL0 = USIPE6+USIPE7+USIMST+USISWRST; // Port & USI mode setup
  USICTL1 = USII2C+USIIE;              // Enable I2C mode & USI interrupt
  USICKCTL = USIDIV_3+USISSEL_2+USICKPL; // Setup USI clocks: SCL = SMCLK/8 (~125kHz) // was USIDIV_3
  USICNT |= USIIFGCC;                  // Disable automatic clear control
  USICTL0 &= ~USISWRST;                // Enable USI
  USICTL1 &= ~USIIFG;                  // Clear pending flag
  __enable_interrupt();
 
  int a=0;
  for(int n=0;;n++)
  {
    if(n==0) MST_Data = 0x00;
    if(n==1) MST_Data = LCD_EX_SETBIASOSC | LCD_BIAS_1_5 | LCD_OSC_183HZ;
    if(n==2) MST_Data = 0x00;
    if(n==3) MST_Data = LCD_EX_FOLLOWERCONTROL | LCD_FOLLOWER_ON | LCD_RAB_2_00;
    if(n==4) MST_Data = 0x00;
    if(n==5) MST_Data = LCD_DISPLAYON | LCD_CURSORON | LCD_BLINKON;
    if(n==6) MST_Data = 0x00;
    if(n==7) MST_Data = LCD_ENTRYMODESET | LCD_ENTRYLEFT;
 
    if(n==9) MST_Data = 0x00;
    if(n==10) MST_Data = LCD_EX_CONTRASTSETL | (0x0c & 0x0f);
    if(n==11) MST_Data = 0x00;
    if(n==12) MST_Data = LCD_EX_POWICONCONTRASTH | LCD_ICON_ON | LCD_BOOST_ON | ((0x0c >> 4) & 0x03);
    if(n==14) MST_Data = 0x00;
    if(n==15) MST_Data = LCD_CLEARDISPLAY;
    if(n==16) MST_Data = 0x00;
    if(n==17) MST_Data = 0x40;
    if(n==18) MST_Data = 'a'+a;
    USICTL1 |= USIIFG;                 // Set flag and start communication
    LPM0;                              // CPU off, await USI interrupt
   // __no_operation();                  // Used for IAR
//    for (i = 0; i < 5000; i++);        // Dummy delay between communication cycles
    P1OUT &= ~0x01;           // LED off
    __delay_cycles(500000);
    if(n==18)n=16;
    a++;
  }
}
 
/******************************************************
// USI interrupt service routine
******************************************************/
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USI_VECTOR
__interrupt void USI_TXRX (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USI_VECTOR))) USI_TXRX (void)
#else
#error Compiler not supported!
#endif
{
  switch(I2C_State)
    {
      case 0: // Generate Start Condition & send address to slave
              P1OUT &= ~0x01;           // LED off
              USISRL = 0x00;           // Generate Start Condition...
              USICTL0 |= USIGE+USIOE;
              USICTL0 &= ~USIGE;
              USISRL = SLV_Addr;       // ... and transmit address, R/W = 0
              USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, TX Address
              I2C_State = 2;           // Go to next state: receive address (N)Ack
              break;
 
      case 2: // Receive Address Ack/Nack bit
              USICTL0 &= ~USIOE;       // SDA = input
              USICNT |= 0x01;          // Bit counter = 1, receive (N)Ack bit
              I2C_State = 4;           // Go to next state: check (N)Ack
              break;
 
      case 4: // Process Address Ack/Nack & handle data TX
              USICTL0 |= USIOE;        // SDA = output
              if (USISRL & 0x01)       // If Nack received...
              { // Send stop...
                USISRL = 0x00;
                USICNT |=  0x01;       // Bit counter = 1, SCL high, SDA low
                I2C_State = 10;        // Go to next state: generate Stop
              //  P1OUT |= 0x01;         // Turn on LED: error
                P1OUT |= 0x01;         // Turn on LED: error
                __delay_cycles(5000000);
              }
              else
              { // Ack received, TX data to slave...
                USISRL = MST_Data;     // Load data byte
                USICNT |=  0x08;       // Bit counter = 8, start TX
                I2C_State = 6;         // Go to next state: receive data (N)Ack
                P1OUT &= ~0x01;        // Turn off LED
              }
              break;
 
      case 6: // Receive Data Ack/Nack bit
              USICTL0 &= ~USIOE;       // SDA = input
              USICNT |= 0x01;          // Bit counter = 1, receive (N)Ack bit
              I2C_State = 8;           // Go to next state: check (N)Ack
              break;
 
      case 8: // Process Data Ack/Nack & send Stop
              USICTL0 |= USIOE;
              if (USISRL & 0x01)       // If Nack received...
              ;//  P1OUT |= 0x01;         // Turn on LED: error
              else                     // Ack received
              {
                MST_Data++;            // Increment Master data
              //  P1OUT &= ~0x01;        // Turn off LED
              }
              // Send stop...
              USISRL = 0x00;
              USICNT |=  0x01;         // Bit counter = 1, SCL high, SDA low
              I2C_State = 10;          // Go to next state: generate Stop
              break;
 
      case 10:// Generate Stop Condition
              USISRL = 0x0FF;          // USISRL = 1 to release SDA
              USICTL0 |= USIGE;        // Transparent latch enabled
              USICTL0 &= ~(USIGE+USIOE);// Latch/SDA output disabled
              I2C_State = 0;           // Reset state machine for next transmission
              LPM0_EXIT;               // Exit active for next transfer
              break;
    }
 
  USICTL1 &= ~USIIFG;                  // Clear pending flag
}

Comments are closed.