This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430G2231: Problem on USI stuck at end.

Part Number: MSP430G2231

I attempted to create a small clock using a MAX7219 for the display. I wrote some code, and while the display does show, it gets stuck at the end. During debugging, I noticed that when I pause the program, it stops on the following line:

while (!(USICTL1 & USIIFG));

I implemented a quick fix by limiting the cycles with an escape counter.
LogicAn
Is there an error in my configuration?

#include <msp430.h> 
#include "msp430g2231.h"
#include <stdint.h>
#include <stdbool.h>
#include "max7219.h"

void SetSPI(void);
void SetI2C(void);
#define MODE_SPI 0x00
#define MODE_I2C 0x01
#define BUSY_SPI 0x02
#define BUSY_I2C 0x04
#define REQ_SPI 0x08
#define REQ_I2C 0x10

void changeUSI(int modo) {
    // Deshabilitar el USI
    USICTL0 |= USISWRST;

    if (modo == MODE_SPI) {
        SetSPI();
    } else if (modo == MODE_I2C) {
        SetI2C();
    }

    // Habilitar el USI
    USICTL0 &= ~USISWRST;
}
void SetSPI(void){
    USICTL0 = USIPE6 + USIPE5 + USIMST + USIOE;
    USICTL1 = USICKPH;
    USICKCTL |= USIDIV_0 + USISSEL_2;
    USICNT = USI16B;
}

void SetI2C(void){
    USICTL0 = USIPE6 + USIPE5 + USIMST + USIOE;
    USICTL1 |= USICKPH;
    USICKCTL |= USIDIV_0 + USISSEL_2;
}

void enviar(uint8_t comando, uint8_t dato) {
    // Cargar el byte en el registro USISR
    USISRH = comando;
    USISRL = dato;
    int scape = 10;
    P1OUT &= ~BIT4;
    USICNT |= 16;
    // Limpiar la bandera de interrupción de contador USI
    USICTL1 &= ~USIIFG;

    // Esperar a que se complete la transmisión
    while (!(USICTL1 & USIIFG) && --scape);
    P1OUT |= BIT4; // Establecer P1.4 en alto después de la transmisión
}

int main(void) {
  WDTCTL = WDT_ADLY_250;   // WDT 250ms, ACLK, interval timer
  IE1 |= WDTIE;            // Enable WDT interrupt
  if (CALBC1_1MHZ == 0xFF) // If calibration constants erased
  {
    while (1)
      ; // do not load, trap CPU!!
  }
  DCOCTL = 0; // Select lowest DCOx and MODx settings
  BCSCTL1 = CALBC1_1MHZ;
  DCOCTL = CALDCO_1MHZ;

        BCSCTL3 |= XCAP_3; //LFXTAL Capacitor 12.5pf

  P1OUT = BIT4 | BIT3 | BIT7;                // Initialize all GPIO
  P1SEL = UART_TXD + UART_RXD; // Timer function for TXD/RXD pins
  P1DIR = 0xFF & ~(UART_RXD | BIT7 | BIT3);    // Set all pins but RXD to output
  P1REN = BIT3 | BIT7;
  P2OUT = 0x00;
  //P2SEL = 0x00;
  P2DIR = 0x3F;

  __enable_interrupt();

  TimerA_UART_init(); // Start Timer_A UART
  TimerA_UART_print("G2xx1 TimerA UART\r\n");
  TimerA_UART_print("READY.\r\n");
  uint8_t bitcount = 1;
  TimerA_UART_print("Config Module 1\r\n");
  TimerA_UART_print("Set SPI\r\n");
  changeUSI(MODE_SPI);
  TimerA_UART_print("Shutdown\r\n");
  enviar(SHUTDOWN, SHUTDOWN_MODE);
  TimerA_UART_print("Display Limit\r\n");
  enviar(SCAN_LIMIT, DISPLAY_7);
  TimerA_UART_print("Intensity\r\n");
  enviar(INTENSITY, DUTY_CYCLE_15_32);
  TimerA_UART_print("Decode Mode\r\n");
  enviar(DECODE_MODE, 0xFF);
  TimerA_UART_print("Test Off\r\n");
  enviar(DISPLAY_TEST, TEST_NORMAL_OPERATION);
  TimerA_UART_print("Turn On\r\n");
  enviar(SHUTDOWN, SHUTDOWN_NORMAL_OPERATION);
  TimerA_UART_print("Digits\r\n");
  enviar(DIGIT_0, 1);
  enviar(DIGIT_1, 2);
  enviar(DIGIT_2, 3);
  enviar(DIGIT_3, 4);
  enviar(DIGIT_4, 5);
  enviar(DIGIT_5, 6);
  enviar(DIGIT_6, 7);
  enviar(DIGIT_7, 8);
  enviar(0,0);
  for (;;) {
    // Wait for incoming character
    __bis_SR_register(LPM0_bits);
    TimeReport();
    // Echo received character
    //TimerA_UART_tx(rxBuffer);
  }
}

  • > USICNT |= 16;
    > USICTL1 &= ~USIIFG;

    I think there's a race here: You have 16 (S)MCLKs to get past the second line, or you'll clear the IFG you're looking for. It's not a very tight race, but if you get an ill-timed interrupt that will make the window much larger.

    I don't think you need to clear the IFG (second line) at all, since it auto-cleared when you set USICNT [Ref User Guide (SLAU144K) Sec 14.2], i.e. I think you can delete that line. At the least, you should move it to precede the USICNT setting.

**Attention** This is a public forum