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.

[参考译文] MSP432P401R:I2C时钟挂起

Guru**** 2539500 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/580223/msp432p401r-i2c-clock-hang

部件号:MSP432P401R

我编写了一些代码,应该遵循以下方案,使用I2C与传感器通信。

我预计示波器读数为下表中的内容:

S 1. 1. 0 0 0 0 0 确认 0 0 0 0 1. 0 0 0 确认 S 1. 1. 0 0 0 0 0 R 确认 0 0 0 0 0 0 0 0 确认/确认

P

我得到的是图片上的内容:

我的理解是:

S 1. 1. 0 0 0 0 0 确认 0 0 0 0 1. 0 0 0 确认 P S 1. 1. 0 0 0 0 0 R 确认 0 0 0 0 0 0 0 0 确认 1. 1. 1. 1. 1. 1. 1.

问题/困惑的根源:

  • 时钟保持低电平,在重置之前,无法再次使用总线
  • 生成额外的时钟脉冲,但不发送停止
  • 我用一个单独的I2C设备测试了这个错误,并遇到了同样的问题

我的代码如下所示:

#include "driverlib.h"

#define I2C_PINS gPIO_PORT_P3,gPIO_PIN6 + gPIO_PIN7
#define USI_MODULE EUSCI_B2_BASE
#define slaver_address 0b110万
#define prox_register 0x08

volatile uint16_t response = 0;
volatile uint8_t lsb = 0;
volatile uint8


I2I2I = 0;I2I配置= 0


EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK时钟源
300万, // SMCLK = 3MHz
EUSCI_B_I2C_SET_DATA_RATE_100KBPS, //所需的I2C时钟为100kHz
0, //无字节计数器阈值
EUSCI_B_I2C_NO_AUTO_STOP //无自动停止
};


int main(void){

WDT_A_HoldTimer();

GPIO_setAsPeripheralModuleFunctionInputPin (I2C_PINS,GPIO主要模块功能);

/*在100kHz的频率下将I2C主设备初始化到SMCLK,没有自动停止*/
I2C_initMaster(USCI_MODULE,&i2cConfig);

/*指定从属地址*/
I2C_setSlaveAddress (USI_MODULE,SLAVE_ADDRESS);

/*将主中继器设置为传输模式*/
I2C_setMode (USI_MODULE,EUSCI_B_I2C_Transmit_MODE);

/*启用I2C模块以启动操作*/
I2C_enableModule (USI_MODULE);

while (I2C_isBusBusy (USI_MODULE)== EUSCI_B_I2C_BUS_BUS_BUSY);

I2C_masterSendSingleByte (USI_MODULE,PROx_REGISTER);
I2C_masterReceiveStart (USI_MODULE);
LSB = I2C_masterReceiveMultiByteNext(USCI_MODULE);
MSB += I2C_masterReceiveMultiByteNext(USCI_MODULE);
I2C_masterReceiveMultiByteStop (USI_MODULE);
响应=(MSB <<8)|(lsb和0xff);

while (1);
}

如果有人能澄清出什么错的话,我将非常感谢。

谢谢!

