Tengo una placa de desarrollo MSP430FR6989 ( MSP-EXP430FR6989 ).
Me gustaría programarlo para que se comunique con un oxímetro de pulso y frecuencia cardíaca MAX30102 IC, la interfaz se realiza a través del protocolo I2C.
Solo tengo un maestro (MSP430) y un esclavo (MAX30102).
Al leer la guía del usuario de MSP430 (pg821 Capítulo 32 Modo eUSCI I2C) y la hoja de datos MAX30102 (pg16/32) , esto es lo que entiendo:
UCB0I2CSA = 0x57
, configuramos UCTR
para una escritura y configuramos UCTXSTT
para una condición de INICIO.UCTXSTT
bit se borra y el UCB0TXIFG0
bit se estableceUCB0TXIFG0
se establece el bit, MSP430 va a un ISR, se borra el indicador de interrupción y escribimos el registro de dirección de MAX30102 FIFO_WR_PTR en el búfer de transmisión UCB0TXBUF
.UCBOTXIFG0
el bit se establece, va al ISR, borramos el UCTR
bit para un modo de lectura y lo configuramos UCTXSTT
para una condición de INICIO REPETIDO.UCRXIFG0
establece, MSP430 va a eUSCI_B0 ISR (esta vez, el valor en el vector de interrupción corresponde a los datos recibidos).UCB0RXBUF
(FIFO_WR_PTR) se almacena en una variable global WritePointer = UCB0RXBUF
.He escrito un código MSP430 en consecuencia.
#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;
}
}
Sin embargo, cuando construyo y ejecuto el código, probé el SCL (P1.7) con un osciloscopio y solo obtengo un alto voltaje (3.3V). Incluso si la configuración de mi software I2C es incorrecta, debería obtener al menos 9 pulsos (dirección de 7 bits, escritura de 1 bit, ACK/NACK de 1 bit) del SCL con el osciloscopio.
Cuando depuré el código y el MSP430 entra en el ciclo while, cuando UCTXSTT
está configurado, no se configura ningún indicador de interrupción.
PD: la conexión HW es un drenaje abierto, con resistencias de 4,7 K ohmios que actúan como resistencias pull-up.
No sé dónde está mi error, por favor ayúdenme con este problema.
#define ENABLE_PINS 0xFFFE
PM5CTL0 = ENABLE_PINS;
Esto escribe todos los demás bits como 1. Para borrar un solo bit, use PM5CTL0 &= ~LOCKLPM5;
.
//config pins P1.6 SDA P1.7 SCL
P1SEL0 &= ~(BIT6 | BIT7);
P1SEL1 |= (BIT6 | BIT7);
Como se muestra en la tabla 6-21 de la hoja de datos, debe configurar el bit en P1SEL0 y borrar el bit en P1SEL1.
while(1)
{
UCB0CTLW0 |= (UCTR | UCTXSTT);//W and START
}
Esto inicia continuamente una nueva transacción. Desea al menos esperar hasta que el anterior haya terminado.
Embedded_Dude
counter
la declaración else dentro del ISREmbedded_Dude