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.

[参考译文] MSP430FR2672:SDA 和 SCL 在 I2C 期间都保持高电平、但仍接收中断、每次只读取0xFF

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1003768/msp430fr2672-both-sda-and-scl-are-held-high-during-i2c-but-still-receive-interrupts-just-reads-0xff-every-time

器件型号:MSP430FR2672

我正在使用定制板、我已经编写了一些 I2C 代码、查看了许多其他资源、它似乎与一切都相当匹配。 这是一个主器件、用于与从加速计连接。 在 SDA 和 SCL 线路上、我还有两个外部上拉电阻器、每条线路为10K。 当我执行该程序时、它看起来工作正常、因为所有正确的中断都会触发、并且我能够从总线读取一个值作为响应、但每次它都是0xFF。 此外、当我在这两行上放置一个示波器时、它们在整个时间内都处于高电平。 下面是我的代码。 请告诉我其中是否有任何明显的问题。 现在、代码重复尝试从位于0x29的寄存器中读取。 提前感谢!

#include <msp430.h> 
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>


#define SLAVE_ADD 0b0011000

/**
 * main.c
 */

int value;
volatile bool isWrite = false;
volatile int stateCounter = 0;

void init_i2c(){


    P2DIR |= 0x80;
    P2OUT |= 0x80;  //GPIO For LED

    P1SEL0 &= ~(BIT2 | BIT3);
    P1SEL1 &= ~(BIT2 | BIT3);
    P1DIR |= BIT3;


    P1OUT |= BIT3;  //Free up SCL from slave
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;
    P1OUT |= BIT3;
    P1OUT &= ~BIT3;

    __delay_cycles(1000);

    UCB0CTLW0 |= UCSWRST;

    UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC;

    UCB0BRW = 320;

    UCB0CTLW1 = UCASTP_2;

    UCB0TBCNT = 0x07;

    UCB0I2CSA =  SLAVE_ADD;

    // I2C pins
    P1SEL0 |= BIT2 | BIT3;
    P1SEL1 &= ~(BIT2 | BIT3);

    UCB0CTLW0 &= ~UCSWRST;

    UCB0IE |= UCTXIE + UCRXIE + UCNACKIE;

    _enable_interrupts();

    PM5CTL0 &= ~LOCKLPM5;

}

#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void){

    int interruptValue = 0;
  switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
  {
    case USCI_NONE:
        interruptValue = 1; break;         // Vector 0: No interrupts
    case USCI_I2C_UCALIFG:
        interruptValue = 2; break;         // Vector 2: ALIFG
    case USCI_I2C_UCNACKIFG:                // Vector 4: NACKIFG

        printf("UNACK");
        fflush (stdout);

      break;
    case USCI_I2C_UCSTTIFG:
        interruptValue = 3; break;         // Vector 6: STTIFG
    case USCI_I2C_UCSTPIFG:
        interruptValue = 4; break;          // Vector 8: STPIFG
    case USCI_I2C_UCRXIFG3:
        interruptValue = 5; break;          // Vector 10: RXIFG3
    case USCI_I2C_UCTXIFG3:
        interruptValue = 6; break;          // Vector 12: TXIFG3
    case USCI_I2C_UCRXIFG2:
        interruptValue = 7; break;          // Vector 14: RXIFG2
    case USCI_I2C_UCTXIFG2:
        interruptValue = 8; break;          // Vector 16: TXIFG2
    case USCI_I2C_UCRXIFG1:
        interruptValue = 9; break;          // Vector 18: RXIFG1
    case USCI_I2C_UCTXIFG1:
        interruptValue = 10; break;          // Vector 20: TXIFG1
    case USCI_I2C_UCRXIFG0:                 // Vector 22: RXIFG0

        value = UCB0RXBUF & 0xFF;
        printf("%x",value);
        fflush (stdout);
        UCB0CTLW0 |= UCTXSTP;
        __bic_SR_register_on_exit(CPUOFF);

        break;
    case USCI_I2C_UCTXIFG0:                 // Vector 24: TXIFG0

        if(!isWrite){

            UCB0TXBUF = 0x29;
            UCB0I2CSA =  SLAVE_ADD;
            UCB0CTLW0 &= ~UCTR;
            UCB0CTLW0 |= UCTXSTT;
            while((UCB0CTLW0 & UCTXSTT));
            UCB0CTLW0 |= UCTXSTP;
            printf("%x",value);
            fflush (stdout);
        }else{
            if(stateCounter == 0){
                UCB0TXBUF = 0x20;
                stateCounter++;
            }else if(stateCounter == 1){
                UCB0TXBUF = 0x50;
                stateCounter++;

            }else{

                UCB0CTLW0 |= UCTXSTP;
                stateCounter++;
                printf("HJKFSD");
                fflush (stdout);
                __bic_SR_register_on_exit(CPUOFF);

            }
        }

        break;
    default:
        interruptValue = 11; break;
  }

  printf("%d:",interruptValue);
  fflush(stdout);


}

void initClockTo16MHz()
{
    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    FRCTL0 = FRCTLPW | NWAITS_1;

    // Clock System Setup
    __bis_SR_register(SCG0);                           // disable FLL
    CSCTL3 |= SELREF__REFOCLK;                         // Set REFO as FLL reference source
    CSCTL0 = 0;                                        // clear DCO and MOD registers
    CSCTL1 &= ~(DCORSEL_7);                            // Clear DCO frequency select bits first
    CSCTL1 |= DCORSEL_5;                               // Set DCO = 16MHz
    CSCTL2 = FLLD_0 + 487;                             // DCOCLKDIV = 16MHz
    __delay_cycles(3);
    __bic_SR_register(SCG0);                           // enable FLL
    while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));         // FLL locked
}

int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
	


	initClockTo16MHz();
	init_i2c();

	printf("Start");
	puts("Start1");
	putchar('c');
    fflush (stdout);

    while ( UCB0STAT & UCBBUSY )
            ;

    while(1){
        __delay_cycles(1000000);
    UCB0I2CSA =  SLAVE_ADD;
    UCB0IFG &= ~(UCTXIFG + UCRXIFG);

    /*UCB0CTLW0 |= UCTR; //Setting to transmitt mode

    UCB0CTLW0 |= UCTXSTT;

    //Reading and writing here are exact same
    isWrite = true;

    __bis_SR_register(LPM0_bits + GIE);*/

    UCB0I2CSA =  SLAVE_ADD;
    UCB0IFG &= ~(UCTXIFG + UCRXIFG);

    UCB0CTLW0 |= UCTR; //Setting to transmitt mode

    UCB0CTLW0 |= UCTXSTT;

    isWrite = false;
    stateCounter = 0;

    __bis_SR_register(LPM0_bits + GIE);
    }

	return 0;
}

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

    1) 1)由于 LOCKLPM5仍然被置位、所有与 P1OUT.3的闲置被浪费。 这一点毫无意义、因为 I2C 不需要它。 通常。 我在我的一些代码中看到一个手动生成的时钟、如果它在一个 POR 之后立即看到 UCBUSY。 我不知道为什么这么做、但我确信当时是有道理的。 :-)

    2)我一直不清楚 LOCKLMP5是否对 PxSEL 寄存器有任何影响(即使在仔细阅读文档之后)。 设置 STT 后、I2C 硬件应超时从器件地址。 完全缺少时钟表明 PxSEL 存在问题。