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:USI 问题卡在结束时。

Guru**** 1633940 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1352270/msp430g2231-problem-on-usi-stuck-at-end

器件型号:MSP430G2231

我尝试使用 MAX7219来创建一个用于显示屏的小时钟。 我编写了一些代码、当显示屏显示出来时、最后会卡住。 在调试过程中、我注意到当我暂停程序时、程序会在下面的行中停止:

while (! (USICTL1和 USIIFG));

我通过使用转义计数器限制周期来实现了一个快速修复方法。

我的配置中是否有错误?

#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;

    我认为这里有一场比赛:你有16个(S) MCLK 越过第二条线、或者你将清除你正在寻找的 IFG。 这不是一个非常紧张的比赛、但如果你得到一个错误的时间中断、将使窗口大得多。

    我认为您根本不需要清除 IFG (第二行)、因为当您设置 USICNT [参考用户指南(SLAU144K)第14.2节]时、它会自动清除、即、我认为您可以删除这一行。 至少、您应该将其移动到 USICNT 设置之前。