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.
这 是九个月前在后火炉上放置的前一个线程的延续、我最终将再次查看。 我的系统使用 MSP432E401Y 通过 SPI 和 UART 接口控制和读取多个不同器件的数据。 我当前在 CPU 控制下从 SPI 器件读取数据、但 UART 速度很慢、在传输过程中无法承受 CPU 延迟、因此我使用 uDMA 将数据从传感器移动到内部存储器。
我需要在系统中添加一个温度传感器、我正在考虑使用具有 I2C 接口的 TMP117。 我购买了 TMP117 EVM、并将其用蓝色线连接到我的 MSP432板上以进行测试和代码开发。 I2C 总线也太慢、无法通过 CPU 执行传输、因此我也想使用 uDMA。 我创建了一个非常简单的项目、目标是采取婴儿措施、以获得功能齐全的解决方案。 以下是 main()例程的代码:
#include <ti/devices/msp432e4/driverlib/driverlib.h> #include "common.h" void main(void) { uint32_t g_ui32SysClock; // The system clock frequency int32_t status; tempReady = false; g_ui32SysClock = init_CLK(); // configure system clock init_GPIO(); // configure the device pins int_disable(); status = init_temp_I2C(g_ui32SysClock); // configure temperature sensor I2C interface status = init_temperature(); // initialize temperature driver parameters // the code below is used to transfer data from the TMP117 under CPU control // int_enable(); // // while(1){ // while(!tempReady); // tempReady = false; // } // end of CPU control // the code below is used to transfer data from the TMP117 under uDMA control ConfigureuDMATX(); MAP_uDMAChannelRequest(UDMA_CH23_I2C5TX); // end of uDMA control }
我的第一步 是使用 CPU 写入配置和读取/写入函数。 首先,init_temp_I2C()函数启用 I2C 外设,然后 init_temperatures ()配置 TMP117并开始数据采集。 当 TEMP_DRDY 中断触发 tempReadyFxn() ISR 读取数据时。 最后, 当 I2C 传输完成时,tempCallBack()回调会设置 tempReady 信标。 使用此代码、我可以成功地从 TMP117捕获数据。
下一步是在 I2C、TMP117和 UDMA 由 CPU 初始化后使用 UDMA 来捕获数据。 我使用 了 Resource Explorer 中的 i2c_master_dma_fifo 和 i2c_mastermode_fifodma_transfer 示例作为指南。
下面的图表解释了 TMP117的数据传输协议:
当主器件(MSP432)驱动 SDA 线路时、灰色框显示;当 TMP117驱动线路时、白色框显示。
我的数据传输比显示的要简单、因为我始终从相同的寄存器地址读取数据、每次传输都不需要发送寄存器地址。 相反、MSP432只需要通过 SDA 发送一个字节、然后 TMP117将使用两个字节进行回复。 因为传输的数据太少、我认为我不需要使用 FIFO。 TMP117以500ms 的速率进行采样、但 MSP432仅以1S 的速率记录温度数据、因此我不介意我是否覆盖尚未记录的数据。
随附的项目文件显示了我的测试的当前状态。 在这个非常简单的代码中、我使用 init_temp_I2C()和 init_temperated() 来初始化 I2C 外设和 TMP117。 接下来、我将尝试启用和配置 UDMA 外设、并从 I2C 总线发送一个字节。 函数 ConfigureuDMATX()的目的是将 uDMA 通道23映射 到 I2C5,并将 单个字节的转码器从 sendMasterTxData 指向的内存初始化为 I2C5主数据寄存器,然后我希望该数据寄存器在 I2C5SDA 上传输。
void ConfigureuDMATX(void) { MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA))){} MAP_uDMAEnable(); MAP_uDMAControlBaseSet(pui8ControlTable); MAP_uDMAChannelAssign(UDMA_CH23_I2C5TX); MAP_uDMAChannelAttributeDisable(UDMA_CH23_I2C5TX, UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); MAP_uDMAChannelControlSet(UDMA_CH23_I2C5TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_NONE | UDMA_ARB_1); MAP_uDMAChannelTransferSet(UDMA_CH23_I2C5TX | UDMA_PRI_SELECT, UDMA_MODE_AUTO, (void *)&sendMasterTxData, (void *)&I2C5->MDR, 1); MAP_uDMAChannelEnable(UDMA_CH23_I2C5TX); }
最后、我调用 map_uDMAChannelRequest (UDMA_CH23_I2C5TX)来执行传输。
很遗憾, 在执行 MAP_uDMAChannelRequest()后,我看不到 I2C 总线上的传输。
如果能帮助您解决这个问题、我将不胜感激。 我不知道我是否错误地配置了 UDMA、或者错过了一些关键的初始化 Conde。
谢谢、
-Phil
请参阅 MSP432E4 TRM 中的以下部分。
我还建议您查看 MSP432E4 SDK 中的"i2c_mastermode_fifodma_transfer"示例。
关于" map_I2CTxFIFOConfigSet()函数" map_I2CMasterIntEnableEx()函数"的内容
我的建议是、首先让示例代码 I2C1在您的器件上工作。 然后更改 I2C 通道和 DMA 通道。
伊斯天
正如我在问题中所述、 i2c_mastermode_fifodma_transfer 是我参考的两个示例之一、请参阅我在上面第四段中的说明。 正如我还说过的、我不使用 FIFO。 我的 I2C 接口已经在工作、正如我在上面所描述的那样。 我的板没有可用的 I2C1引脚、我只有一个板、因此无法运行示例代码。
是的、我知道。 我使用示例代码检查您的代码设置。 我能观察到的唯一区别是 FIFO 设置。
因为您已经使其适用于 I2C、并且无法启用 I2C1。 您能否先根据 I2C5在代码上添加 FIFO 设置以查看它是否有帮助? 与我们的示例代码相比、您对代码所做的更改很少。
谢谢、我将尝试使用 Xmit FIFO 并返回报告。
我从 i2c_mastermode_fifodma_transfer 示例开始、而不是尝试创建我自己的自定义例程。 它看起来很有希望、但只有在我运行 DMA RX 函数时设置断点时、它才有效。 如果我让它在没有断点的情况下运行、那么 I2C RX 传输会被截断。
我正在尝试简化和清理代码、然后我将在这里报告。
伊斯天
我取得了一些有希望的进展。 我从 i2c_mastermode_fifodma_transfer.c 文件开始、并对其进行了修改以满足我的需求。 最大的更改是删除 FSM、以便更轻松地遵循代码流。
要从 TMP117捕获数据、首先必须向寄存器地址0x01发送配置命令。 然后我从地址0x00读取数据。 最后、当 TMP117生成数据就绪中断时、我需要从地址0x00进行截断的 I2C 读取-其中一个仅发送读取从地址、然后 TMP117以两个字节进行响应。
在我的修改后的代码(已连接)中、我首先设置 I2C 和 UDMA 用于主机传输。 接下来是一个函数 SEND_CONFIG(),它使用 I2C 主 FIFO 突发发送将配置字写入地址0x01 (配置)。 接下来、它使用 I2C 主 FIFO 单次接收到地址0x00 (TEMP_RESULT)来读回第一个温度数据字。 该数据字 按预期存储在 getMasterRxData[]中。
SEND_CONFIG()完成后,我启用 GPIO P3中断,即 TMP117数据就绪输入。 在 GPIOP3_IRQHandler() ISR 中,我执行一 个简单的 I2C 主 FIFO 单次接收来从 TMP117读取数据。
使用逻辑分析仪、我可以看到 I2C 总线上的预期活动。 下图显示了发生的情况。 T=0之前 SCL 和 SDA 上的活动是 SEND_CONFIG()期间的活动。 随后的 SCL 和 SDA 活动来自 GPIOP3_IRQHandler()的执行。 GPIO P3中断按预期以500ms 的间隔发生、MSP432按预期处理前四个中断。
第五个 GPIO P3中断没有完全执行。 原因是 I2C RX FIFO 在第四个中断后填满、因此当 I2C 读取第九个数据字节时、它没有空间放入、执行开始。
以下是 SEND_CONFIG()活动的捕捉,数据0x0BE7存储在 getMasterRxData[]中:
这是第一个 P3中断活动:
下面是截断的第五个 P3中断活动:
我的问题是、DMA 为什么停止将数据从 I2C RX FIFO 移动到 getMasterRxData[]? 我认为这是我完成这项工作所需的最后一项工作。
e2e.ti.com/.../i2c_5F00_mastermode_5F00_fifodma_5F00_transfer.c
我已经回答了我自己的问题。 我没有意识到每次传输后都需要重写 UDMA 通道控制字。 该操作的开销是意外的。 我需要最大程度地减小 CPU 上的 I2C 传输负载、在可以处理 I2C 接收 FIFO 被告知保持数据之前、我似乎可以使用它。 FIFO 服务代码比重写 UDMA 控制字所需的时间更短、因此我决定停止使用 UDMA 来取代 FIFO。
因此、我将关闭此 TT。