Ich habe ein MSP430FR6989- Entwicklungsboard ( MSP-EXP430FR6989 ).
Ich möchte es so programmieren, dass es mit einem MAX30102- Pulsoximeter und einem Herzfrequenz-IC kommuniziert. Die Schnittstelle erfolgt über das I2C-Protokoll.
Ich habe nur einen Master (MSP430) und einen Slave (MAX30102).
Aus dem Lesen des MSP430-Benutzerhandbuchs (Seite 821, Kapitel 32, eUSCI-I2C-Modus) und des MAX30102-Datenblatts (Seite 16/32) geht Folgendes hervor:
UCB0I2CSA = 0x57
, setzen sie UCTR
für einen Schreibvorgang und setzen sie UCTXSTT
für eine START-Bedingung.UCTXSTT
Bit wird gelöscht und das UCB0TXIFG0
Bit gesetztUCB0TXIFG0
das Bit gesetzt ist, geht MSP430 zu einem ISR, das Interrupt-Flag wird gelöscht, und wir schreiben das Adressregister von MAX30102 FIFO_WR_PTR in den Übertragungspuffer UCB0TXBUF
.UCBOTXIFG0
wird das Bit gesetzt, geht zur ISR, wir löschen das UCTR
Bit für einen Lesemodus und setzen es UCTXSTT
für eine REPEATED START-Bedingung.UCRXIFG0
gesetzt, MSP430 geht zu eUSCI_B0 ISR (diesmal entspricht der Wert am Interrupt-Vektor den empfangenen Daten).UCB0RXBUF
(FIFO_WR_PTR) wird in einer globalen Variablen gespeichert WritePointer = UCB0RXBUF
.Ich habe entsprechend einen MSP430-Code geschrieben.
#include <msp430.h>
#include <stdint.h>
uint8_t WritePointer = 0;//to store the value inside the FIFO_WR_PTR
#define ENABLE_PINS 0xFFFE
#define MAX30102_SLAVE_ADDR 0x57
#define MAX30102_FIFO_WR_PTR_ADDR 0x04
//other address definitions
// S SLA/W (A) FIFO_WR_PTR_ADDR (A) SR SLA/R (A) (FIFO_WR_PTR) NACK P 1st interaction
/*
* Private Variables
*/
void configClock(void);
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
PM5CTL0 = ENABLE_PINS;
configClock ();
//config pins P1.6 SDA P1.7 SCL
P1SEL0 &= ~(BIT6 | BIT7);
P1SEL1 |= (BIT6 | BIT7);
UCB0CTLW0 |= UCSWRST;//put it on a restart mode to config
UCB0CTLW0 |= (UCMST | UCMODE_3 | UCSSEL__SMCLK);// i2c master cs smclk
UCB0BRW = 10;//100kbps fSCL = fSMCLK / 10 = 100 KHz
UCB0IFG &= ~UCTXIFG0;//set eUSCI_B0 for operation
UCB0I2CSA = MAX30102_SLAVE_ADDR;//from datasheet address is 0x57
UCB0CTLW0 &= ~UCSWRST;//release for operation
UCB0IE |= (UCTXIE0 | UCRXIE0);//enable RX and TX isr
//when and ACK is received a tx or rx isr is serviced
_BIS_SR (GIE);//enable global interrupt
while(1)
{
UCB0CTLW0 |= (UCTR | UCTXSTT);//W and START
}
return 0;
}
void configClock (void)
{
CSCTL0 = CSKEY;
CSCTL1 = 0x0000;//DCO 1MHz
CSCTL2 |= (SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK);
}
#pragma vector = USCI_B0_VECTOR
__interrupt void eUSCI_B0_I2C_ISR (void)
{
static int counter = 0;
//this is a byte counter, after the Slave ACK Address and W
//Master is expected to transmit data (register address of FIFO_WR_PTR)
//then set a REPEATED START, along with the slave address (the same) and change the mode to read
switch(UCB0IV)
{
case USCI_I2C_UCTXIFG0:
if(counter == 0)
{
UCB0TXBUF = MAX30102_FIFO_WR_PTR_ADDR;
counter++;
}
else
{
UCB0CTLW0 &= ~UCTR;//R
UCB0CTLW0 |= UCTXSTT;//repeated start
counter = 0;
}
break;
case USCI_I2C_UCRXIFG0:
WritePointer = UCB0RXBUF;
//WritePointer is a global variable
//FIFO_WR_PTR is assigned to WritePointer
UCB0CTLW0 |= UCTXSTP;
//MSP430 to initiate STOP condition
break;
default:
break;
}
}
Wenn ich jedoch den Code baue und ausführe, habe ich den SCL (P1.7) mit einem Oszilloskop geprüft und ich bekomme nur eine hohe Spannung (3,3 V). Selbst wenn meine I2C-Softwarekonfiguration falsch ist, sollte ich immer noch mindestens 9 Impulse (7-Bit-Adresse, 1-Bit-Write, 1-Bit-ACK/NACK) vom SCL mit dem Oszilloskop erhalten.
Als ich den Code debuggte und der MSP430 in die While-Schleife wechselt, wenn UCTXSTT
gesetzt ist, wird kein Interrupt-Flag gesetzt.
PS: Der HW-Anschluss ist ein Open-Drain mit 4,7-kOhm-Widerständen, die als Pullup-Widerstände fungieren.
Ich weiß nicht, wo mein Fehler liegt, bitte helfen Sie mir bei diesem Problem.
#define ENABLE_PINS 0xFFFE
PM5CTL0 = ENABLE_PINS;
Dadurch werden alle anderen Bits als 1 geschrieben. Um ein einzelnes Bit zu löschen, verwenden Sie PM5CTL0 &= ~LOCKLPM5;
.
//config pins P1.6 SDA P1.7 SCL
P1SEL0 &= ~(BIT6 | BIT7);
P1SEL1 |= (BIT6 | BIT7);
Wie in Tabelle 6-21 des Datenblatts gezeigt, müssen Sie das Bit in P1SEL0 setzen und das Bit in P1SEL1 löschen.
while(1)
{
UCB0CTLW0 |= (UCTR | UCTXSTT);//W and START
}
Dadurch wird fortlaufend eine neue Transaktion gestartet. Sie möchten zumindest warten, bis der vorherige fertig ist.
Eingebetteter_Typ
counter
zurückgesetzt, wenn MSP430 die Else-Anweisung in die ISR eingibtEingebetteter_Typ