主题中讨论的其他器件: ADS127L01
工具/软件:Code Composer Studio
您好!
我使用 TM4C1294NCPDT 接收 来自 ADS127L01 ADC 的测量值。 我最近正在努力将 DMA 功能添加到我的旧项目中。 我的代码所做的是提供 SPI 总线以与 ADC 通信、然后数据通过 TCP 套接字发送到客户端设备。 由于我需要定期将数据从固定地址移动到以太网缓冲器、因此我决定在采用乒乓配置的 RX FIFO 上使用 DMA。 我以前在其他一些应用中使用过它。 客户端的最终结果 几乎与没有 DMA 功能的情况相同、唯一的区别是缓冲区的最后2个样本总是被破坏。
我填充大小为700的 rdata2缓冲器(短型数组、2字节变量)。 SPI 外设上的 RX DMA 由 RX FIFO 中的4个或更多字触发 、这就是我使指向 rdata2缓冲器的指针递增的方式。 下面的代码显示了 RX DMA 中断、传输变量是单个 DMA 传输的大小、并且被设置为4 (索引大小的条件基于708而不是700、因为以太网数据包中有一些固定的起始帧(大小为8)) 变量索引被重置为8。
基本上、在这个中断中、我跟踪目的地址、递增 RES_DEST2指针(指向 rdata2缓冲区)、并且在填充后将其复位为&rdata2[8]。
// // //这是 SSI1的处理程序,在 DMA RX 传输后进行处理 // ********* void IntSSI1 (void) { // test_variable=test_variable+1; int ui32mode1; int ui32mode2; ui32mode1 = uDMAChannelModeGet (UDMA_CHANGE_SSI1RX | UDMA_PRI_SELECT); ui32mode2 = uDMAChannelModeGet (UDMA_CHANGE_SSI1RX | UDMA_ALT_SELECT); index=index+transfer; if (index<708)//缓冲区中有空间,因此目的地址通过传输递增(4) { // //主要配置,配置并在传输停止后重新启用 // RES_DEST2 = RES_DEST2 +传输; if (ui32mode1 = udma_mode_stop) { test_variable=test_variable+1; uDMAChannelTransferSet (UDMA_CHANGE_SSI1RX | UDMA_PRI_SELECT、 UDMA_MODE_PINGONG、(void *)(SSI1_BASE + 0x008)、 //0x008是 SSIDR 寄存器 RES_DEST2、//递增地址 传输);//要传输的数据项数,如果 SSI FIFO 使用突发 DMA (使用大小为8的一半 FIFO) ,则传输大小为4} // //次要配置,配置并在传输停止后重新启用 // if (ui32mode2 = udma_mode_stop) { test_variable2=test_variable2+1; uDMAChannelTransferSet (UDMA_CHANGE_SSI1RX | UDMA_ALT_SELECT、 UDMA_MODE_PINGONG、(void *)(SSI1_BASE + 0x008)、 //0x008是 SSIDR 寄存器 RES_DEST2、//递增地址 传输);//要传输的数据项数,如果 SSI FIFO 使用突发 DMA (使用大小为8的一半 FIFO) ,则传输大小为4} } 否则、if (index>=708)//目标地址需要复位 { RES_DEST2=&rdata2[8]; // //主要配置,配置并在传输停止后重新启用 // if (ui32mode1 = udma_mode_stop) { uDMAChannelTransferSet (UDMA_CHANGE_SSI1RX | UDMA_PRI_SELECT、 UDMA_MODE_PINGONG、(void *)(SSI1_BASE + 0x008)、 //0x008是 SSIDR 寄存器 RES_DEST2、//递增地址 传输);//要传输的数据项数,如果 SSI FIFO 使用突发 DMA (使用大小为8的一半 FIFO) ,则传输大小为4} // //次要配置,配置并在传输停止后重新启用 // if (ui32mode2 = udma_mode_stop) { uDMAChannelTransferSet (UDMA_CHANGE_SSI1RX | UDMA_ALT_SELECT、 UDMA_MODE_PINGONG、(void *)(SSI1_BASE + 0x008)、 //0x008是 SSIDR 寄存器 RES_DEST2、//递增地址 传输);//要传输的数据项数,如果 SSI FIFO 使用突发 DMA (使用大小为8的一半 FIFO) ,则传输大小为4} send_sign=1;//Flag 通过 TCP 套接 字发送数据}
我的缓冲区类型为 short、它始终指向 SPI 模块的数据寄存器((void *)(SSI1_base + 0x008)。 DMA 的初始化代码如下:
dma_conf (RES_dest2、pui8ControlTable、transfer);,其中:
RES_DEST2=&rdata2[8]和
void dma_conf (unsigned short * buf、unsigned char * ControlTable、unsigned int Transfer_size) { // //在系统级别启用 uDMA 控制器。 // SysCtlPeripheralEnable (SYSCTL_Periph_UDMA); // //启用 UDMA 控制器。 // uDMAEnable(); // //指向控制表以用于通道控制结构体。 作为输入参数传递 // uDMAControlBaseSet (ControlTable); // //禁用所有属性 // uDMAChannelAttributeDisable (UDMA_CHANGE_SSI1RX、UDMA_ATTR_ALL); // //启用特定 DMA 通道,SSI1 RX 为24 // uDMAChannelAttributeEnable (uDMA_CHANGE_SSI1RX、UDMA_ATTR_USEBURST);//uDMAChannelAttributeEnable ()函数可用于为通道分配不同的外围设备(第680页为 DS) // //配置主设置,使用32位 uint 变量大小。 使用突发传输 UDMA_NEW_USEBURST、SSI FIFO 缓冲区将结果加载到同一地址、因此无 SRC 增量 // uDMAChannelControlSet (UDMA_CHANGE_SSI1RX | UDMA_PRI_SELECT、 UDMA_SIZE_16 | UDMA_DST_INC_16 | //地址增量值必须等于或大于 dest/src size (DSTSIZE)的值。 UDMA_SRC_INC_NONE | // UDMA_ARB_8); //仲裁大小必须至少为外设可容纳的项目数(如果 SSI FIFO 为半个、因此为4帧) UDMA_ARB_4); //仲裁大小必须至少为外设可容纳的项目数(如果 SSI FIFO 为半个、因此为4帧) // //分配缓冲区,将有8个传输(buf 大小) // uDMAChannelTransferSet (UDMA_CHANGE_SSI1RX | UDMA_PRI_SELECT、 UDMA_MODE_PINGONG、 (void *)(SSI1_base + 0x008)、 //0x008是 SSIDR 寄存器 BUF、 // sizeof (buf)); transfer_size); uDMAChannelControlSet (UDMA_CHANGE_SSI1RX | UDMA_ALT_SELECT、 UDMA_SIZE_16 | UDMA_DST_INC_16 | //地址增量值必须等于或大于 dest/src size (DSTSIZE)的值。 UDMA_SRC_INC_NONE | // UDMA_ARB_8); //仲裁大小必须至少为外设可容纳的项目数(如果 SSI FIFO 为半个、因此为4帧) UDMA_ARB_4); //仲裁大小必须至少为外设可容纳的项目数(如果 SSI FIFO 为半个、因此为4帧) // //分配缓冲区,将有8个传输(buf 大小) // uDMAChannelTransferSet (UDMA_CHANGE_SSI1RX | UDMA_ALT_SELECT、 UDMA_MODE_PINGONG、 (void *)(SSI1_base + 0x008)、 //0x008是 SSIDR 寄存器 BUF、 // sizeof (buf)); transfer_size); // //一旦启用了通道,外设就会启动 //发出传输请求,数据传输将开始。 // uDMAChannelEnable (UDMA_CHANGE_SSI1RX); }
此数据由客户端接收、这是在测试期间将基准正弦信号馈送到 ADC 时输出的结果:
缩放:
由于 rdata2包含原始测量值、实际上2个 ADC 帧代表一个测量指数349、350对应于 rdata2数组中的最后4个值(rdata2[704]-[707])。 可以看到、最后2次测量总是损坏的、但实际上、使用索引1049、1050的测量具有正确的索引699和700的值。 如果通孔测量持续10秒或分钟、则其一致性不受影响。 看起来每个帧的最后一个 DMA 传输被延迟、并为下一个帧更新了 rdata2的最后4个元素。
在调试之后、我发现这不是以太网通信或数据转换问题、因为在 MCU 存储器中检查 rdata2时发现这是在 MCU 端发生的。 我对如何实现这一目标的想法已一转不下。 我多次检查索引、没有发现任何原因。 另外一点是、其他点也很好、所以最后一次 DMA 传输出现了问题(大小为4的最后一次 DMA 传输与2个测量值完全一致)。
SPI 时钟为15MHz、16位帧 SSI_FRF_MOTO_MODE_1 (受控 ADC 需要)作为主器件工作。
我将赞赏任何想法和意见。




