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.

[参考译文] 编译器/TM4C129EKCPDT:如何使用两个 ADC 配置 UDMA

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/735418/compiler-tm4c129ekcpdt-how-to-config-udma-with-two-adc

器件型号:TM4C129EKCPDT

工具/软件:TI C/C++编译器

我可以从 ADC 9和 ADC,读取两个电压、但无法使用 UDMA 将两个 ADC 值保存到数组中。

我不知道如何使用两个 ADC 通道配置 UDMA。

我尝试重复使用 uDMA,但失败了。

我想使用 UDMA 读取 ADC9和 ADC11电压吗? 我可以从 数组获取两个电压值。

谢谢! 如果可以,您能给我一些演示,但使用两个 带有 uDMA 的 ADC。

我的代码(udna 部件出错,我无法 确认 ADC 部件是否正确):

#include 
#include 
#include "inc/hw_memmap.h"
#include "driverlib/rom.h"

#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"

#include "driverlib/uart.h"
#include "driverlib/udma.h"

#include "driverlib_rom.h"#include


"#include "driverlib_rom.h"#include "#include "#include "driverlib_rom.h"

#include "stdio.h"
#include "drv_adc.h"
#include 
#include "hw_memmap.h"
#include "hw_ints.h"
#include "TIVA_timer.h"
#include "interrupt.h"
#include "rom.h"
#include "plc_config.h"
uint32_t g_ui32SysClock;

//***************
//
// uDMA 控制器使用的控制表。 此表必须与
1024字节边界对齐//。
////
*****************
#if defined (ewarm)
#pragma DATA_alignment=1024
uint8_t pui8ControlTable[1024];
#Elif Defined (CCS)
#pragma DATA_ALIGN (pui8ControlTable、1024)
uint8_t pui8ControlTable[1024];
#else
uint8_t pu8ControlTable[1024]____(dio_attend_)(_1024)


*(_1024)(_diforitudi8ControlTable_)*(_1024)
//
//内存传输源和目的缓冲区的大小(以字为单位)。
////
*****************
#define MEM_buffer_size 1024
//*********
//
//用于内存传输的源和目的缓冲区。
////
*****************
静态 uint32_t g_ui32SrcBuf[MEM_buffer_size];
静态 uint32_t g_ui32DstBuf[MEM_buffer_size];
//*********
//
// uDMA 错误的计数。 此值由 UDMA 错误
//处理程序递增。
////
*****************
静态易失性 uint32_t g_ui32uDMAErrCount = 0;
//*********
//
//内存 uDMA 传输块的计数。
每当一个内存块传输完成时、这个值由// uDMA 中断处理程序递增。
////
*****************
静态易失性 uint32_t g_ui32MemXferCount = 0;
//*********
//
//发生 UDMA 中断但 UDMA 传输未
完成的次数//。 这应该保持为0。
////
*****************
静态易失性 uint32_t g_ui32BadISR = 0;



#defineADC_buff _size64

extern char HardVer[5];

uint32_t ADC_value;

