Forum: Mikrocontroller und Digitale Elektronik MSP430 F2012 I2C


von Kempi (Gast)


Lesenswert?

Hallo liebe Leute,
sichergibt es schon einige Einträge über I2C beim MSP430. Leider jedoch 
noch keinen, der meine Frage bezüglich meinem verwendeten Derivat: F2012 
berantworten würde...

Wie das I2C-Protokoll ansich funktioniert, kann man in hunderten von 
tollen Büchern nachlesen. TI hat hier unten "vermutlich" 
super-funktionierende Routienen geschrieben. Mein Problem ist nun 
folgendes. Wie den Wald vor den Bäumen sehe ich nicht die Stelle im 
Quelltext, wo ich hineinschreiben kann, was z.Bsp. der Slave ausführen 
soll wenn der Master ein Daten-Byte geschickt hat. Richtig, es ist mein 
C-Verständnis, welches mich auf dem Schlauch stehen lässt. Gerne würde 
ich in einer Schleife mit Switch/If abfragen, welcher Auftrag ausgeführt 
werden soll. In welches Register wird das Empfangene Byte geschrieben 
und wohin übergebe ich das zu sendende? Ik hoff, dass ihr Versteht was 
ich meine... ;)
Danke im Voraus!

1
//******************************************************************************
2
//  MSP430F20xx Demo - I2C Slave Receiver / Slave Transmitter, multiple bytes
3
//
4
//  Description: I2C Master communicates with I2C Slave using
5
//  the USI. Master data should increment from 0x55 with each transmitted byte.
6
//  ACLK = n/a, MCLK = SMCLK = Calibrated 1MHz
7
//
8
//  ***THIS IS THE SLAVE CODE***
9
//
10
//                  Slave                      Master
11
//                                    (msp430x20x3_usi_12.c)
12
//               MSP430F20x2/3              MSP430F20x2/3
13
//             -----------------          -----------------
14
//         /|\|              XIN|-    /|\|              XIN|-
15
//          | |                 |      | |                 |
16
//          --|RST          XOUT|-     --|RST          XOUT|-
17
//            |                 |        |                 |
18
//      LED <-|P1.0             |        |                 |
19
//            |                 |        |             P1.0|-> LED
20
//            |         SDA/P1.7|------->|P1.6/SDA         |
21
//            |         SCL/P1.6|<-------|P1.7/SCL         |
22
//
23
//  Note: internal pull-ups are used in this example for SDA & SCL
24
//
25
//  R. B. Elliott / H. Grewal
26
//  Texas Instruments Inc.
27
//  February 2008
28
//  Built with IAR Embedded Workbench Version: 3.42A
29
//******************************************************************************
30
31
#include  <msp430x20x3.h>
32
#define Number_of_Bytes  5                  // **** How many bytes?? ****
33
34
void Setup_USI_Slave(void);
35
36
char MST_Data = 0;                          // Variable for received data
37
char SLV_Data = 0x55;
38
char SLV_Addr = 0x90;                       // Address is 0x48<<1 for R/W
39
int I2C_State, Bytecount, transmit = 0;     // State variables
40
41
void Data_RX(void);
42
void TX_Data(void);
43
void main(void)
44
{
45
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog
46
  if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                     
47
  {  
48
    while(1);                               // If calibration constants erased
49
                                            // do not load, trap CPU!!
50
  } 
51
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
52
  DCOCTL = CALDCO_1MHZ;
53
  Setup_USI_Slave();
54
  
55
  LPM0;                                     // CPU off, await USI interrupt
56
  _NOP();
57
}
58
59
//******************************************************************************
60
// USI interrupt service routine
61
// Rx bytes from master: State 2->4->6->8 
62
// Tx bytes to Master: State 2->4->10->12->14
63
//******************************************************************************
64
#pragma vector = USI_VECTOR
65
__interrupt void USI_TXRX (void)
66
{
67
  if (USICTL1 & USISTTIFG)                  // Start entry?
68
  {
69
    P1OUT |= 0x01;                          // LED on: sequence start
70
    I2C_State = 2;                          // Enter 1st state on start
71
  }
72
73
  switch(__even_in_range(I2C_State,14))
74
    {
75
      case 0:                               // Idle, should not get here
76
              break;
77
78
      case 2: // RX Address
79
              USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, RX address
80
              USICTL1 &= ~USISTTIFG;        // Clear start flag
81
              I2C_State = 4;                // Go to next state: check address
82
              break;
83
84
      case 4: // Process Address and send (N)Ack
85
              if (USISRL & 0x01){            // If master read...
86
                SLV_Addr = 0x91;             // Save R/W bit
87
                transmit = 1;}
88
              else{transmit = 0;
89
                  SLV_Addr = 0x90;}
90
              USICTL0 |= USIOE;             // SDA = output
91
              if (USISRL == SLV_Addr)       // Address match?
92
              {
93
                USISRL = 0x00;              // Send Ack
94
                P1OUT &= ~0x01;             // LED off
95
                if (transmit == 0){ 
96
                  I2C_State = 6;}           // Go to next state: RX data
97
                if (transmit == 1){  
98
                  I2C_State = 10;}          // Else go to next state: TX data
99
              }
100
              else
101
              {
102
                USISRL = 0xFF;              // Send NAck
103
                P1OUT |= 0x01;              // LED on: error
104
                I2C_State = 8;              // next state: prep for next Start
105
              }
106
              USICNT |= 0x01;               // Bit counter = 1, send (N)Ack bit
107
              break;
108
109
    case 6: // Receive data byte
110
              Data_RX();
111
              break;  
112
113
      case 8:// Check Data & TX (N)Ack
114
              USICTL0 |= USIOE;             // SDA = output
115
              if (Bytecount <= (Number_of_Bytes-2))          
116
                                            // If not last byte
117
              {
118
                USISRL = 0x00;              // Send Ack
119
                I2C_State = 6;              // Rcv another byte
120
                Bytecount++;
121
                USICNT |= 0x01;             // Bit counter = 1, send (N)Ack bit
122
              }
123
              else                          // Last Byte
124
              {
125
                USISRL = 0xFF;              // Send NAck
126
              USICTL0 &= ~USIOE;            // SDA = input
127
              SLV_Addr = 0x90;              // Reset slave address
128
              I2C_State = 0;                // Reset state machine
129
              Bytecount =0;                 // Reset counter for next TX/RX
130
              }
131
              
132
              
133
              break;
134
135
     case 10: // Send Data byte
136
              TX_Data();
137
              break;
138
139
      case 12:// Receive Data (N)Ack
140
              USICTL0 &= ~USIOE;            // SDA = input
141
              USICNT |= 0x01;               // Bit counter = 1, receive (N)Ack
142
              I2C_State = 14;               // Go to next state: check (N)Ack
143
              break;
144
145
      case 14:// Process Data Ack/NAck
146
           if (USISRL & 0x01)               // If Nack received...
147
              {
148
              USICTL0 &= ~USIOE;            // SDA = input
149
              SLV_Addr = 0x90;              // Reset slave address
150
              I2C_State = 0;                // Reset state machine
151
               Bytecount = 0;
152
             // LPM0_EXIT;                  // Exit active for next transfer
153
              }
154
              else                          // Ack received
155
              {
156
                P1OUT &= ~0x01;             // LED off
157
                TX_Data();                  // TX next byte
158
               }
159
         break;
160
    
161
      }
162
  USICTL1 &= ~USIIFG;                       // Clear pending flags
163
}
164
165
void Data_RX(void){
166
  
167
              USICTL0 &= ~USIOE;            // SDA = input
168
              USICNT |=  0x08;              // Bit counter = 8, RX data
169
              I2C_State = 8;                // next state: Test data and (N)Ack
170
}
171
172
void TX_Data(void){
173
              USICTL0 |= USIOE;             // SDA = output
174
              USISRL = SLV_Data++;
175
              USICNT |=  0x08;              // Bit counter = 8, TX data
176
              I2C_State = 12;               // Go to next state: receive (N)Ack
177
}
178
179
void Setup_USI_Slave(void){
180
  P1OUT = 0xC0;                             // P1.6 & P1.7 Pullups
181
  P1REN |= 0xC0;                            // P1.6 & P1.7 Pullups
182
  P1DIR = 0xFF;                             // Unused pins as outputs
183
  P2OUT = 0;
184
  P2DIR = 0xFF;
185
  
186
  USICTL0 = USIPE6+USIPE7+USISWRST;         // Port & USI mode setup
187
  USICTL1 = USII2C+USIIE+USISTTIE;          // Enable I2C mode & USI interrupts
188
  USICKCTL = USICKPL;                       // Setup clock polarity
189
  USICNT |= USIIFGCC;                       // Disable automatic clear control
190
  USICTL0 &= ~USISWRST;                     // Enable USI
191
  USICTL1 &= ~USIIFG;                       // Clear pending flag
192
  
193
  transmit = 0;
194
  _EINT();
195
196
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.