基督教

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

    基督教,

    我尝试使用我们的传感器BoosterPack重新创建您的问题。  我成功地重现了问题。  

    我添加了以下行:

    while ( I2C_masterIsStopSent(USCI_MODUL)!= EUSCI_B_I2C_STOP_SEND_COMPLETE );

    在此行之后:


    I2C_masterSendSingleByte (USI_MODULE,PROx_REGISTER);


    它似乎给了我一个丢失的nack和stop (P)。  这对您也有效吗?

    但是,我仍然发现代码存在问题。  当我单步浏览程序时,我看到lsb ( 但不总是msb)的值正确加载;但当我让它运行然后暂停时,我注意到lsb和msb仍然等于0。

    您是否看到相同的问题?  我注意到我遇到的所有示例代码都使用中断,而不像您那样尝试轮询。  我不知道这是什么原因,但我会研究一下。  我可能建议您中断基于代码的代码而不是轮询,除非您有理由严格地坚持轮询。

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

    好的。  我将此代码更改为使用中断,正如我在上一篇文章中建议 的那样,使用此示例代码作为基础。  我认为这对您会有所帮助。  请注意,我使用的是USI_B1,因此您必须纠正,在宏定义和ISR中都有几个引用B1的位置。  另外,值得注意的是,我使用的示例代码设置了在接收最后一个字节时以这种方式接收到第二个到最后一个位之后的停止位, TXSTP位已设置,nack和Stop(P)将在最终RX发生后设置。

    代码如下:

    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    
    #define I2C_PINS gPIO_PORT_P6,gPIO_PIN4 + gPIO_PIN5
    #define USI_MODULATE_SCI_B1_BASE
    #define slaver_address 0b100万
    #define prox_register 0x03
    
    volatile uint16_t response =0;volatile
    fut_0 = 0;
    
    易失
    性= 0;易失性指数0 = 0;易失性指数= 0;易失性0;易失性0 = 0;易失性指数= 0;易失性指数= 0;易失性0;易失性指数
    /* I2C主配置参数*/
    const eUSI_I2C_MasterConfig i2cConfig ={
    
    EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK时钟源
    300万, // SMCLK = 3MHz
    EUSCI_B_I2C_SET_DATA_RATE_100KBPS, //所需的I2C时钟为100kHz
    0, //无字节计数器阈值
    EUSCI_B_I2C_NO_AUTO_STOP //无自动停止
    };
    
    int main(void){
    
    WDT_A_HoldTimer();
    
    GPIO_setAsPeripheralModuleFunctionInputPin (I2C_PINS,GPIO主要模块功能);
    
    I2C_DisableModule (USI_MODULE);//更改1
    /*在100kHz的频率下将I2C主设备初始化到SMCLK,没有自动停止*/
    I2C_initMaster(USCI_MODULE,&i2cConfig);
    
    /*指定从属地址*/
    I2C_setSlaveAddress (USI_MODULE,SLAVE_ADDRESS);
    
    /*将主中继器设置为传输模式*/
    I2C_setMode (USI_MODULE,EUSCI_B_I2C_Transmit_MODE);
    
    /*启用I2C模块以启动操作*/
    I2C_enableModule (USI_MODULE);
    
    /*启用并清除中断标志*/
    I2C_clearInterruptFlag (USI_MODULE,EUSCI_B_I2C_Receive_INTERRUPT0);
    //启用主接收中断
    I2C_enableInterrupt (USI_MODULE,EUSCI_B_I2C_Receive_INTERRUPT0);
    interrupT_enableInterrupt (INT_EUSCIB1);
    
    while (I2C_isBusBusy (USI_MODULE)== EUSCI_B_I2C_BUS_BUS_BUSY);
    
    I2C_masterSendSingleByte (USI_MODULE,PROx_REGISTER);
    /*等待字节发送后再接收。*/
    while ( I2C_masterIsStopSent(USCI_MODUL)!= EUSCI_B_I2C_STOP_SEND_COMPLETE );
    I2C_masterReceiveStart (USI_MODULE);
    
    /*等待直到收到最后一个字节*/
    while ( I2C_masterIsStopSent(USCI_MODUL)!= EUSCI_B_I2C_STOP_SEND_COMPLETE );
    
    /*等待以确保值已加载到MSB中。 */
    while (!msbCapted)
    {
    ;}
    
    
    /*交换字节顺序并加载到响应*/
    响应=(MSB <<8)|(lsb和0xff);
    
    while (1);
    }/*********************************************************************************
    
    
    * eUSCIB0 ISR。 接收操作在此ISR内进行。
    ***************** /
    void EUSCIB1_IRQHandler (void)
    {
    UINT_FAST16_t状态;
    
    状态= I2C_getEnabledInterruptStatus(USCI_MODULE);
    MAP_I2C_clearInterruptFlag (USI_MODULE,STATUS);
    
    /*将字节接收到接收缓冲区。 如果我们已收到所有字节,
    *发送停止条件*/
    IF (状态和EUSCI_B_I2C_Receive_INTERRUPT0)
    {
    IF (xferIndex == 0)
    {
    I2C_masterReceiveMultiByteStop (USI_MODULE);
    LSB = I2C_masterReceiveMultiByteNext(USCI_MODULE);
    xferIndex++;
    }
    else if (xferIndex == 1)
    {
    MSB = I2C_masterReceiveMultiByteNext(USCI_MODULE);
    I2C_DisableInterrupt (USI_MODULE,EUSCI_B_I2C_Receive_INTERRUPT0);
    msbCapted =真;
    }
    }
    }
    
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Christian,我有一段时间没有听到您的消息。 希望这意味着您能够使这项工作正常吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    John,您好!
    很抱歉回复延迟。 我使用了您之前提供的代码(但有不同的针脚和eusci模块),我仍然在第7位上遇到时钟拉伸问题,但它在第二个接收位上发生,而不是产生额外的时钟脉冲。 我将进行一些进一步的测试,看看我是否可以隔离问题。