大家好、
我正在处理 MSP430上的 i2c 主器件通信。 问题是、即使在我设置 UCB1IE |=(UCTXIE0 | UCRXIE0 | UCNACKIE | UCALIE)时、也不会调用 ISR、即使它应该被启用。
由于在此页中插入代码会导致错误、因此所有代码 都将上传到此列表。 它使用 来自该 gist的 delay()和 millis()函数。
感谢您的任何建议:)
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.
大家好、
我正在处理 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 是否都是通过逻辑分析仪/示波器上拉的
-验证主设备是否使用逻辑分析仪/示波器发送正确的地址
谢谢、
王国新
出于某种原因、我对 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。]
是的、这正是问题的关键。 我正在混合 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)并恢复它。 就个人而言、我将使用投票循环(阅读两个字、直到高半字同意)。
感谢大家。 您指出了代码中的另一个错误。
[引用 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, ¶m); //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 引脚为其供电。 这使您可以对从器件进行电源(复位)控制、以便在程序控制下恢复。
是否可能、包含以下代码的函数 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 [链接]中
感谢 您:Urica Wang 和 Bruce McKenney47378。 如果没有您的帮助,我可能会将整个 MCU 设置为启动状态,并启动我自己的场:)。