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.

LP-MSP430FR2476: 怎么在多个外设中断下循环执行?

Part Number: LP-MSP430FR2476


您好,我用例程改了一个通过硬件eUSCI_B  I2C接口控制一个外围传感器,发送采集命令--->连续采集数据,

我发现每运行一次,只能采集一次数据,我单步调试,发现程序停留在最后一行?为什么没有循环调用中断去执行读取数据的动作?非常感谢!

UCB0IE |= UCTXIE0 | UCRXIE0 | UCNACKIE;  //开启了收发,无响应中断,

TXByteCtr = 2;                 // Load TX byte counter,发两个字节命令
while (UCB0CTLW0 & UCTXSTP);                // Ensure stop condition got sent
UCB0CTLW0 |= UCTR | UCTXSTT;             // I2C TX, start condition

__bis_SR_register(LPM0_bits | GIE);          // Enter LPM0 w/ interrupts
// Remain in LPM0 until all data is TX'd
while(1)
{
RXByteCtl = 9;
while (UCB0CTL1 & UCTXSTP);              // Ensure stop condition got sent
UCB0CTLW0 &= ~UCTR;                    // I2C RX
UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
__bis_SR_register(LPM0_bits|GIE);             / / Enter LPM0 w/ interrupt

}

中断处理后,我加了下面这几行,想继续触发RX中断,但是还是不行?

UCB0CTLW0 &= ~UCTR; // I2C RX
UCB0CTLW0 |= UCTXSTT;
UCB0IFG |= UCTXIFG;
RXByteCtl = 9;
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0

