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.

[参考译文] MSP430FR5969:如何进入中断服务程序、卡在__ bis_SR_register (LPM3_bits + GIE)中;

Guru**** 2589275 points
Other Parts Discussed in Thread: MSP-EXP430FR5969

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/624121/msp430fr5969-how-to-enter-interupt-service-routine-stuck-in-__bis_sr_register-lpm3_bits-gie

器件型号:MSP430FR5969
主题中讨论的其他器件:MSP-EXP430FR5969

您好!

我不熟悉 MSP430技术和微控制器编程。 目前我正在处理 i2c、但我遇到了这个问题。 如果我错了、请不要太苛刻、请纠正我的错误、但 shoud 不 是_ bis_sr_register (LPM3_bits + GIE); 让程序进入 ISR? LPM0和 LPM1 (2、3、4)之间的区别是什么?

我添加了输出命令、这样我就可以在控制台中看到代码被卡住了、并且始终在  shoud 处出现残桩、而不 是_ bis_SR_register (LPM3_bits + GIE);

/*
main.c
*/

#include 
#include 

unsigned char SlaveAddress = 0x76;
unsigned char TXByteCtr;
unsigned char RXByteCtr;
unsigned char * PTxData;
unsigned char * PRxData;

unsigned char RXData[6];
unsigned char TXDataArr[3];

