controlador I2C para MSP432

0

Estoy intentando desarrollar un controlador I2C para MSP432. A partir de ahora, estoy conectando un acelerómetro a través del módulo USCI B2_ en MSP432.

El problema al que me enfrento es que obtengo un NACK en el registro IFG cuando genero una condición de inicio.

  • ¿Cuál podría ser el problema potencial en el código?

A continuación se adjunta el código. Indique cualquier error que haya cometido al desarrollar la función i2c_write_byte .

También:

  • ¿Necesito tener resistencias adicionales en las líneas SDA y SCL?

No he agregado resistencias de pull-up externas adicionales ya que mi sensor ya tiene las resistencias de pull-up incluidas.

      /**
 * @file i2c.c
 * @brief This file is to be used for the setting the I2C peripheral of the microcontroller.
 * @author Vikrant Waje
 * @date November 18, 2018
 *
 */

//***********************************************************************************
// Include files
//***********************************************************************************
#include"main.h"


//***********************************************************************************
// Global variables
//***********************************************************************************


//***********************************************************************************
// Function implementation
//***********************************************************************************
/*------------------------------------------------------------------------------------------------------------------------------------*/
/*
  @brief: Setup the I2C peripheral.


 @param: None
 @param:None

 @return: None
 */
/*-----------------------------------------------------------------------------------------------------------------------------*/
void i2c_setup(){
    i2c_gpio_setup();
    i2c_set_parameters();
    i2c_enable();
}
/*------------------------------------------------------------------------------------------------------------------------------------*/
/*
  @brief: Assign GPIO to I2C peripherals.
  SCL = P3.7 (UCSI B)(SEL1 =0 , SEL0 = 1 )
  SDA = P3.6 (UCSI B)(SEL1 =0 , SEL1 = 1)

 @param: None
 @param:None

 @return: None
 */
/*-----------------------------------------------------------------------------------------------------------------------------*/
void i2c_gpio_setup(){
   // SCL->SEL1 |=BIT0;
    P3->SEL0 |= (BIT6 | BIT7); //P3_SEL0.7 = 1 and P3_SEL0.6 = 1
}
/*------------------------------------------------------------------------------------------------------------------------------------*/
/*
  @brief: Set the parameters for I2C peripherals.


 @param: None
 @param:None

 @return: None
 */
/*-----------------------------------------------------------------------------------------------------------------------------*/
void i2c_set_parameters(){

   /* I2C_Init_Typedef * i2c_struct = malloc(sizeof(I2C_Init_Typedef));

    i2c_struct->enable = enable_false; // Enable Software reset
    i2c_struct->mode = I2C; //Enable I2C mode
    i2c_struct->master = master_mode; // Enable master mode
    i2c_struct->sync_mode =sync_mode_enable; //Enable sync mode
    i2c_struct->clock_source = smclk;   //Use SMCLK as clock source
   // i2c_struct->acknowledge = sw_ack_enable;    //Software acknowledgement enabled
    i2c_struct->bit_rate =8;*/

    i2c_init();


}

/*------------------------------------------------------------------------------------------------------------------------------------*/
/*
  @brief: Initialise I2c using the parameters set in the structure.


 @param: i2c_struct: Pointer to initialisation structure
 @param:None

 @return: None
 */
/*-----------------------------------------------------------------------------------------------------------------------------*/
void i2c_init(/*I2C_Init_Typedef * i2c_struct*/){

    EUSCI_B2->CTLW0 |=EUSCI_B_CTLW0_SWRST|EUSCI_B_CTLW0_MODE_3|EUSCI_B_CTLW0_MST|EUSCI_B_CTLW0_SYNC|EUSCI_B_CTLW0_SSEL__SMCLK;
    EUSCI_B2->BRW = 0x0008;


    /* EUSCI_B2->CTLW0 |= (i2c_struct->enable |  i2c_struct->mode| i2c_struct->master | i2c_struct->sync_mode | i2c_struct->clock_source  );
   // EUSCI_B2->CTLW1 |= (i2c_struct->acknowledge);
    EUSCI_B2->BRW = i2c_struct->bit_rate;*/
}

/*------------------------------------------------------------------------------------------------------------------------------------*/
/*
  @brief: Enable i2c communication.


 @param: None
 @param:None

 @return: None
 */
/*-----------------------------------------------------------------------------------------------------------------------------*/
void i2c_enable(){
    EUSCI_B2->CTLW0 &= ~(EUSCI_B_CTLW0_SWRST); //Enable i2c communication
}
/*------------------------------------------------------------------------------------------------------------------------------------*/
/*
  @brief: Write byte for I2C.


 @param: data_byte: Data that is to be written
 @param:None

 @return: None
 */
/*-----------------------------------------------------------------------------------------------------------------------------*/

void i2c_write_byte(uint8_t slave_addr,uint8_t reg_addr,uint8_t data_byte){
    while(EUSCI_B2->STATW & EUSCI_B_STATW_BBUSY);
    EUSCI_B2->I2CSA = (slave_addr << 1);    //Set slave address with write bit (LSB = 0)
    EUSCI_B2->CTLW0 |= EUSCI_B_CTLW0_TR ; //Set as transmitter
    EUSCI_B2->CTLW0 |= EUSCI_B_CTLW0_TXSTT ; // Send start condition
    while(!(EUSCI_B2->IFG & EUSCI_B_IFG_TXIFG0) ); //Wait until start condition is transmitted
    // EUSCI_B2->IFG &= ~(EUSCI_B_IFG_TXIFG0); //Clear the flag


     EUSCI_B2->TXBUF = reg_addr;    //Send the register address
     while(!(EUSCI_B2->IFG & EUSCI_B_IFG_TXIFG0) ); //Wait until the data in TXBUF(register address) is transmitted
   //  EUSCI_B2->IFG &= ~(EUSCI_B_IFG_TXIFG0); //Clear the flag

     EUSCI_B2->TXBUF = data_byte;    //Send the data byte
     while(!(EUSCI_B2->IFG & EUSCI_B_IFG_TXIFG0) ); //Wait until the data in TXBUF(register address) is transmitted
    // EUSCI_B2->IFG &= ~(EUSCI_B_IFG_TXIFG0); //Clear the flag

     EUSCI_B2->CTLW0 |= EUSCI_B_CTLW0_TXSTP; // Generate a stop condition
     while(!(EUSCI_B2->IFG & EUSCI_B_IFG_TXIFG0) ); //Wait until the data in TXBUF(register address) is transmitted
     EUSCI_B2->IFG &= ~(EUSCI_B_IFG_TXIFG0); //Clear the flag

}


