主题中讨论的其他器件: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个字符的数据。
[报价 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/5322466 #5322466"]g_dmaCTRLPKT1.FRCNT = bsize;/*帧计数*/[/QUOT]此设置也不正确、因为您可以看到它的名称是帧计数、即需要发送或接收的帧数。 您不应在此处使用位大小进行初始化。
要接收或传输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。
尊敬的 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。