void initI2C (void);
void RXdata (unsigned char reg_addr、unsigned char RX_BYTE);
void TXdata (unsigned char TX_BYTE);
void IIC_TX (void);
void IIC_RX (void);void start_TX
(void start_TX (void);void start_TX (void)

void init_slave ();
void read_slave ();

int main (void)
{
WDTCTL = WDTPW | WDTHOLD;

// I/O init
//禁用 GPIO 上电默认高阻抗模式以激活
//先前配置的端口设置
PM5CTL0 &=~LOCKLPM5;
P1SEL1 |= BIT7 | // I2C 引脚
//

initI2C ();

__bis_sr_register (GIE);

init_slave ();

read_slave ();

while (1)
{
//read_slave();
}
//////////////////////////////////////

I2C B0/////////////////////////////////////////////
#if defined (__TI_Compiler_version__)|| defined (__IAR_systems_icc_)
#pragma vector = USCI_B0_vector
__interrupt void USCI_B0_ISR (void)
#Elif defined (__GNU__)
void __attribute__(interrupt (USCI_B0_vector)#USCI_ISR vector (void

)(void)#USCI_ISR vector 0!
#endif
{
("输入的中断服务例程\n");
switch (__evo_in_range (UCB0IV、0x1E)){
情况0x00:中断;//向量0:无中断中断中断;
情况0x02:break;

情况0x04:
UCB0CTLW0 |= UCTXSTT;//如果 NACK,则重新发送开始
中断;//向量4:NACKIFG 中断;

情况0x06:中断;//向量6:STTIFG 中断;
情况0x08:中断;//向量8:STPIFG 中断;
情况0x0a:中断;//向量10:RXIFG3中断;
情况0x0c:中断;//向量14:TXIFG3中断;
情况0x0E:中断;//向量16:RXIFG2中断;
情况0x10:中断;//向量18:TXIFG2中断;
情况0x12:中断;//向量20:RXIFG1中断;
情况0x14:中断;//向量22:TXIFG1中断;

情况0x16://向量24:RXIFG0中断;
* PRxData++= UCB0RXBUF;//获取 RX 数据
RXByteCtr --;
if (RXByteCtr = 0){
_DELAY_CYCLES (30);
UCB0CTLW1 |= UCSWACK;
UCB0CTLW0 |= UCTXACK;
UCB0CTLW0 |= UCTXSTP;
}
否则{
UCB0IFG &=~UCRXIFG0;
_BIC_SR_REGISTER_ON_EXIT (LPM3_BITS);
}
中断;

情况0x18:
if (TXByteCtr){//检查 TX 字节计数器
UCB0TXBUF =* PTxData++;//加载 TX 缓冲区
TXByteCtr --;
}
否则{
UCB0CTLW0 |= UCTXSTP;// I2C 停止条件
UCB0IFG &=~UCTXIFG;//清除 USCI_B0 TX 内部标志
__BIC_SR_REGISTER_ON_EXIT (LPM3_BITS);//退出 LPM0
}
中断;//向量26:TXIFG0中断;

情况0x1A:
UCB0IFG &=~UCBCNTIFG;
中断;//向量28:BCNTIFG 中断;

情况0x1c:中断;//向量30:时钟低电平超时中断;
情况0x1E:中断;//向量32:第9位中断;
默认值:break;
}
}

void initI2C (void){
PUT ("初始化 i2c");
UCB0CTLW0 |= UCSWRST;//将 eUSCI_B 置于复位状态
UCB0CTLW0 |= UCMODE_3 | UCMST | UCSSEL_2 | UCSYNC;// I2C 模式、主模式、SMCLk //+ UCSSEL_2 | UCSYNC
UCB0CTLW1 |= UCASTP_2;//生成自动停止
//到达 UCB0TBCNT 后
UCB0BRW = 0x20;// 12
UCB0CTLW0 &=~ UCSWRST;//清除复位寄存器
UCB0IE |= UCNACKIE | UCBCNTIE;
PUT ("初始化 i2c 成功");
}

void TXdata (unsigned char TX_BYTE){
PUT ("调用 IIC_TX");
IIC_TX();
PUPS ("从 IIC_TX 返回");
PTxData =(unsigned char *)&TXDataArr;// TX 数组起始地址
printf ("PTxData =%d"、TXDataArr[0]);
TXByteCtr = TX_BYTE;//加载 TX 字节计数器
printf ("TXByteCtr =%d\n"、TX_BYTE);
PUT ("调用 start_tx");
START_TX();
}
void IIC_TX (void){
PUT ("输入的 IIC_TX \n");
printf ("从器件地址=%d \n"、SlaveAddress);
UCB0I2CSA =从地址;
PUT ("启用 TX 中断");
UCB0IE |= UCTXIE0;//启用 TX 中断
Put ("TX 中断启用\n");
放置("退出 IIC_TX\n");
}

void start_TX (void){
放置("输入的 start_tx \n");
while (UCB0CTLW0 & UCTXSTP);//确保发送了 STOP 条件
放置("已发送停止条件\n");
放置("启动 i2c TX\n");
UCB0CTLW0 |= UCTR + UCTXSTT;// I2C TX,启动条件
PUT ("满足启动条件\n");
放置("输入中断服务例程\n");
_bis_SR_register (LPM3_bits + GIE);//输入 LPM0、带中断
PUT ("退出 start_tx\n");
}

void init_slaver(){
放置("正在初始化传感器");
TXDataArr[0]= 0xF4;
TXDataArr[1]= BIT5 + BIT2 + BIT1;
TXDATA (2);
PUT ("初始化传感器成功");
}

void read_slave(){
放置("从传感器读取数据...");
RXDATA (0xFA、2);
PUT ("数据读取");

}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我建议:从 LPM0开始、直到您使其他所有器件可靠工作。

    在 LPM0时、仅 CPU 被关闭。 连续升高的 LPM (LPM1/2/3/4)会关闭更多的 MCU 功能(主要是时钟)、到 LPM4几乎没有任何运行。 我忘记了 FR5xx 系列上的 LPM3不运行的内容、不过您应该能够从用户手册中提取这些内容。 同时、只需使用 LPM0即可避免这个问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Krisjanis、

    除了 Bruce 已经说过的、您的 eUSCI 外设由在 LPM3中被关闭的 SMCLK 供电。 在您进入 LPM3之前、可能尚未完全发送起始位和从地址、因此可能会关闭生成 I2C 时钟输出的 SMCLK。 您也可以过早地将 GIE UCTXIE0置位(因此在启动 I2C 序列之前会发生中断)、并且永远不会置位 UCRXIE0。 PUT 和 printf 函数也可能会产生干扰。

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

    1) 1)如果我以后不将主器件用作接收器、那么我是否不启用 UCRXIE0?

    2) 2)如果我不只需要进入 ISR shuld、那么我在不需要省电的情况下使用 LPM。

    3) 3)如果启用 LPM、我无法确定代码的错误、我会卡在__ bis_SR_register (LPM0_bits + GIE)中-这次我在 进入 ISR 之前启用了 UCTXIE0。 如果我不启用 LPM、则会跳过 ISR  

    #include 
    #include 
    
    void initial_master (void);
    void initialize_slave (void);
    void transmit _data (unsigned char TX_BYTE);
    void start_tx (void);
    
    const unsigned char slave_address = 0x76;
    
    unsigned char Rx_BYTE_CTR = 0;
    unsigned char TX_BYTE_CTR = 0;
    unsigned char Rx_data = 0;unsigned char TX_data[]
    = 0;
    
    unsigned ch
    
    //const unsigned char TXData[]={0xA1、0xB1、0xC1、0xD1};
    //const unsigned char SlaveAddress[]={0x0A、0x0B、0x0C、0x0D};
    
    int main (void)
    {
    TX_DATA[0]= 0xF4;
    TX_DATA[1]= BIT5 + BIT2 + BIT1;
    WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
    
    P1SEL1 |= BIT6 | BIT7;//设置 i2c 引脚
    //禁用 GPIO 加电默认高阻抗模式,以激活
    //先前配置的端口设置
    PM5CTL0 | BIT1;
    
    
    
    
    //在初始化 PM1时(~1)
    Initialize_SLAVE ();
    
    //_DELAY_CYCLLES (2000);
    // UCB0I2CSA = SLAVE_ADDRESS;
    // TX_BYTE_CTR = 1;
    
    // while (UCB0CTL1 & UCTXSTP); //确保发送停止条件
    // UCB0CTLW0 |= UCTR | UCTXSTT; // I2C 启动条件
    
    
    //_ bis_SR_register (GIE); //输入 LPM0,带中断
    }
    
    //返回0;
    }
    
    #if defined (__TI_Compiler_version__)|| defined (__IAR_systems_ICC__)
    #pragma vector = USCI_B0_vector
    __interrupt void USCI_B0_ISR (void)
    #Elif defined (__GNU__)#pragma vector = USCI_B0_vector
    _(interrupt (USCI_B0_ISR
    
    )#void) USCI_COVERSI_0!
    #endif
    {
    switch (__even_in_range (UCB0IV、USCI_I2C_UCBIT9IFG))
    }
    USCI_NONE 案例: 中断; //向量0:无中断
    USCI_I2C_UCALIFG 案例:中断; //向量2:ALIFG
    USCI_I2C_UCNACKIFG 案例: //向量4:NACKIFG
    UCB0CTL1 |= UCTXSTT; // I2C 启动条件
    中断;
    案例 USCI_I2C_UCSTTIFG:中断; //向量6:STTIFG
    案例 USCI_I2C_UCSTPIFG:中断; //向量8:STPIFG
    USCI_I2C_UCRXIFG3案例:中断; //向量10:RXIFG3
    USCI_I2C_UCTXIFG3案例:中断; //向量12:TXIFG3
    USCI_I2C_UCRXIFG2案例:中断; //向量14:RXIFG2
    USCI_I2C_UCTXIFG2案例:中断; //向量16:TXIFG2
    USCI_I2C_UCRXIFG1案例:中断; //向量18:RXIFG1
    USCI_I2C_UCTXIFG1案例:中断; //向量20:TXIFG1
    USCI_I2C_UCRXIFG0案例: //向量22:RXIFG0
    RX_DATA = UCB0RXBUF; //获取 RX 数据
    _BIC_SR_REGISTER_ON_EXIT (LPM0_Bits | GIE);//退出 LPM0
    中断;
    USCI_I2C_UCTXIFG0案例: //向量24:TXIFG0
    IF (TX_BYTE_CTR) //检查 TX 字节计数器
    {
    int i = 0;
    UCB0TXBUF =&TX_DATA; //加载 TX 缓冲区
    TX_BYTE_CTR--; //测量 TX 字节计数器
    i++;
    }
    其他
    {
    UCB0CTLW0 |= UCTXSTP; // I2C 停止条件
    UCB0IFG &=~UCTXIFG; //清除 USCI_B0 TX int 标志
    __BIC_SR_REGISTER_ON_EXIT (LPM0_Bits | GIE);//退出 LPM0
    }
    中断;
    USCI_I2C_UCBCNTIFG 案例: //向量26:BCNTIFG
    P1OUT ^= BIT0; //在 P1.0上切换 LED
    中断;
    USCI_I2C_UCCLTOIFG 案例:中断; //向量28:时钟低电平超时
    USCI_I2C_UCBIT9IFG 案例:中断; //向量30:第9位
    默认值:break;
    }
    
    
    
    void initialize_master (void){
    UCB0CTLW0 |= UCSWRST;//将 eUSCI_B 置于复位状态
    UCB0CTLW0 |= UCMODE_3 | UCMST | UCSSEL_2 | UCSYNC;// I2C 模式、主模式、SMCLk //+ UCSSEL_2 | UCSYNC
    UCB0CTLW1 |= UCASTP_2;//生成自动停止
    //到达 UCB0TBCNT 后
    UCB0BRW = 0x20;// 12
    UCB0CTLW0 &=~ UCSWRST;//清除复位寄存器
    UCB0IE |= UCNACKIE | UCBCNTIE;
    }
    
    void initialize_slave (void){
    TX_DATA[0]= 0xF4;
    TX_DATA[1]= BIT5 + BIT2 + BIT1;
    Transmit 数据(2);
    }
    
    void transmit 数据(unsigned char TX_BYTE){
    UCB0I2CSA = SLAVE_ADDRESS;
    TX_BYTE_CTR = TX_BYTE;//加载 TX 字节计数器
    START_TX();
    }
    
    void START_TX (void){
    // while (UCB0CTLW0和 UCTXSTP);//确保发送了停止条件
    UCB0CTLW0 |= UCTR + UCTXSTT;// I2C TX,启动条件
    UCB0IE |= UCTXIE0;//启用 TX 中断
    _DELAY_CYCLES (2000);
    _bis_SR_register (LPM0_bits | GIE);
    _DELAY_CYCLES (2000);
    //_bis_SR_register (LPM0_Bits + GIE);//输入 LPM0、带中断
    } 

    4) 4)我设置了多大的延迟是否重要?

    我提出这些问题是因为我查看了 TI 示例、不知道为什么会使用 LPM  

    5) 5)我的项目设置或硬件本身是否存在问题?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我假设您希望收到一些消息、因为您在 RXIFG0情况下有代码、因此需要在某个点设置 RXIE0。
    2/3. 您不会卡在_bis_SR_register (LPM0_bits + GIE)中、而是 PC 处于睡眠状态、并且从未进入 ISR、因此不会执行任何代码。 在 UCTXSTT 之前启用 TXIE0。
    不可以、这是用于调试的。
    5.如果您没有看到与 TI 提供的示例进行任何通信,那么硬件可能会出现问题,您是否在 I2C 线路上使用了适当的上拉电阻(10kOhm)? 您能否在示波器或逻辑分析仪上查看它们?

    此致、
    Ryan
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    //*
    #include 
    //#include 
    
    void char_master (void);
    void initialize_slave (void);
    void transmit _data (unsigned char TX_BYTE);
    void start_TX (void);
    
    const unsigned char slave_address = 0x76;// ws 0x46
    
    unsigned char rx_Byte_CTR = 0;
    unsigned char tx_Byte_CTR = 0;
    unsigned char trx_data = 0;unsigned char tx
    =
    
    0;unsigned char tx char
    
    //const unsigned char TXData[]={0xA1、0xB1、0xC1、0xD1};
    //const unsigned char SlaveAddress[]={0x0A、0x0B、0x0C、0x0D};
    
    int main (void)
    {
    TX_DATA[0]= 0xF4;
    TX_DATA[1]= BIT5 + BIT2 + BIT1;
    WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
    
    
    P1SEL1 |= BIT6 | BIT7;//设置 i2c 引脚
    P1REN |= BIT6 | BIT7;//上拉
    //禁用 GPIO 加电模式 PPM5LO0
    
    ~激活先前配置的 LPM5高阻抗设置;//激活 LPM5CTLPM0
    
    
    
    
    while (1)
    {
    initialize_master();
    Initialize_SLAVE ();
    
    //return 0;
    }
    
    #if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
    #pragma vector = USCI_B0_Vector
    __interrupt void USCI_B0_ISR (void)
    #Elif defined (__GISR__)#pragma COMPLETE_TRIBUCI_TRIBU0
    
    
    (void)(USCI_COMPLETE_COMPLETE_TRUSIR_)(void 0_COMPLETE_ERROR)(USCILE_INTERRUPTIC_0_COMPLETE)
    #endif
    {
    
    switch (__even_in_range (UCB0IV、USCI_I2C_UCBIT9IFG))
    }
    USCI_NONE 案例: 中断; //向量0:无中断
    USCI_I2C_UCALIFG 案例:中断; //向量2:ALIFG
    USCI_I2C_UCNACKIFG 案例: //向量4:NACKIFG
    UCB0CTL1 |= UCTXSTT;//如果 NACK,则重新发送开始
    中断;
    案例 USCI_I2C_UCSTTIFG:中断; //向量6:STTIFG
    案例 USCI_I2C_UCSTPIFG:中断; //向量8:STPIFG
    USCI_I2C_UCRXIFG3案例:中断; //向量10:RXIFG3
    USCI_I2C_UCTXIFG3案例:中断; //向量12:TXIFG3
    USCI_I2C_UCRXIFG2案例:中断; //向量14:RXIFG2
    USCI_I2C_UCTXIFG2案例:中断; //向量16:TXIFG2
    USCI_I2C_UCRXIFG1案例:中断; //向量18:RXIFG1
    USCI_I2C_UCTXIFG1案例:中断; //向量20:TXIFG1
    USCI_I2C_UCRXIFG0案例: //向量22:RXIFG0
    RX_DATA = UCB0RXBUF; //获取 RX 数据
    _BIC_SR_REGISTER_ON_EXIT (LPM0_Bits | GIE);//退出 LPM0
    中断;
    USCI_I2C_UCTXIFG0案例: //向量24:TXIFG0
    IF (TX_BYTE_CTR) //检查 TX 字节计数器
    {
    int i = 0;
    UCB0TXBUF = TX_DATA[i]; //加载 TX 缓冲区
    TX_BYTE_CTR--; //测量 TX 字节计数器
    i++;
    }
    其他
    {
    UCB0CTLW0 |= UCTXSTP; // I2C 停止条件
    UCB0IFG &=~UCTXIFG; //清除 USCI_B0 TX int 标志
    __BIC_SR_REGISTER_ON_EXIT (LPM0_Bits | GIE);//退出 LPM0
    }
    中断;
    USCI_I2C_UCBCNTIFG 案例: //向量26:BCNTIFG
    P1OUT ^= BIT0; //在 P1.0上切换 LED
    中断;
    USCI_I2C_UCCLTOIFG 案例:中断; //向量28:时钟低电平超时
    USCI_I2C_UCBIT9IFG 案例:中断; //向量30:第9位
    默认值:break;
    }
    
    
    
    void initialize_master (void){
    //printf ("正在初始化 i2c\n");
    UCB0CTLW0 |= UCSWRST;//将 eUSCI_B 置于复位状态
    UCB0CTLW0 |= UCMODE_3 | UCMST | UCSSEL_2 | UCSYNC;// I2C 模式、主模式、SMCLk //+ UCSSEL_2 | UCSYNC
    UCB0CTLW1 |= UCASTP_2;//生成自动停止
    //到达 UCB0TBCNT 后
    UCB0BRW = 0x20;// 12
    UCB0CTLW0 &=~ UCSWRST;//清除复位寄存器
    UCB0IE |= UCNACKIE | UCBCNTIE;
    //printf ("正在初始化 i2c 成功\n");
    }
    
    void initialize_slave (void){
    UCB0I2CSA = SLAVE_ADDRESS;
    TX_DATA[0]= 0xF4;
    TX_DATA[1]= BIT5 + BIT2 + BIT1;
    Transmit 数据(2);
    }
    
    void transmit 数据(unsigned char TX_BYTE){
    TX_BYTE_CTR = TX_BYTE;
    START_TX();
    }
    
    void START_TX (void){
    while (UCB0CTLW0 & UCTXSTP);//确保发送了 STOP 条件
    UCB0IE |= UCTXIE0;//启用 TX 中断
    UCB0CTL1 |= UCTR + UCTXSTT;// I2C TX、启动条件
    _DELAY_CYCLES (2000);
    _bis_SR_register (LPM0_bits | GIE);
    }
    
    
    

    我将 TXIE0放在 UCTXSTT 之前、就像您建议的那样

    我还启用了上拉 电阻(我不知道我是否正确) P1REN |= BIT6 | BIT4;//上拉电阻

    我看了示波器、可以看到从器件未被应答。  而不是。 我将 MSP-exp430fr5969 Launchpad 与传感器 Booster Pack 搭配使用、虽然读数是 P1.6和 P1.7、但我的 Launchpad 将 ASD 和 SLC 分别作为 P3.5和 P3.6。  "%20="">" target="_blank">

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    与内部相比、您需要外部上拉电阻。 在没有任何器件连接到 I2C 引脚的情况下、您不会获得从器件确认。

    此致、
    Ryan