谢谢!

  • #include <msp430.h>
    #include <stdint.h>


    uint8_t RXByteCtl;
    uint8_t RXData[];

    uint8_t TXData[]= {0x15, 0x36}; // TX data
    uint8_t TXByteCtr;

    int main(void)
    {
    WDTCTL = WDTPW | WDTHOLD;
    P1SEL0 |= BIT2 | BIT3; // I2C pins

    PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings

    UCB0CTLW0 |= UCSWRST; // Software reset enabled
    UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC; // I2C mode, Master mode, sync
    // UCB0CTLW1 |= UCASTP_2; // Automatic stop generated after UCB0TBCNT is reachedF

    UCB0BRW = 10; // fSCL = SMCLK/160 = ~100kHz
    RXByteCtl = 9; // number of bytes to be received
    UCB0I2CSA = 0x0025; // Slave address
    UCB0CTL1 &= ~UCSWRST;
    UCB0IE |= UCTXIE0 | UCRXIE0 | UCNACKIE; // | UCBCNTIE;

    TXByteCtr = 2; // Load TX byte counter
    while (UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTLW0 |= UCTR | UCTXSTT; // I2C TX, start condition

    __bis_SR_register(LPM0_bits | GIE); // Enter LPM0 w/ interrupts
    // Remain in LPM0 until all data is TX'd
    while(1)
    {
    RXByteCtl = 9;
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTLW0 &= ~UCTR; // I2C RX
    UCB0CTLW0 |= UCTXSTT; // I2C start condition
    __bis_SR_register(LPM0_bits|GIE); // Enter LPM0 w/ interrupt

    }
    }
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCIB0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
    {

    case USCI_NONE: break; // Vector 0: No interrupts
    case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG
    case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG
    UCB0CTL1 |= UCTXSTT; // I2C start condition
    break;
    case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG
    case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG
    case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3
    case USCI_I2C_UCTXIFG3: break; // Vector 14: TXIFG3
    case USCI_I2C_UCRXIFG2: break; // Vector 16: RXIFG2
    case USCI_I2C_UCTXIFG2: break; // Vector 18: TXIFG2
    case USCI_I2C_UCRXIFG1: break; // Vector 20: RXIFG1
    case USCI_I2C_UCTXIFG1: break; // Vector 22: TXIFG1
    case USCI_I2C_UCRXIFG0: // Vector 24: RXIFG0
    if(RXByteCtl>0)
    {
    __delay_cycles(6000);
    RXByteCtl--;
    RXData[RXByteCtl] = UCB0RXBUF; // Get RX data
    }
    else
    {
    /*
    display( );

    */

    UCB0CTLW0 &= ~UCTR; // I2C RX
    UCB0CTLW0 |= UCTXSTT;
    UCB0IFG |= UCTXIFG;
    RXByteCtl = 9;
    __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
    }
    break;
    case USCI_I2C_UCTXIFG0:
    if (TXByteCtr) // Check TX byte counter
    {
    UCB0TXBUF = TXData[TXByteCtr-1]; // Load TX buffer
    TXByteCtr--; // Decrement TX byte counter
    //__delay_cycles(10);
    }
    else
    {
    UCB0CTLW0 |= UCTXSTP; // I2C stop condition
    UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
    __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
    }
    break;
    case USCI_I2C_UCBCNTIFG: break; // Vector 28: BCNTIFG
    case USCI_I2C_UCCLTOIFG: break; // Vector 30: clock low timeout
    case USCI_I2C_UCBIT9IFG: break; // Vector 32: 9th bit
    default: break;
    }
    }

  • 具体就是我用的UCB0 I2C 口,

    UCB0CTLW0, UCB0CTLW1, UCB0IE, UCB0IFG 这几个register,哪些是用户可以更改(write & read),哪些是系统自己用的(read only)?

    谢谢!

  • 我用例程改了一个通过硬件eUSCI_B  I2C接口控制一个外围传感器

    请问您修改的哪个例程?目前MSP430是主机?

    UCB0CTLW0, UCB0CTLW1, UCB0IE, UCB0IFG 这几个register,哪些是用户可以更改(write & read),哪些是系统自己用的(read only)?

    这个您可以看一下哦用户手册内的寄存器说明,如

    RW就表示可以读也可以写

  • 您好,谢谢解答,

    再帮我看看,我的代码为什么不能无限循环RX中断?

  • switch(__even_in_range(UCA1IV,USCI_UART_UCSTTIFG))
    {
    case USCI_NONE: break; // Vector 0 - no interrupt
    case USCI_SPI_UCRXIFG:
    SPI_RXData = UCA1RXBUF;
    UCA1IFG &= ~UCRXIFG;
    __bic_SR_register_on_exit(LPM0_bits); // Wake up to setup next TX
    break;
    case USCI_SPI_UCTXIFG:
    UCA1TXBUF = RTD; // Transmit characters
    UCB0CTLW0 |= UCTXSTT;
    RXByteCtrl = 9;
    break;
    default: break;

    您好,我在A1中断处理后面这么操作,程序能返回到B0中断那里吗?就是在两个中断直接来回循环?谢谢!

  • 抱歉,之前漏掉了您的回复。请问您现在情况如何了?

  • 您好,谢谢!

    现在是第二次进入while(1)循环后,hang在第一个while (UCB0CTL1 & UCTXSTP); 不管是TX, RX STT,看到一个topic在说这个现象,有人把LP jumper去掉有效,我试了没有作用。

  • 现在是第二次进入while(1)循环后,hang在第一个while (UCB0CTL1 & UCTXSTP); 不管是TX, RX STT,看到一个topic在说这个现象,有人把LP jumper去掉有效,我试了没有作用。

    这个很接近我的问题,也是I2C 的clk一直为低了,但是没有说怎么解决?怎么排查?能帮我问下吗?非常感谢!

  • SCL一直为低,有可能是程序设计上的问题导致MCU无法读取&填充buffer而导致,建议重点分析MCU I2C中断服务程序

    1. I2C中断服务程序被意外屏蔽
    2. 中断服务程序中陷入了一些标志位查询的while(flag != xxx)死循环
    3. I2C功能系统被意外禁止
  • 非常感谢您的耐心解答!

    我大概发现了问题:示波器这边,我发现其实我已经正确RX到了第一轮的数据,最后一个byte后跟了一个NACK(即高电平),这个也符合user guide描述,没有问题。

    但是,然后过了很长时间(大约一半的RX时间)master又发送了一个read-header得到不完整的2byte,(即最后一个byte只有7bit,然后就SDA high, SCL low 持续不变了)。

    程序这边,就是停留在__bis_SR_register(LPM0_bits | GIE);等待RX中断了,

    为什么会有一个小尾巴?莫名多出来一个read-header和不完整的2byte?

    非常感谢!

  • 然后过了很长时间(大约一半的RX时间)master又发送了一个read-header得到不完整的2byte

    也就是说,之前的RX是正常的,之后某一次RX不正常?

    若是可以,能否给出示波器波形?

  • 总的图像

    正常接收9个字节,以master NACK结束,

    这个就是master私自发送读,得到2个不完整数据,破坏了状态吧?

    我即使多加一句这个UCB0CTLW1 |= UCASTP_0; 还是一样,

    谢谢!

  • UCB0CTL1 &= ~UCTR; // I2C RX
    UCB0CTL1 |= UCTXSTT; // I2C start condition
    __bis_SR_register(LPM0_bits | GIE); // Enter LPM0 w/ interrupt

    如果有前面2行,第三行是不是一定会被执行跳转去执行RX中断?

    现在问题就是while(1)第二遍就停留在这里了?

    谢谢!

  • 我如果注释掉RX部分,while里只要TX,可以连续不断发送2 byte commands 出去,TX中断来回循环很顺利。

  • 如果有前面2行,第三行是不是一定会被执行跳转去执行RX中断?

    这个语句表明进入LPM0且打开了中断

    这个就是master私自发送读,得到2个不完整数据,破坏了状态吧?

    看起来是的。我目前对此没有什么想法,单纯看您程序的话,并没有发现什么问题。

  • 好的,谢谢您!我再调调看,

  • 好的,期待您的反馈