主题中讨论的其他器件:HALCOGEN
工具与软件:
尊敬的 TI 支持部门:
您是否具有用于 DMA 控制器进行 I2C 读写的示例源代码和 HalcGen 配置?
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.
工具与软件:
尊敬的 TI 支持部门:
您是否具有用于 DMA 控制器进行 I2C 读写的示例源代码和 HalcGen 配置?
尊敬的 Manoraj:
我没有任何直接示例可以与您分享、但您可以通过以下方式实现:
首先了解 DMA 将如何与 i2c 模块配合使用:
另请参阅以下主题、在这里可以找到一些代码参考。
(+) TMS570LC4357:如何将 DMA 用于 I2C 发送和接收? -基于 Arm 的微控制器论坛-基于 Arm 的微控制器- TI E2E 支持论坛
只是尝试从你自己的一方实施,如果你在实施中遇到任何困难,那么我将进一步帮助你。
——
谢谢、此致、
Jagadish。
尊敬的 Jagadish:
感谢 您的答复。
我使用内部回送以16位大小读回数据。
我只能通过 DMA 读取前8位。
请在下面找到我的代码
/*
*版权所有(C) 2009-2015德州仪器(TI)公司- www.ti.com
*
*
*以源代码和二进制形式重新分发和使用,无论有无
*修改,只要满足以下条件即可
*已满足:
*
*源代码的再分发必须保留上述版权
*通知,本条件列表及以下免责声明。
*
*二进制形式的再分发必须复制上述版权
*通知,本条件列表和以下免责声明在
*随附的文档和/或其他材料
*分发。
*
*既不是德州仪器(TI)公司的名称、也不是公司的名称
*其贡献者可用于认可或推广衍生产品
*未经事先书面许可使用本软件。
*
*本软件由版权所有者和贡献者提供
"按现状"和"按可得到"的基础提供
本站明确声明不作出任何种类的所有明示或暗示的保证
*不得使用特定目的。 在任何情况下均不得享有版权
*所有者或贡献者对任何直接的、间接的、附带的、
*特殊、示例性或后果性损害,包括但不包括
*仅限于采购替代商品或服务;不能使用,
*数据,或利润;或业务中断,然而造成和任何
*责任理论,无论是合同,严格的责任,或侵权
*包括疏忽或以任何方式产生的使用
*本软件,即使被告知此类损坏的可能性。
*
*/
/*用户代码 begin (0)*/
/*用户代码结束*/
/*包含文件*/
#include "HL_sys_common.h"
#include "HL_system.h"
#include "HL_sys_dma.h"
/*用户代码 begin (1)*/
#include "HL_i2c.h"
#define own_add 0x20
#define SLV_ADD 0x10
第16章不是你
#define I2C1_TX_ADDR ((uint32_t)(&(i2cREG1->DXR))+ 3)
#define I2C1_RX_ADDR ((uint32_t)(&(i2cREG1->DRR))+ 3)
UINT8 TX_PACK[bsize]={'H'、'E'、'R'、'C'、'U'、'L'、'E'、'S'、'M'、'I'、'C'、'R'、'O'、'-'、'T'、'A'};
uint8 DMA_RX_PACK[bsize]={0};
void i2cEnableLoopback (i2cbase_t * i2c);
/*用户代码结束*/
/*用户代码 begin (2)*/
/*用户代码结束*/
void main (void)
{
/*用户代码 begin (3)*/
g_dmaCTRL g_dmaCTRLPKT2、g_dmaCTRLPKT1;
//启用 CPU 对中断请求的响应
_enable_irq();
/* i2c 初始化*/
i2cInit ();
/*配置要与之通信的从器件地址*/
i2cSetSlaveAdd (i2cREG1、SLV_ADD);
i2cSetDirection (i2cREG1、I2C_transmitter);
/*设置 i2c 自身地址*/
i2cSetOwnAdd (i2cREG1、own_add);
/*启用内部回送*/
i2cEnableLoopback (i2cREG1);
dmaReqAssign (DMA_CH0、DMA_REQ10);
dmaReqAssign (DMA_CH1、DMA_REQ11);
dmaSetChEnable (DMA_CH0、DMA_HW);
dmaSetChEnable (DMA_CH1、DMA_HW);
dmaEnableInterrupt (DMA_CH0、BTC、DMA_INTA);
dmaEnableInterrupt (DMA_CH1、BTC、DMA_INTA);
/*为通道1*/配置控制数据包
G_dmaCTRLPKT1.Sadd = I2C1_RX_ADDR;/*源地址*/
g_dmaCTRLPKT1.DADD =(uint32_t) DMA_RX_PACK;/*目标地址 ss */
G_dmaCTRLPKT1.CHCTRL = 0;/*通道控制*/
g_dmaCTRLPKT1.FRCNT = bsize;/*帧计数*/
g_dmaCTRLPKT1.ELCNT = 1;/*元素计数*/
G_dmaCTRLPKT1.ELDOFFSET = 0;/*元素目标偏移*/
G_dmaCTRLPKT1.ELSOFFSET = 0;/*元素目标偏移*/
G_dmaCTRLPKT1.FRDOFFSET = 0;/*帧目标偏移*/
G_dmaCTRLPKT1.FRSOFFSET = 0;/*帧目标偏移*/
G_dmaCTRLPKT1.PORTAGN = PORTB_READ_PORTA_WRITE;
G_dmaCTRLPKT1.RDSIZE = ACCESS_8_BIT;/*读取大小*/
G_dmaCTRLPKT1.WRSIZE = ACCESS_8_BIT;/*写入大小*/
g_dmaCTRLPKT1.tType = FRAME_TRANSFER;/*传输类型*/
G_dmaCTRLPKT1.ADDMODERD = ADDR_FIXED;/*地址模式读取*/
G_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1;/*地址模式写入*/
G_dmaCTRLPKT1.AUTOINIT = AUTOINIT_OFF;/* autoinit */
/*配置通道0的控制包*/
g_dmaCTRLPKT2.Sadd =(uint32_t) TX_Pack;/*源地址*/
G_dmaCTRLPKT2.DADD = I2C1_TX_ADDR;/*目标地址*/
G_dmaCTRLPKT2.CHCTRL = 0;/*通道控制*/
g_dmaCTRLPKT2.FRCNT = bsize;/*帧计数*/
g_dmaCTRLPKT2.ELCNT = 1;/*元素计数*/
g_dmaCTRLPKT2.ELDOFFSET = 0;/*元素目标偏移*/
g_dmaCTRLPKT2.ELSOFFSET = 0;/*元素目标偏移*/
G_dmaCTRLPKT2.FRDOFFSET = 0;/*帧目标偏移*/
G_dmaCTRLPKT2.FRSOFFSET = 0;/*帧目标偏移*/
G_dmaCTRLPKT2.PORTAGN = PORTA_READ_PORTB_WRITE;
G_dmaCTRLPKT2.RDSIZE = ACCESS_8_BIT;/*读取大小*/
G_dmaCTRLPKT2.WRSIZE = ACCESS_8_BIT;/*写入大小*/
g_dmaCTRLPKT2.tType = FRAME_TRANSFER;/*传输类型*/
G_dmaCTRLPKT2.ADDMODERD = ADDR_INC1;/*地址模式读取*/
G_dmaCTRLPKT2.ADDMODEWR = ADDR_FIXED;/*地址模式写入*/
G_dmaCTRLPKT2.AUTOINIT = AUTOINIT_OFF;/* autoinit */
/*-设置 DMA 控制数据包以进行传输*/
dmaSetCtrlPacket (DMA_CH0、g_dmaCTRLPKT1);
dmaSetCtrlPacket (dma_ch1、g_dmaCTRLPKT2);
dmaEnable();
i2cREG1->DMACR |= 0x3;
i2cSetStop (i2cREG1);
/*传输启动条件*/
i2cSetStart (i2cREG1);
/*等待永远*/
while (1);
/*用户代码结束*/
}
/*用户代码 begin (4)*/
/*用户代码结束*/
请找到快照 DMA 接收缓冲区
您是否可以检查 控制数据包的配置?
问题可能是什么?
尊敬的 Manoraj:
您不能直接从 I2C 接收或发送16位数据
您可以看到、数据宽度仅为8位。 因此、如果您希望接收16位、则应该需要发送2个字节。
因此、如果您要传输2个字节或接收2个字节、则应按如下方式配置 DMA
/*Configure control packet for Channel 1*/ g_dmaCTRLPKT1.SADD = I2C1_RX_ADDR; /* source address */ g_dmaCTRLPKT1.DADD = (uint32_t)DMA_RX_PACK; /* destination addr ss */ g_dmaCTRLPKT1.CHCTRL = 0; /* channel control */ g_dmaCTRLPKT1.FRCNT = 2; /* frame count */ g_dmaCTRLPKT1.ELCNT = 1; /* element count */ g_dmaCTRLPKT1.ELDOFFSET = 0; /* element destination offset */ g_dmaCTRLPKT1.ELSOFFSET = 0; /* element destination offset */ g_dmaCTRLPKT1.FRDOFFSET = 0; /* frame destination offset */ g_dmaCTRLPKT1.FRSOFFSET = 0; /* frame destination offset */ g_dmaCTRLPKT1.PORTASGN = PORTB_READ_PORTA_WRITE; g_dmaCTRLPKT1.RDSIZE = ACCESS_8_BIT; /* read size */ g_dmaCTRLPKT1.WRSIZE = ACCESS_8_BIT; /* write size */ g_dmaCTRLPKT1.TTYPE = FRAME_TRANSFER; /* transfer type */ g_dmaCTRLPKT1.ADDMODERD = ADDR_FIXED; /* address mode read */ g_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1; /* address mode write */ g_dmaCTRLPKT1.AUTOINIT = AUTOINIT_OFF; /* autoinit */ /*Configure control packet for Channel 0*/ g_dmaCTRLPKT2.SADD = (uint32_t)TX_PACK; /* source address */ g_dmaCTRLPKT2.DADD = I2C1_TX_ADDR; /* destination address */ g_dmaCTRLPKT2.CHCTRL = 0; /* channel control */ g_dmaCTRLPKT2.FRCNT = 2; /* frame count */ g_dmaCTRLPKT2.ELCNT = 1; /* element count */ g_dmaCTRLPKT2.ELDOFFSET = 0; /* element destination offset */ g_dmaCTRLPKT2.ELSOFFSET = 0; /* element destination offset */ g_dmaCTRLPKT2.FRDOFFSET = 0; /* frame destination offset */ g_dmaCTRLPKT2.FRSOFFSET = 0; /* frame destination offset */ g_dmaCTRLPKT2.PORTASGN = PORTA_READ_PORTB_WRITE; g_dmaCTRLPKT2.RDSIZE = ACCESS_8_BIT; /* read size */ g_dmaCTRLPKT2.WRSIZE = ACCESS_8_BIT; /* write size */ g_dmaCTRLPKT2.TTYPE = FRAME_TRANSFER; /* transfer type */ g_dmaCTRLPKT2.ADDMODERD = ADDR_INC1; /* address mode read */ g_dmaCTRLPKT2.ADDMODEWR = ADDR_FIXED;; /* address mode write */ g_dmaCTRLPKT2.AUTOINIT = AUTOINIT_OFF; /* autoinit */
配置2个帧和1个大小为8位的元素、因此、通过这种方式、您可以使用 I2C 上的 DMA 接收或传输两个8字节。
——
谢谢、此致、
Jagadish。
尊敬的 Jagadish:
我能够使用以下 DMA 和 HalCoGen 配置通过 DMA 读取16位数据
/*为通道1*/配置控制数据包
G_dmaCTRLPKT1.Sadd = I2C1_RX_ADDR;/*源地址*/
g_dmaCTRLPKT1.DADD =(uint32_t) DMA_RX_PACK;/*目标地址 ss */
G_dmaCTRLPKT1.CHCTRL = 0;/*通道控制*/
g_dmaCTRLPKT1.FRCNT = bsize;/*帧计数*/
g_dmaCTRLPKT1.ELCNT = 1;/*元素计数*/
G_dmaCTRLPKT1.ELDOFFSET = 0;/*元素目标偏移*/
G_dmaCTRLPKT1.ELSOFFSET = 0;/*元素目标偏移*/
G_dmaCTRLPKT1.FRDOFFSET = 0;/*帧目标偏移*/
G_dmaCTRLPKT1.FRSOFFSET = 0;/*帧目标偏移*/
G_dmaCTRLPKT1.PORTAGN = PORTB_READ_PORTA_WRITE;
G_dmaCTRLPKT1.RDSIZE = ACCESS_8_BIT;/*读取大小*/
G_dmaCTRLPKT1.WRSIZE = ACCESS_8_BIT;/*写入大小*/
g_dmaCTRLPKT1.tType = FRAME_TRANSFER;/*传输类型*/
G_dmaCTRLPKT1.ADDMODERD = ADDR_FIXED;/*地址模式读取*/
G_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1;/*地址模式写入*/
G_dmaCTRLPKT1.AUTOINIT = AUTOINIT_OFF;/* autoinit */
/*配置通道0的控制包*/
g_dmaCTRLPKT2.Sadd =(uint32_t) TX_Pack;/*源地址*/
G_dmaCTRLPKT2.DADD = I2C1_TX_ADDR;/*目标地址*/
G_dmaCTRLPKT2.CHCTRL = 0;/*通道控制*/
g_dmaCTRLPKT2.FRCNT = bsize;/*帧计数*/
g_dmaCTRLPKT2.ELCNT = 1;/*元素计数*/
g_dmaCTRLPKT2.ELDOFFSET = 0;/*元素目标偏移*/
g_dmaCTRLPKT2.ELSOFFSET = 0;/*元素目标偏移*/
G_dmaCTRLPKT2.FRDOFFSET = 0;/*帧目标偏移*/
G_dmaCTRLPKT2.FRSOFFSET = 0;/*帧目标偏移*/
G_dmaCTRLPKT2.PORTAGN = PORTA_READ_PORTB_WRITE;
G_dmaCTRLPKT2.RDSIZE = ACCESS_8_BIT;/*读取大小*/
G_dmaCTRLPKT2.WRSIZE = ACCESS_8_BIT;/*写入大小*/
g_dmaCTRLPKT2.tType = FRAME_TRANSFER;/*传输类型*/
G_dmaCTRLPKT2.ADDMODERD = ADDR_INC1;/*地址模式读取*/
G_dmaCTRLPKT2.ADDMODEWR = ADDR_FIXED;/*地址模式写入*/
G_dmaCTRLPKT2.AUTOINIT = AUTOINIT_OFF;/* autoinit */
HalCoGen 配置:将 I2C 位计数从8更改为16
尊敬的 Manoraj:
我认为您之前用于接收16位数据的配置也不正确。
突出显示的设置不适用于16位数据传输、这意味着需要在 i2c 上接收16个字符的数据。
此设置也不正确、因为您可以看到它的名称是帧计数、即需要发送或接收的帧数。 您不应在此处使用位大小进行初始化。
要接收或传输16位、只需将上述两个设置保持为2。
您的从设备是什么?
——
谢谢、此致、
Jagadish。
尊敬的 Manoraj:
我为发送和接收创建了一个 i2c 示例项目。
我的项目如下:
e2e.ti.com/.../I2C_5F00_DMA_5F00_TEST_5F00_LC4357.zip
我通过连接到从器件(另一个被配置为从器件的 TI 电路板)测试了该项目。
当我配置为发送器时、我将向从器件发送以下突出显示的数据:
这里是我的输出、大家可以看到我从从器件收到了 ACK、然后 TMS 板将数据正确发送到 DMA 上的从器件。
同样、我还测试了接收功能:
为了测试接收功能、我将在从器件侧发送下面突出显示的数据、
这是我的主输出、我能够将数据从从从器件正确接收到主 RX 缓冲区中。
因此、应将此代码作为参考、并根据您的从设备正确配置从设备地址和数据计数。
同时确保您正确遵循从站协议、如果您正确执行这些操作、那么您的代码肯定会起作用。
我另一条建议是、客户通常不会更喜欢 DMA 上的 i2c。 这是因为 i2c 从器件发送少量字节可能是几个字节、对于这个数量的数据不是必需的 DMA。 如果有很大的数据块、那么它可能很有用、但对于几个字节来说、它不是必需的。 "你是我的女人,我知道你是我的女人。"
——
谢谢、此致、
Jagadish。
使用 DMA I2C、我将从从设备的 FIFO 读取3kb 的数据
在这种情况下、选择 DMA 是合理的。
如何识别 i2c2的自有地址?
在这种情况下、自身地址可能不重要、仅确保您配置了正确的从器件地址。 忽略自身的地址。
尊敬的 Jagadish:
我已经配置了从器件、能够从从器件中读取 FIFO。
但从器件具有一个限制条件
为了读取完整的 FIFO、我需要单独读取7个寄存器以获得已配置的采样数量。
这意味着我需要调用 i2cSetStart (i2cREG2) 来获取7 *个 已配置采样数。
需要始终使用 I2C 来清除使 CPU 保持忙状态的 FIFO
I2C 或 DMA 中是否有重复模式用于读取 n 次数据?
尊敬的 Manoraj:
[报价 userid="495032" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1390906/tms570lc4357-example-source-code-and-halcogen-configuration-for-i2c-read-and-write-by-dma-controller/5339802 #5339802"]但从器件具有一个限制条件
为了读取完整的 FIFO、我需要单独读取7个寄存器以获得已配置的采样数量。
[报价]我完全不知道该从设备。
如果我们对从器件的处理能力存在限制、但我建议完全检查从器件、继续 FIFO 读取模式等功能可能会有所帮助。
自动启动模式(AIM)如何在 DMA 中工作?
关于自动初始化模式理解、请参阅以下主题:
(+) TMS570LC4357:DMA 翻转-基于 Arm 的微控制器论坛-基于 Arm 的微控制器- TI E2E 支持论坛
我的意思是、在传输完成后、它将再次自动初始化所有参数、例如源地址、目标地址、帧计数、以便启动 下一次传输。 如果我们启用 DMA 通道、则下一次传输将自动启动。
——
谢谢、此致、
Jagadish。