/*------------------------------------------------------------------------------------------------------------------------------------*/
/*
  @brief: Read byte for I2C.


 @param: None
 @param:None

 @return: data_byte:Data that is read
 */
/*-----------------------------------------------------------------------------------------------------------------------------*/
uint8_t i2c_read_byte(uint8_t slave_addr,uint8_t reg_addr){
    EUSCI_B2->I2CSA = (slave_addr << 1);    //Set slave address with write bit (LSB = 0)
    EUSCI_B2->CTLW0 &= ~(EUSCI_B_CTLW0_TR) ; //Set as Receiver
    EUSCI_B2->CTLW0 |= EUSCI_B_CTLW0_TXSTT ; // Send start condition

    while(!(EUSCI_B2->IFG & EUSCI_B_IFG_TXIFG0) ); //Wait until start condition is transmitted
     EUSCI_B2->IFG &= ~(EUSCI_B_IFG_TXIFG0); //Clear the flag

     while((EUSCI_B2->CTLW0 & EUSCI_B_CTLW0_TXSTT) );   //Wait for complete slave address to get transmitted

     EUSCI_B2->TXBUF = reg_addr;    //Send the register address
     while(!(EUSCI_B2->IFG & EUSCI_B_IFG_TXIFG0) ); //Wait until the data in TXBUF(register address) is transmitted
     EUSCI_B2->IFG &= ~(EUSCI_B_IFG_TXIFG0); //Clear the flag

     EUSCI_B2->I2CSA = (slave_addr << 1) | (0x01);    //Set slave address with write bit (LSB = 0)
     EUSCI_B2->CTLW0 |= EUSCI_B_CTLW0_TXSTT ; // Send start condition

     while(!(EUSCI_B2->IFG & EUSCI_B_IFG_TXIFG0) ); //Wait until start condition is transmitted
     EUSCI_B2->IFG &= ~(EUSCI_B_IFG_TXIFG0); //Clear the flag


     while((EUSCI_B2->CTLW0 & EUSCI_B_CTLW0_TXSTT) );   //Wait for complete slave address to get transmitted

     while(!(EUSCI_B2->IFG & EUSCI_B_IFG_RXIFG) ); //Wait until start condition is transmitted
     EUSCI_B2->IFG &= ~(EUSCI_B_IFG_RXIFG); //Clear the flag

     EUSCI_B2->CTLW0 |= EUSCI_B_CTLW0_TXNACK; //Transmit a NACK


     EUSCI_B2->CTLW0 |= EUSCI_B_CTLW0_TXSTP; // Generate a stop condition

     return EUSCI_B2->RXBUF;

}
    
pregunta Vikrant Waje

1 respuesta

0
EUSCI_B2->CTLW0 |=EUSCI_B_CTLW0_SWRST|EUSCI_B_CTLW0_MODE_3|EUSCI_B_CTLW0_MST|EUSCI_B_CTLW0_SYNC|EUSCI_B_CTLW0_SSEL__SMCLK;
                ^^

|= no borra ningún bit. Para modificar todos los campos de registro, use = .

EUSCI_B2->BRW = 0x0008;

Es probable que SMCLK / 8 sea demasiado rápido.

while(EUSCI_B2->STATW & EUSCI_B_STATW_BBUSY);

La espera de este bit no es realmente útil. Espera a que TXSTP sea claro.

EUSCI_B2->I2CSA = (slave_addr << 1);    //Set slave address with write bit (LSB = 0)

Una dirección de esclavo I²C tiene siete bits, por lo que no debe cambiar nada. (El hardware maneja automáticamente el bit R / W, basado en el bit de registro TR).

 EUSCI_B2->CTLW0 |= EUSCI_B_CTLW0_TXSTP; // Generate a stop condition
 while(!(EUSCI_B2->IFG & EUSCI_B_IFG_TXIFG0) ); //Wait until the data in TXBUF(register address) is transmitted

No hay ningún byte que transmitir. Espere a que se borre TXSTP o (si su código ya hace esto, espere al comienzo de cada transacción) no haga nada.

EUSCI_B2->CTLW0 &= ~(EUSCI_B_CTLW0_TR) ; //Set as Receiver
EUSCI_B2->CTLW0 |= EUSCI_B_CTLW0_TXSTT ; // Send start condition

while(!(EUSCI_B2->IFG & EUSCI_B_IFG_TXIFG0) ); //Wait until start condition is transmitted
...

No puede transmitir cuando el bit TR no está establecido.

EUSCI_B2->CTLW0 |= EUSCI_B_CTLW0_TXNACK; //Transmit a NACK

TXNACK se usa solo en el modo de receptor esclavo. Un maestro transmite un NACK configurando TXSTP mientras se recibe el último byte, es decir, antes del último RXIFG. (Consulte la figura 26-13 del Manual de referencia).

    
respondido por el CL.

Lea otras preguntas en las etiquetas