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.

[参考译文] MSP430FR50431:I2C 主设备从不调用 ISR

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1031041/msp430fr50431-i2c-master-never-calls-isr

器件型号:MSP430FR50431

大家好、

我正在处理 MSP430上的 i2c 主器件通信。 问题是、即使在我设置  UCB1IE |=(UCTXIE0 | UCRXIE0 | UCNACKIE | UCALIE)时、也不会调用 ISR、即使它应该被启用。  

由于在此页中插入代码会导致错误、因此所有代码 都将上传到此列表。  它使用 来自该 gist的 delay()和 millis()函数。

感谢您的任何建议:)

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

    您好、Jan、

    在 i2c_master.c 的第132行(在 i2c_master_init ()中)中、根据器件数据表中的输入/输出图部分、我将使用 GPIO_secondary module_function 而不是 primary。

    如果您仍然遇到问题、我会尝试其他一些操作:

    -检查 SCL 和 SDA 是否都是通过逻辑分析仪/示波器上拉的

    -验证主设备是否使用逻辑分析仪/示波器发送正确的地址

    谢谢、

    王国新

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

    当 UCSWRST=1时、设置 IE 无效。  

    更一般的情况是、将 USCI 复位(UCSWRST->1)会将 IE 寄存器清零。  通常情况下、IES 会根据事务类型(R/W)进行设置、因此这通常不会妨碍执行。  (是的、这在使用 UCASTP.时有点麻烦。)  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="489743" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1031041/msp430fr50431-i2c-master-never-calls-isr/3811891 #3811891"]在 i2c_master.c 行132 (在 i2c_master_init ()中)中,我将根据器件数据表中的输入/输出图部分使用 GPIO_secondary module_function 而不是 primary。

    出于某种原因、我对 GPIO_PORT_P3使用了 MODULE_FUNCTION、而不是 GPIO_PORT_P5。

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

    感谢您的回复 Bruce、

    我更新 了要点

    1) 1) IES 在 UCSWRST 之后置1

    2) 2)自动停止被移动到单独的函数 auto_stop_set、该函数保留了 IES。

    现在、进入 ISR。 但只能一次。 UCB1IV 等于 UCSTTIFG。 它发生在 i2c_master_wait()函数的开头。 是否有可能、这是因为禁用中断的 Millis ()函数可能会对 I2C ISR 造成一些干扰? 它在 while 循环中被调用、因此可能没有足够的时间来启动另一个中断...

    此外、我甚至不知道如何处理 UCSTTIFG。 我是否应该像这样发送第一个字节:

    if (TX_buffer && TX_buffer_remain_length){

      UCB1TXBUF = TX_BUFFER[--TX_BUFFER_LEASE_LENGTH];

    还是等待发送起始值

    while (UCB1CTLW0和 UCTXSTT);

    还是将其全部忽略并等待 eUSCI 完成这项工作?

    为什么为  UCSTTIFG 调用 ISR? 但是、I 设置  bit_clear (UCB1IE、UCSTPIE | UCSTTIE);会禁用此中断。

    编辑:

    逻辑分析仪显示、SDA 和 SCL 线路都保持高电平。 不发送 START 信号。

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

    >案例 UCSTTIFG:

    您不会获得 UCSTTIFG 矢量值、因为您尚未启用 UCSTTIE。

    UCB1IV 中的值不是 IFG (位)值、而是小整数指数。 [参考用户指南(SLAU367P)表32-20]您看到的2实际上是 UCIV_UCALIFG。

    我不知道为什么你会在单主控总线上获得这个。 (事实是众所周知的、我从未设计过多主控总线、因此、虽然我了解仲裁机制、但我 不知道 ALIFG 的工作方式。) 我的第一个想法是暂时不设置 UCALIE、看看你能达到多远。  

    您使用的是什么从器件?

    [编辑:黑暗中的一个镜头:如果 UCMM = 0、ALIFG 可能始终置1? (我在随机时间看到过它、但从未进行过调查。) 尝试设置 UCMM = 1。]

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="47378" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1031041/msp430fr50431-i2c-master-never-calls-isr/3813101 #3813101"]由于尚未启用 UCSTTIE,因此无法获取 UCSTTIFG 矢量值。[/quot]

    是的、这正是问题的关键。 我正在混合 UCIV__* IFG 值。

    我再次使用最新的更改更新了列表 [链接]。 现在、出于 某种原因、我得到的是 UCIV_UCNACKIFG。 但是、我看不到在逻辑分析仪上传输的任何起始信号或器件地址。 可能我在硬件方面遇到了更深层次的问题。  

    是否可以在第一次调用 Millis (包含__ENABLE_INTERRUPT ()的调用)之前禁用中断,从而在 调试器中看不到以前的 TX 中断? 每次我单步执行 程序时,  i2c_master_wait 中调用 millis()函数后,i2c_isr ()就会弹出。

    [引用 userid="47378" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1031041/msp430fr50431-i2c-master-never-calls-isr/3813101 #3813101"]

    您使用的是什么从器件?

    [/报价]

    我尝试了 VEML60 [数据表] RGBW 传感器 和 CAT24 [数据表] EEPROM 模块。 都以  UCIV__UCNACKIFG 结束。  

    我将尝试将一些 I2C 器件直接连接到 launchpad 而不是自定义 HW、以确保其不会出现 HW 问题。

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

    MSP430启动时禁用中断(GIE=0)。 这与 Cortex-M 器件等不同。 如果 main()不是__enable_interrupt (),则第一次调用 Millis ()将会。

    我想我没有看到 I2C 在没有任何总线活动的情况下生成 NACK。 我的第一个怀疑是我的范围,但我把一切都归咎于我的范围(:-))。

    一个常见的错误是使用 SLA (从器件地址)字节(左移)代替 I2C 地址。 对于 VEML60、您应该使用0x10 [数据表第7页]和 CAT24 0x50 (A0-A2未连接)。 [数据表第5页]

    未经请求:是的、Millis 可能不应任意启用中断。 头文件中的某处有一种机制,用于捕获 SR (GIE)并恢复它。 就个人而言、我将使用投票循环(阅读两个字、直到高半字同意)。

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

    您好、Jan、

    我认为由于 send_start()例程中的第75行和第76行,您在任何其他总线活动(启动等)之前会遇到问题。 您在第75行的注释表明您正在尝试清除 NACK 中断标志、但我看到您在发送 START 之前正在第76行中使用 bit_set (...、UCNACKIFG)。

    谢谢、

    王国新

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

    感谢大家。 您指出了代码中的另一个错误。

    [引用 userid="47378" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1031041/msp430fr50431-i2c-master-never-calls-isr/3813351 #3813351]MSP430启动时禁用中断(GIE=0)。 这与 Cortex-M 器件等不同。 如果 main()不是__enable_interrupt (),则第一次调用 Millis ()将会。

    我现在在 main()中启动中断而 millis()函数不再触及中断。

    [引用 userid="47378" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1031041/msp430fr50431-i2c-master-never-calls-isr/3813351 #3813351]\n 一个常见错误是使用 SLA (从器件地址)字节(向左移位)代替 I2C 地址。 对于 VEML60、您应该使用0x10 [数据表第7页]和 CAT24 0x50 (A0-A2未连接)。 [数据表第5页][/引述]

    我仔细检查了地址、我正在使用这些地址。 现在我要坚持使用 CAT24、它的运行应该更简单-只需读取和写入即可。 地址设置为 0x50

    CAT24的写入函数如下:

    #define DEVICE_ADDRESS (0x50)
    
    // Parameter is memory address and it's value
    error cat24_write(uint8_t address, uint8_t value) {
        error err = ERROR_FAIL;
    
        uint8_t buffer[] = {
            address,
            value
        };
    
        err = i2c_master_write(EEPROM_ADDRESS, buffer, sizeof(buffer), I2C_SEND_STOP);
        RET_IF_FAIL(err);
    
        err = i2c_master_wait(1000);    // This ends with ERROR_I2C_TIMEOUT
        return err;
    }

    [引用 userid="47378" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1031041/msp430fr50431-i2c-master-never-calls-isr/3813351 #3813351"]未经请求:是的、Millis 可能不应任意启用中断。 头文件中的某处有一种机制,用于捕获 SR (GIE)并恢复它。 个人而言、我将使用投票循环(阅读两个字、直到高半字同意)。[/引述]

    您是否会这么善良、并向我介绍有关投票循环的一些资源? 为什么环路周期之间的上8位不匹配? 我不应该检查整个值吗?

    [引用 userid="489743" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1031041/msp430fr50431-i2c-master-never-calls-isr/3813379 #3813379]\n 由于 send_start()例程中的第75行和第76行,我认为您在任何其他总线活动(启动等)之前会遇到问题。 您在第75行的注释表明您正在尝试清除 NACK 中断标志、但我看到您在发送开始前正在第76行中使用 bit_set (...、UCNACKIFG)。[/quot]

    是的、就是这样。 我删除了它。 现在、我回到了起点。 I2C ISR 不会被调用一次。

    我在调试器中浏览了代码并观察了寄存器值。 这是  i2c_master_write()之后的状态

    UCB1CTLW0 = 0x0F92 (= UCTXSTT | UCTR | UCSSEL_2 | UCSYNC |  UCMODE_3 | UCMST)
    UCB1CTLW1 = 0x0 (I turned off automatic STOP generation for now)
    UCB1BRW = 0x000A (= 10, to get 100kHz)
    UCB1STATW = 0x0010 (= I2C bus is busy)
    UCB1TXBUF = 0x0 (= ISR was not called yet, so there is no data to be sent)
    UCB1RXBUF = 0x0 (= no data to be read)
    UCB1I2CSA = 0x0050 (= slave is CAT24, with A0 - A2 pins not connected)
    UCB1IE = 0x0002 (= UCTXIE0)
    UCB1IFG = 0x0
    UCB1IV = 0x0

    出于某种原因、UCB1STATW 在   i2c_master_wait (1000)期间保持设置为 UCBBUSY。 因为它无法发送 start 以开始。 因此、我假设由于 eUSCI 无法发送 START、因此它会暂停并从不使用 UCIV__UCTXIFG0调用 ISR。

    可能是什么错误? 它是否再次出现在代码中? 还是硬件问题?


    编辑:我使用 此 driverlib 示例中的修改代码 将2个字节的数据发送到 CAT24:

    #include <driverlib.h>
    
    // CAT24 EEPROM
    #define SLAVE_ADDRESS (0x50)
    
    // Store value 0x2A on address 0x10
    uint8_t transmitData[] = {
        0x10,
        0x2A
    };
    
    int main(void) {
    
        WDT_A_hold(WDT_A_BASE);
        //Set DCO frequency to 1MHz
        CS_setDCOFreq(CS_DCORSEL_0,CS_DCOFSEL_0);
        //Set ACLK = VLO with frequency divider of 1
        CS_initClockSignal(CS_ACLK,CS_VLOCLK_SELECT,CS_CLOCK_DIVIDER_1);
        //Set SMCLK = DCO with frequency divider of 1
        CS_initClockSignal(CS_SMCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_1);
        //Set MCLK = DCO with frequency divider of 1
        CS_initClockSignal(CS_MCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_1);
    
        GPIO_setAsPeripheralModuleFunctionInputPin(
            GPIO_PORT_P5,
            GPIO_PIN6 + GPIO_PIN5,
            GPIO_SECONDARY_MODULE_FUNCTION
        );
    
        /*
         * Disable the GPIO power-on default high-impedance mode to activate
         * previously configured port settings
         */
        PMM_unlockLPM5();
    
        //Initialize Master
        EUSCI_B_I2C_initMasterParam param = {0};
        param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
        param.i2cClk = CS_getSMCLK();
        param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_100KBPS;
        param.byteCounterThreshold = 1;
        param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
        EUSCI_B_I2C_initMaster(EUSCI_B1_BASE, &param);
    
        //Specify slave address
        EUSCI_B_I2C_setSlaveAddress(EUSCI_B1_BASE,
            SLAVE_ADDRESS
        );
    
        //Set in transmit mode
        EUSCI_B_I2C_setMode(EUSCI_B1_BASE,
            EUSCI_B_I2C_TRANSMIT_MODE
        );
    
        //Enable I2C Module to start operations
        EUSCI_B_I2C_enable(EUSCI_B1_BASE);
    
        uint8_t index = 0;
        for(index = 0; index < 2; index++) {
            //Send single byte data.
            EUSCI_B_I2C_masterSendSingleByte(EUSCI_B1_BASE,
                transmitData[index]
            );
    
            //Delay until transmission completes
            while (EUSCI_B_I2C_isBusBusy(EUSCI_B1_BASE)) ;
    
            //Delay between each transaction
            __delay_cycles(50);
    
        }
    
    }

    它在线路上停止  

    while (!(HWREG16 (baseAddress + OFS_UCBxIFG)& UCTXIFG) )(来自  EUSCI_B_I2C_masterSendSingleByte 函数)。 因此、出于某种原因、不发送 START 信号...

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

    如果无法获得该初始 TXIFG、则表示总线在某种程度上卡滞。 一个主要问题是从器件将 SCL 和/或 SDA 保持在低电平、这是因为 I2C 单元需要控制总线来发出启动(或停止)信号。 尝试对从设备进行电源循环(只需拔下/重新插入 Vcc 导线)。

    CAT24声称最大电流消耗为3.5mA、因此可以使用 GPIO 引脚为其供电。 这使您可以对从器件进行电源(复位)控制、以便在程序控制下恢复。

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

    您好、Jan、

    除 Bruce 的建议之外、我还建议您查看此应用报告[链接]、了解 MSP430 MCU 常见串行通信问题的解决方案。 这里有一些使用 MSP 器件实现 I2C 的技巧。

    谢谢、

    王国新

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

    是否可能、包含以下代码的函数 PMM_unlockLPM5 ():

    void PMM_unlockLPM5 (void)
    {
    	//Direct register access to avoid compiler warning - #10420-D  
    	//For FRAM devices, at start up, the GPO power-on default 
    	//high-impedance mode needs to be disabled to activate previously 
    	//configured port settings. This can be done by clearing the LOCKLPM5
    	//bit in PM5CTL0 register
    
    	PM5CTL0 &= ~LOCKLPM5;
    }
    

    会以任何方式帮助我吗? 在过去的几天里,我做了一些更改, GPIO_setAsPeripheralModuleFunctionnOutputPin ()之后调用 PMM_unlockLPM5 ()是其中之一。 它现在似乎在工作。 i2c_master_read 和 i2c_master_write 仍然返回错误状态、但数据已正确写入和读取。 我将创建有关其余问题的单独问题。

    最终代码发布在 gist [链接]中

    感谢 。 如果没有您的帮助,我可能会将整个 MCU 设置为启动状态,并启动我自己的场:)。

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

    PMM_unlockLPM5 ()需要在某个时间/某个地方调用。 通常(类似于__ENABLE_INTERRUPT),它将由 main()调用,而不是库函数,但我在 gist 中看不到 main()。 如果您可以发布 main.c、这可能会减少猜测。