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.

[参考译文] MSP430FR2433:从 bq34z100读取数据会卡在中断中、无法跳出。

Guru**** 2484615 points
Other Parts Discussed in Thread: BQ34Z100

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1226958/msp430fr2433-reading-data-from-the-bq34z100-is-stuck-in-an-interrupt-and-cannot-be-jumped-out

器件型号:MSP430FR2433
主题中讨论的其他器件:BQ34Z100

大家好、

从 bq34z100读取数据会卡在中断中、无法跳出。  

请查看以下代码:

#include <msp430fr2433.h>
#include <stdint.h>

#define DEVICE_ADDR 0x55 //Address of BQ34Z100 chip 
#define SDA_PIN BIT7 // Program the SDA data line to use pin P1.7 
#define SCL_PIN BIT6 // Program the SCL clock line to use the P1.6 pin 


//Function declaration 
void i2c_write(uint8_t reg_addr, uint8_t data);
void i2c_read(uint8_t reg_addr, uint8_t *rx, uint8_t bytes);

uint16_t soc, soh, cc, rm;

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; //Turn off the watchdog, otherwise the CPU will be reset 
// Configure the P1.6 and P1.7 pins for I2C functional mode 
P1SEL0 |= SCL_PIN | SDA_PIN;
P1SEL1 &= ~(SDA_PIN | SCL_PIN);

UCB0CTL1 |= UCSWRST; //Enables software reset 
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; //I2C master mode, synchronous communication mode 
UCB0CTL1 = UCSSEL_2 + UCSWRST; //Select SMCLK to keep the software reset 
UCB0BR0 = 12; //fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0;
UCB0I2CSA = DEVICE_ADDR; //Address of BQ34Z100 chip 
UCB0CTL1 &= ~UCSWRST; //Clear the software reset to resume operation 

//read SOC
i2c_read(0x02, (uint8_t *)&soc, 2);

//read SOH
i2c_read(0x2e, (uint8_t *)&soh, 2);

//read CC
i2c_read(0x2c, (uint8_t *)&cc, 2);

//read RM
i2c_read(0x04, (uint8_t *)&rm, 2);

return 0;
}

//Write register function 
void i2c_write(uint8_t reg_addr, uint8_t data)
{
uint8_t tx_data[2];
tx_data[0] = reg_addr;
tx_data[1] = data;

UCB0CTL1 |= UCTR + UCTXSTT; //Send the start byte and set to write mode 
while(!(UCB0IFG & UCTXIFG));
UCB0TXBUF = tx_data[0]; //Sets the register address 
while(!(UCB0IFG & UCTXIFG));
UCB0TXBUF = tx_data[1]; //Transmit data 
while(UCB0STAT & UCBBUSY); //Wait for the transfer to complete 
}

//Read register function 
void i2c_read(uint8_t reg_addr, uint8_t *rx, uint8_t bytes)
{
UCB0CTL1 |= UCTR + UCTXSTT;
while(!(UCB0IFG & UCTXIFG));
UCB0TXBUF = reg_addr; //Set the register address to be read 

//Reinitiates the start signal and prepares to receive data 
UCB0CTL1 &= ~UCTR;
UCB0CTL1 |= UCTXSTT;
while(!(UCB0IFG &=~ UCRXIFG));

uint8_t *data = rx;
int i;
for (i = 0; i < bytes-1; i++)
{
data[i] = UCB0RXBUF;

UCB0CTL1 |= UCTXACK;
while(!(UCB0IFG &=~UCRXIFG)); //Wait for a byte to be received 
}

//Determines if an ACK is also required to be sent for reading (based on the ACK returned from the slave) 
if (bytes > 1) {
data[i] = UCB0RXBUF;
UCB0CTL1
|= UCTXSTP; //Transmit stop bit flag 
} else {
UCB0CTL1
|= UCTXSTP + UCTXNACK; //There is no need to send an ACK again with only one byte 
}
}

您能帮助检查这个问题吗? 谢谢。

此致、

樱桃

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

    >#define SDA_PIN BIT7 //将 SDA 数据线路编程为使用引脚 P1.7
    >#define SCL_PIN BIT6 //对 SCL 时钟线进行编程以使用 P1.6引脚

    我阅读了数据表(SLASE59D)表6-17、UCB0SDA/SCL 位于 P1.2/P1.3上。 请尝试改用此选项。 (您可能还需要修复线路。)

    >#define SDA_PIN BIT2 //将 SDA 数据线路编程为使用引脚 P1.2
    >#define SCL_PIN BIT3 //对 SCL 时钟线进行编程以使用 P1.3引脚

    ----------------

    > while (!(UCB0IFG &=~ UCRXIFG));

    这不能做你想要的——它清除 RXIFG,然后测试是否设置了任何其他(不相关的) IFG。 请尝试改用:

    > while (!(UCB0IFG & UCRXIFG));

    读取 RXBUF 将为你清除 UCRXIFG。

    ----------------

     UCB0CTL1 |= UCTXACK;

    I2C 单元会为您执行 ACK。 我不是很确定 UCTXACK 在主模式下做了什么(如果有的话)、但我建议您删除此行。