float R=0;
float TEMP=0;
uint16_t g_temp;
uint16_t g_vol;
uint16_t g_ele;
//*********
//
//初始化 UDMA 软件通道以执行内存到内存的 UDMA
//传输。
////
*****************
void
InitADC0Transfer (void)
{
uint_fast16_t ui16Idx;

//
//用简单的递增模式填充源存储器缓冲区。
//
for (ui16Idx = 0;ui16Idx < MEM_buffer_size;ui16Idx++)
{
G_ui32SrcBuf[ui16Idx]= ui16Idx;
}

//
//启用来自 uDMA 软件通道的中断。
//
IntEnable (INT_UDMA);

//
//将 UDMA 软件通道的属性置于已知状态。
//默认情况下,这些应该已经被禁用。
//
uDMAChannelAttributeDisable (UDMA_CHANGE_ADC0、
UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT |
(UDMA_ATTR_HIGH_PRIOR|
uDMA_attr_REQMASK);

//
//配置 SW 通道的控制参数。 开关通道
//将用于在两个存储器缓冲区之间传输,每次32位。
//因此数据大小为32位,地址增量为32位
//用于源和目的。 仲裁数目将设置为8、
//这会导致 UDMA 控制器在8个项目后重新比特率
//已转移。 这可以防止该通道占用 UDMA 控制器
//一旦传输开始,就允许其他通道循环(如果有)
//具有更高的优先级。
//
uDMAChannelControlSet (UDMA_CHANGE_ADC0 | UDMA_PRI_SELECT、
UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 |
UDMA_ARB_8);

//
//设置软件通道的传输参数。 这将会
//配置传输缓冲区和传输大小。 必须为自动模式
//用于软件传输。
//
uDMAChannelTransferSet (UDMA_CHANGE_ADC0 | UDMA_PRI_SELECT、
UDMA_MODE_AUTO、g_ui32SrcBuf、g_ui32DstBuf、
MEM_buffer_size);

//
//现在软件通道被启动一个传输。 通道
//必须启用。 对于基于软件的传输、必须有一个请求
//已印发。 之后、UDMA 存储器传输开始。
//
uDMAChannelEnable (UDMA_CHANGE_ADC0);
uDMAChannelRequest (UDMA_CHANGE_ADC0);
}


//*********
//
// uDMA 错误的中断处理程序。 如果
// uDMA 在尝试执行传输时遇到总线错误,则会发生此中断。 此
//处理程序仅在发生错误时递增计数器。
////
*****************
void uDMAErrorHandler (void)
{
uint32_t ui32Status;

//
//检查 uDMA 错误位
//
ui32Status = uDMAErrorStatusGet ();

//
//如果存在 uDMA 错误,则清除该错误并递增
//错误计数器。
//
if (ui32状态)
{
uDMAErrorStatusClear ();
G_ui32uDMAErrCount++;
}
}

//*********
//
//内存通道中 uDMA 中断的中断处理程序。 此
//中断将递增计数器,然后重新启动另一个内存
//传输。
////
*****************
void
uDMAIntHandler (void)
{
uint32_t ui32模式;

//
//检查主控制结构体以指示完成。
//
ui32Mode = uDMAChannelModeGet (UDMA_CHANGE_ADC0);
if (ui32Mode = uDMA_MODE_STOP)
{
//
//递增已完成传输的计数。
//
G_ui32MemXferCount++;

//
//为另一个传输配置它。
//
uDMAChannelTransferSet (UDMA_CHANGE_ADC0、UDMA_MODE_AUTO、
G_ui32SrcBuf、g_ui32DstBuf、
MEM_buffer_size);

//
//启动另一个传输。
//
uDMAChannelEnable (UDMA_CHANGE_ADC0);
uDMAChannelRequest (UDMA_CHANGE_ADC0);
}

//
//如果通道未停止,则说明有问题。
//
其他
{
G_ui32BadISR++;
}
}



void ADC_Init (void)
{
SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);//ADC0


SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);//ADC GPIO-B VER
GPIOPinTypeADC (GPIO_PORTB_BASE、GPIO_PIN_4);//ADC 引脚
ADCSequenceConfigure (ADC0_BASE、1、ADC_TRIGGER_PROCESSOR、0);
ADCSequenceStepConfigure (ADC0_BASE、1、0、ADC_CTL_CH10 | ADC_CTL_IE |ADC_CTL_END);
ADCSequenceEnable (ADC0_BASE、1);
ADCIntClear (ADC0_BASE、1);
ADCIntEnable (ADC0_BASE、1);


SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE);
GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_5);
ADCSequenceConfigure (ADC0_BASE、3、ADC_TRIGGER_PROCESSOR、0);
ADCSequenceStepConfigure (ADC0_BASE、3、0、ADC_CTL_CH8 | ADC_CTL_IE |ADC_CTL_END);
ADCSequenceEnable (ADC0_BASE、3);
ADCIntClear (ADC0_BASE、3);
ADCIntEnable (ADC0_BASE、3);


SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);//ADC GPIO-E
GPIOPinTypeADC (GPIO_PORTB_BASE、GPIO_PIN_5);//
ADCSequenceConfigure (ADC0_BASE、2、ADC_TRIGGER_PROCESSOR、0);
ADCSequenceStepConfigure (ADC0_BASE、2、0、ADC_CTL_CH11 | ADC_CTL_IE |ADC_CTL_END);
ADCSequenceEnable (ADC0_BASE、2);
ADCIntClear (ADC0_BASE、2);
ADCIntEnable (ADC0_BASE、2);


IntEnable (INT_ADC0SS0);
return;
}

void dma_init (void)
{
//
//在系统级别启用 uDMA 控制器。 使其继续
//在处理器处于睡眠状态时运行。
//
SysCtlPeripheralEnable (SYSCTL_Periph_UDMA);
SysCtlPeripheralSlepEnable (SYSCTL_Periph_UDMA);
//
//启用 uDMA 控制器错误中断。 将发生该中断
//如果在传输过程中出现总线错误。
//
IntEnable (INT_UDMAERR);

//启用 UDMA

uDMAEnable();
//
//指向控制表以用于通道控制结构体。
//
uDMAControlBaseSet (pui8ControlTable);
//
//初始化 UDMA 内存到内存的传输。
//

InitADC0Transfer();

}


void ai_thread (void*参数)
{
int i、value;
浮动 V、I、RV;
float ch_read;
uint32_t p_adc_buff [100];
ADC_Init();
// dma_init();
while (1)
{
//读取第一个电压值使用 ADC
for (i=0;i<100;i++)
{
ADCProcessorTrigger (ADC0_BASE、3);
while (!ADCIntStatus (ADC0_BASE、3、false))
{
}
ADCIntClear (ADC0_BASE、3);
ADCSequenceDataGet (ADC0_BASE、3、&p_ADC_buff [i]);
}
for (i=0、value=0;i<100;i++)
{
值+= p_adc_buff [i];
}
值=值/100;

ch_read = Value*3.3/4096.0;
v = ch_read * 100.0*1000.0/12.0;// V 是正确的值


////////////////////////////////////////////////////////////////////////////////////////// 使用 ADC 读取第二个电压值
for (i=0;i<100;i++)
{
ADCProcessorTrigger (ADC0_BASE、2);
while (!ADCIntStatus (ADC0_BASE、2、false))
{
}
ADCIntClear (ADC0_BASE、2);
ADCSequenceDataGet (ADC0_BASE、2、&p_ADC_buff [i]);
}
for (i=0、value=0;i<100;i++)
{
值+= p_adc_buff [i];
}
值=值/100;

ch_read = Value*3.3/4096.0;
RV = ch_read/(100.0/10.0)/12.0;// RV 是正确的电压值

rt_thread_delay (20);
}
} 

e2e.ti.com/.../7318.adc.c

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您的问题的简单答案是、如果使用不同的序列完成 ADC 采样、则只需使用该 ADC 序列的 UDMA 通道即可。 在上面的代码中、您使用 ADC0序列2和3。 在为 ADC0序列2配置 UDMA 通道16时应使用 UDMA_CHANGE_ADC2、在为 ADC0序列3配置 UDMA 通道17时应使用 UDMA_CHANGE_ADC3。 您使用的是用于序列0的 UDMA_CHANGE_ADC0。

    但是、这是您真正想要的、一个通道上有100次转换、下一个通道上有100次转换? 如果两个通道的读数大致同时完成、请使用一个序列并执行两个步骤。 然后、在数据数组中、交替值将表示来自每个通道的数据。