Forum: Mikrocontroller und Digitale Elektronik MSP430 I2C Senden und Empfangen Problem


von MSPler (Gast)


Lesenswert?

Hallo zusammen,

ich sitze nun seit Tagen an folgendem Problem:

-- Ich habe das I2C Modul im MSP430FR5729 konfiguriert
-- Ich kann ein Byte Senden und zwei Byte empfangen.

ABER: Das kann ich nur getrennt voneinander. Sobald ich den Code wie 
unten schreibe (erste ein Byte senden,
danach nur noch empfangen) wird vom Slave ein NACK gesendet und die 
Kommunkation bricht ab.

Ich habe schon diverse Taktraten ausprobiert, Delays eingebaut, etc. 
aber ohne Erfolg.

Hat Jemand schon mal mit einem ähnlichen Problem zu tun gehabt?

Viele Grüße,
MSPler
1
#include <msp430.h>
2
#include "init.h"
3
4
unsigned char *pTXData         = 0x0;      // Pointer to TX data
5
unsigned char TXByteCounter    = 0;
6
unsigned char *pRXData         = 0x0;      // Pointer to RX data
7
unsigned char RXByteCounter    = 0;
8
volatile unsigned int TEMP     = 0;
9
volatile float celsius         = 0;
10
11
void receive();
12
void transmit();
13
void i2c_master_receiver();
14
void i2c_master_transmitter()
15
16
int main(void)
17
{
18
  msp430fr5729_ports();
19
  msp430fr5729_clock();
20
21
  //Transmit
22
  i2c_master_transmitter();
23
  __enable_interrupt();
24
  transmit();
25
26
  //Receive
27
  __disable_interrupt();
28
  i2c_master_receiver();
29
  __enable_interrupt();
30
31
32
33
    while(1)
34
    {
35
      receive();
36
    }
37
38
}
39
40
41
//===================================================================================//
42
// ISR2: USCIB0_ISR
43
//===================================================================================//
44
#pragma vector = USCI_B0_VECTOR
45
__interrupt void USCIB0_ISR(void)
46
{
47
  switch(__even_in_range(UCB0IV,12))
48
  {
49
        case 0x04:
50
              UCB0CTLW0 |= UCTXSTT;                   // Resend start if NACK
51
              break;                                  // Vector 4: NACKIFG break;
52
        case 0x16:
53
               RXByteCounter--;                          // Decrement RX byte counter
54
55
               if (RXByteCounter)
56
               {
57
                 *pRXData++= UCB0RXBUF;                // Multiple bytes left to receive
58
               }
59
               else
60
               {
61
                 *pRXData= UCB0RXBUF;                  // Last byte to be received
62
                 __bic_SR_register_on_exit(LPM0_bits);    // Exit LPM0
63
                 RXFlag = FLAG_SUCCESS;          // Set Data Received RX Flag to success
64
               }
65
66
               if(RXByteCounter == 1)                   // Only one byte left?
67
                  UCB0CTL1 |= UCTXSTP;                    // Generate I2C stop condition
68
                                                          // If reading only 1 byte, stop condition
69
                                                          // should have already been sent
70
              // Receive and calculate temperature
71
               slave_temperature = i2c_Data_From_Slave[1] << 8 | i2c_Data_From_Slave[0];
72
               celsius = ((slave_temperature-2730)/10);
73
                    break;                     // Vector 24: RXIFG0 break;
74
75
        case 0x18:
76
              if (TXByteCounter)              // If there's something to transmit
77
              {
78
                    UCB0TXBUF = 0x08;*pTXData++;            // Load TX buffer
79
                    TXByteCounter--;                      // Decrement TX byte counter
80
                    TXFlag = FLAG_SUCCESS;
81
                }
82
                else
83
                {
84
                  UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
85
                  UCB0IFG &= ~UCTXIFG;                    // Clear USCI_B0 TX int flag
86
                  __bic_SR_register_on_exit(LPM0_bits);   // Exit LPM0
87
                  TXFlag = FLAG_SUCCESS;
88
                }
89
90
              break;                                  // Vector 26: TXIFG0 break;
91
        default:     break;
92
  }
93
}
94
95
96
//===================================================================================//
97
// FUNCTION: i2c_MASTER_TRANSMITTER
98
//===================================================================================//
99
void i2c_master_transmitter()
100
{
101
  UCB0CTL1 |= UCSWRST;                          // Enable SW reset
102
  UCB0CTLW0 = UCMST + UCMODE_3 + UCSYNC;         // I2C Master, synchronous mode
103
  UCB0CTL1 = UCSSEL_2 + UCSWRST;                // Use SMCLK, keep SW reset
104
  UCB0BR0 = 0;                                 // fSCL = SMCLK/256 ~ 100kHz
105
  UCB0BR1 = 1;                  // Buad Rate Prescalar = UCB1BR1 * 256 + UCB1BR0
106
  UCB0I2CSA = i2c_BATTERY_ADDRESS;              // Assign Slave Address
107
  UCB0CTL1 &= ~UCSWRST;                        // Clear SW reset, resume operation
108
  UCB0IE |= UCTXIE + UCRXIE + UCNACKIE;         // Enable TX, RX, NACK interrupt
109
}
110
111
//===================================================================================//
112
// FUNCTION: TRANSMIT
113
//===================================================================================//
114
void transmit()
115
{
116
    __delay_cycles(1000);                     // Delay between transmissions
117
    TXByteCounter = 1;                          // Load TX byte counter
118
    while (UCB0CTLW0 & UCTXSTP);              // Ensure stop condition got sent
119
    UCB0CTLW0 |= UCTR + UCTXSTT;              // I2C TX, start condition
120
121
    __bis_SR_register(CPUOFF + GIE);          // Enter LPM0 w/ interrupts
122
}
123
124
125
//===================================================================================//
126
// FUNCTION: i2c_MASTER_TRANSMITTER
127
//===================================================================================//
128
void i2c_master_receiver()
129
{
130
    UCB0CTLW0 |= UCSWRST;                  // Software reset enabled
131
    UCB0CTLW0 |= UCMODE_3  + UCMST + UCSYNC;  // I2C mode, Master mode, sync
132
    UCB0CTLW1 |= UCASTP_2;              // Automatic stop generated
133
                                              // After UCB0TBCNT is reached
134
    UCB0BR0 = 0;                               // fSCL = SMCLK/256 ~ 100kHz
135
    UCB0BR1 = 1;                // Buad Rate Prescalar = UCB1BR1 * 256 + UCB1BR0
136
    UCB0I2CSA  = i2c_BATTERY_ADDRESS;        // Slave address
137
    UCB0CTL1  &=~UCSWRST;
138
    UCB0IE    |= UCRXIE+UCNACKIE+UCBCNTIE;
139
}
140
141
142
//===================================================================================//
143
// FUNCTION: RECEIVE
144
//===================================================================================//
145
void receive()
146
{
147
    __delay_cycles(2000);
148
    pRXData = (unsigned char *) i2c_Data_From_Slave;
149
    RXByteCounter = 2;                              // Load RX byte counter
150
    while (UCB0CTL1 & UCTXSTP);                   // Ensure stop condition got sent
151
    UCB0CTL1 |= UCTXSTT;                          // I2C start condition
152
153
    __bis_SR_register(CPUOFF+GIE);                // Enter LPM0 w/ interrupt
154
}

von Klaus R. (klara)


Lesenswert?

Hallo,
nimm am Anfang ein simples Device wie den PCF8574 als Slave. Der ist so 
ziemlich das unkritischste Device. Wenn dann Deine Kommunikation läuft, 
gehe einen Schritt weiter. Arbeite anfangs mit kleineren Taktraten und 
kurzen Leitungslängen.
mfg klaus.

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.