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.

[参考译文] TM4C129XNCZAD:使用 DMA 发送字节、在2个成功传输后、在以下传输请求之前、下一次传输不会发生 n#39;t

Guru**** 2460180 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/648516/tm4c129xnczad-using-dma-to-send-bytes-after-2-successful-transmission-next-transmission-doesn-t-happen-until-the-following-transfer-request

器件型号:TM4C129XNCZAD

在一种奇怪的情况下,我修改了(不是太多) UDMA_Demo 以将 UART 配置为一次发送一条消息。 它对第一条消息很有效、第二条消息也会立即传输。 但是、第三个消息不会立即传输、但是在以下传输请求中、这两条消息都将被发送。

void
UARTIntHandler (void)
{
uint32_t ui32Status;
uint32_t ui32Mode;

//
//读取 UART 的中断状态。
//
ui32Status = ROM_UARTIntStatus (UART0_BASE,1);
// UARTIntDisable (UART0_BASE);

if (ui32Status == 0x00020000)
{
//在此处执行操作..........
ROM_UARTDMADisable (UART0_BASE、UART_DMA_TX);
//需要此步骤才能退出中断。
ROM_UARTIntClear (UART0_BASE、ui32Status);

return;
}

//HWREG (UART0_BASE + UART_O_ICR)= 0x00020000;
//ui32Status = ROM_UARTIntStatus (UART0_BASE、1);

//
清除任何挂起状态、即使没有
启用/ UART 中断也是如此。 如果启用了 UART 错误中断、那么
//这些中断可能在这里发生并且应该被处理。 由于 UDMA
用于 RX 和 TX、因此不应
启用这两个中断中的任何一个。
//
ROM_UARTIntClear (UART0_BASE、ui32Status);
ui32Status = ROM_UARTIntStatus (UART0_BASE、1);

//
检查 DMA 控制表以查看乒乓"A"传输是否
为//完成。 "A"传输使用接收缓冲器"A"和主
//控制结构体。
//
ui32Mode = ROM_uDMAChannelModeGet (UDMA_CHANNE_UART0RX | UDMA_PRI_SELECT);

//
如果主控制结构体指示停止、则表示"a"
//接收缓冲区已完成。 UDMA 控制器仍应将
//数据接收到"B"缓冲区中。
//
if (ui32Mode = udma_mode_stop)
{
//
递增计数器以指示数据已接收到缓冲区 A 中。在
//实数应用中,此函数将用于向主线程发出
//数据已接收的信号,以便主线程可以处理数据。
//-------------------- >在缓冲区 A-->???中设置接收到的数据标志

g_ui32RxBufACount++;

//
使用主
//控制结构为"A"缓冲区设置下一个传输。 当进入"B"缓冲区的持续接收被
//完成时、UDMA 控制器将切换回此缓冲区。 此
//示例重复使用缓冲区 A,但更复杂的应用程序可以
//使用一组旋转的缓冲区来增加
//主线程在
重复使用缓冲区之前必须处理缓冲区中数据的时间。
//
rom_uDMAChannelTransferSet (UDMA_CHANGE_UART0RX | UDMA_PRI_SELECT、
UDMA_MODE_Pingpong、
(void *)(UART0_BASE + UART_O_DR)、
g_ui8Sigpong RxBufA、sizeof (g_ui8FoxRxBufA)
、(g_ui8FoxRxBuxBufb


)/如果控制是
完整的/检查控制表)/参阅"tongbooboob/"。 "B"传输使用接收缓冲器"B"和副
//控制结构体。
//
ui32Mode = ROM_uDMAChannelModeGet (UDMA_CHANNE_UART0RX | UDMA_ALT_SELECT);

//
如果副控制结构体指示停止、则表示"B"
//接收缓冲区已完成。 UDMA 控制器仍应将
//数据接收到"A"缓冲区中。
//
if (ui32Mode = udma_mode_stop)
{
//
递增计数器以指示数据已接收到缓冲区 A 中。在
//实数应用中,此函数将用于向主线程发出
//数据已接收的信号,以便主线程可以处理数据。
//
g_ui32RxBufBCount++;

//----- >设置接收到的数据标志-->???

//使用替代
//控制结构为"B"缓冲区设置下一个传输。 当进入"A"缓冲区的持续接收被
//完成时、UDMA 控制器将切换回此缓冲区。 此
//示例重复使用缓冲区 B,但更复杂的应用程序可以
//使用一组旋转的缓冲区来增加
//主线程在
重复使用缓冲区之前必须处理缓冲区中数据的时间。
//
rom_uDMAChannelTransferSet (UDMA_CHANNE_UART0RX | UDMA_ALT_SELECT、
UDMA_MODE_Pingpong、
(void *)(UART0_BASE + UART_O_DR)、
g_ui8SigRxBufB、sizeof (g_ui8TOX0/



)表示传输
已被禁用/如果 TOX0/ TOX0/ TOXFx、则表示已完成。
//


//必须重新启用 uDMA TX 通道。
//

}

//*********
//
//初始化 UART0外设并设置 TX 和 RX UDMA 通道。
//将 UART 配置为环回模式,以便在 TX 上发送的任何数据都将
在 RX 上接收//。 UDMA 通道的配置使 TX 通道
//将数据从缓冲区复制到 UART TX 输出。 UDMA RX 通道
//将在乒乓模式下将任何传入的数据接收到一对缓冲器中。
////
*****************
void
InitUART0Transfer (void)
{

//启用 UART 外设、并将其配置为即使 CPU
//处于睡眠状态也能正常工作。
//

ROM_SysCtlPeripheralEnable (SYSCTL_Periph_UDMA);
ROM_SysCtlPeripheralSleep Enable (SYSCTL_Periph_UDMA);

//
启用 UDMA 控制器错误中断。
如果在传输过程中出现总线错误、则会发生此中断//。
//
ROM_IntEnable (INT_UDMAERR);

//
启用 UDMA 控制器。
//
rom_uDMAEnable();

//
//指向控制表以用于通道控制结构体。
//
ROM_uDMAControlBaseSet (pui8ControlTable);

ROM_SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
ROM_SysCtlPeripheralSleep Enable (SYSCTL_Periph_UART0);

//
配置 UART 通信参数。
//
ROM_UARTConfigSetExpClk (UART0_BASE、ui32SysClock、9600、
UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
UART_CONFIG_PAR_NONE);

//
将 TX 和 RX 触发阈值设置为4。
此时、// uDMA 控制器将使用此信号来发出何时应传输更多数据的信号。
将配置// uDMA TX 和 RX 通道,以便
在 UART 准备好传输更多数据时以突发方式传输4 //个字节。
//
ROM_UARTFIFOLevelSet (UART0_BASE、UART_FIFO_TX4_8、UART_FIFO_RX4_8);

//
启用 UART 以进行操作,并为 TX
//和 RX 通道启用 UDMA 接口。
//
ROM_UARTEnable (UART0_BASE);
//ROM_UARTDMAEnable (UART0_BASE、UART_DMA_RX);
ROM_UARTDMAEnable (UART0_BASE、UART_DMA_RX | UART_DMA_TX);
//
//该寄存器写入将 UART 设置为在写入模式下运行。
//
//HWREG (UART0_BASE + UART_O_CTL)|= UART_CTL_TXE;

//
将 UDMA UART0RX 通道的属性置于已知状态。
默认情况下、这些//应已禁用。
//
ROM_uDMAChannelAttributeDisable (UDMA_CHANGE_UART0RX、
UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
UDMA_ATTR_HIGH_PRIOR|
UDMA_ATTR_REQMASK);

//
配置
UART 通道的主控制结构的控制参数// RX。 主控制结构用于
乒乓接收的"A"//部分。 传输数据大小为8位、
//源地址不会增加、因为它将从
//寄存器读取。 目的地址增量是字节8位字节。
//仲裁大小设置为4以匹配 RX FIFO 触发阈值。
//如果可能,UDMA 控制器将使用4字节突发传输。 这个
//比单字节传输更有效。
//
rom_uDMAChannelControlSet (UDMA_CHANNE_UART0RX | UDMA_PRI_SELECT、
UDMA_SIZE 8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
UDMA_ARB_4);

//
配置
UART RX 通道的替代控制结构的控制参数。 备用控制结构体用于
乒乓接收的"B"//部分。 配置与
//主/A 控制结构相同。
//
rom_uDMAChannelControlSet (UDMA_CHANNE_UART0RX | UDMA_ALT_SELECT、
UDMA_SIZE 8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
UDMA_ARB_4);

//
设置 UART RX 主控
件的传输参数//结构。 模式设置为乒乓模式、传输源为
// UART 数据寄存器、目标为接收"A"缓冲器。
//传输大小设置为与缓冲区大小匹配。
//
rom_uDMAChannelTransferSet (UDMA_CHANGE_UART0RX | UDMA_PRI_SELECT、
UDMA_MODE_Pingpong、
(void *)(UART0_BASE + UART_O_DR)、
g_ui8SigRxBufA、sizeof (g_ui8FoxRxBufA)


/为 UART 传输设置替代结构/ SigfRxBu/参数
。 模式设置为乒乓模式、传输源为
// UART 数据寄存器、目标为接收"B"缓冲器。
//传输大小设置为与缓冲区大小匹配。
//
rom_uDMAChannelTransferSet (UDMA_CHANGE_UART0RX | UDMA_ALT_SELECT、
UDMA_MODE_Pingpong、
(void *)(UART0_BASE + UART_O_DR)、
g_ui8SigRxBufB、sizeof (g_ui8TOX0B/ uFOXB


)将已知通道属性置于 UARTxBuf/ UARTxBufB 状态。
默认情况下、这些//应已禁用。
//
rom_uDMAChannelAttributeDisable (UDMA_CHANGE_UART0TX、
UDMA_ATTR_ALTSELECT |
UDMA_ATTR_HIGH_PRIOR|
UDMA_ATTR_REQMASK);

//
设置 UDMA UART TX 通道的 USEBURST 属性。 这将
//强制控制
器在将数据从// TX 缓冲区传输到 UART 时始终使用突发。 这比
默认的允许单次或突发传输的总线用法//更有效。
//
ROM_uDMAChannelAttributeEnable (UDMA_CHANGE_UART0TX、UDMA_ATTR_USEBURST);

//
配置 UART TX 的控制参数。 uDMA UART TX
//通道用于将数据块从缓冲区传输到 UART。
//数据大小为8位。 源地址增量为8位字节
//、因为数据来自缓冲区。 由于
数据将被写入 UART 数据寄存器、所以目的增量为//无。
//仲裁大小设置为4、与 UART TX FIFO 触发
//阈值匹配。
//
rom_uDMAChannelControlSet (UDMA_CHANNE_UART0TX | UDMA_PRI_SELECT、
UDMA_SIZE 8 | UDMA_SRC_INC_8 |
UDMA_DST_INC_NONE |
UDMA_ARB_4);

//
设置 UDMA UART TX 通道的传输参数。 这将
//配置传输源和目标以及传输大小。
//使用基本模式是因为外设正在进行 UDMA 传输
//请求。 源是 TX 缓冲区、目的是 UART
//数据寄存器。
ROM_uDMAChannelTransferSet (UDMA_CHANNE_UART0TX | UDMA_PRI_SELECT、
UDMA_MODE_BASIC、g_ui8SigFoxTxBuf、
(void *)(UART0_BASE + UART_O_DR)、
sizeof (g_ui8FoxSigTxBuf)

)通道和 UARTX/PRIME/DMA 现在开始
传输。 一旦通道被启用、外设将
//发出一个传输请求并且数据传输将开始。
//
ROM_uDMAChannelEnable (UDMA_CHANGE_UART0RX);
ROM_uDMAChannelEnable (UDMA_CHANGE_UART0TX);

//
启用 UART DMA TX/RX 中断。
//


ROM_UARTIntEnable (UART0_BASE、UART_INT_DMATX | UART_INT_DMARX);

//
启用 UART 外设中断。
//
rom_IntEnable (INT_UART0);

}











void SigFoxDMASend (const uint8_t * pu8Buffer、uint32_t ui32Count){int index = 0;//清除两个缓冲区中先前接收的数据 rom_uDMAChannelTransferSet (uint32_t ui32Count);* uartbon_u0dma_u0uuuRdma/ u0uuuuuu0uuuuuuuuuuuuuuuuuuuuuuuuutran_transfer



+ u0uuuuuuuuuuuuuuuuuuuuuuutraduuuuuuuuuuuuuuu0uuuuuu0uuuuu
模式设置为乒乓模式、传输源为
// UART 数据寄存器、目标为接收"B"缓冲器。
//传输大小设置为与缓冲区大小匹配。
//
ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART0RX | UDMA_ALT_SELECT、
UDMA_MODE_Pingpong、
(void *)(UART0_BASE + UART_O_DR)、
g_ui8SigRXB+、sizeof (g_ui8fb











)、sizeof (g_UART0+索引= UTXB+= U0+);index = U0+= Ufu0+= u0+= uTXBUF+= u0+(u0+索引= uTXB+);index = u0+= u0+= uTXBUF+= u0+= u0+= uTXBUF+= u0+= u0uTXBUF= u0u0u0u0u0u0u0u0uTXB+索引;u0u0u0u0uTXBUF+= u0u0u

index++)
{
g_ui8SigFoxTxBuf[index]= 0;
}

//下一步是将新数据移动到传输缓冲区

uint32_t counter8 = 0;

while (ui32Count--)
{
g_ui8SigcounterTxBuf[counter8]= pui8Buffer[ART8];
+





//启动传输另一个函数/ uTX+0/。

//
rom_uDMAChannelTransferSet (uDMA_CHANGE_UART0TX | UDMA_PRI_SELECT、
UDMA_MODE_BASIC、g_ui8SigFoxTxBuf、
(void *)(UART0_BASE + UART_O_DR)
、sizeof (g_ui8SigFoxTxBuf)、必须


启用/ UDMA 通道。
ROM_UARTDMAEnable (UART0_BASE、UART_DMA_RX | UART_DMA_TX);
ROM_uDMAChannelEnable (UDMA_CHANNEL UART0TX);

}

int main (void)
{


//
初始化 UDMA UART 传输。
//
InitUART0Transfer();
delayms (10);

int ui16Idxo = 0;
unsigned char result[UART_RXBUF_size];
for (ui16Idxo = 0;ui16Idxo < UART_RXBUF_SIZE;ui16Foxxo++)
{result[ui16Idxo = 0;ui16uiduuuuuuuuuuuuuuuuuanu0uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu82ua]



;uanu16u82u0uuu82uuuua](uanu



ui16Idxo = 0;
for (ui16Idxo = 0;ui16Idxo < UART_RXBUF_SIZE;ui16Idxo++)
{
result[ui16Idxo]= g_ui8SigFoxRxBufA[ui16Idxo];
}
//开始另一个 DMA 传输到 UART0。

unsigned char bluemo1[]="at$i=10\r";

// SigFoxDMASend (bluemoon1、9);
delayms (10);

//开始另一个到 UART0 TX 的 DMA 传输。

//开始到 UART0 TX 的另一个 DMA 传输。

SigFoxDMASend (bluemoon1、9);
delayms (10);

SigFoxDMASend (bluemoon、4);
delayms (10);

SigFoxDMASend (bluemoon、4);
delayms (10);

} 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    我不清楚您的问题。 第三个不会立即传输、这意味着什么? 第二次传输后、它开始传输的时间有多晚?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    除非您的消息以4字节的倍数出现、否则消息之间将存在延迟、因为您使用的是 UDMA_ARB_4。 尝试使用 UDMA_ARB_1。

    ROM_uDMAChannelControlSet (UDMA_CHANGE_UART0TX | UDMA_PRI_SELECT、
    UDMA_SIZE_8 | UDMA_SRC_INC_8 |
    UDMA_DST_INC_NONE |
    UDMA_ARB_1); 

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

    并设置 FIFO 深度、以便在单个接收到的字符上触发。

    ROM_UARTFIFOLevelSet (UART0_BASE、UART_FIFO_TX1_8、UART_FIFO_RX1_8);
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢大家查看我的代码、我尝试了这些选项、它没有得到解决、但是我确实通过禁用 TX 中断来解决它。