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.
工具/软件:Code Composer Studio
大家好、
我希望使用 Tiva TM4C123GH6PM 在计时器触发的 ADC 上设置 UDMA。 到目前为止,我发现这个主题非常有启发性: 。
不过、这里的示例代码工作正常、我想获得一个使用 ADC_TRIGGER_TIMER 而不是 ADC_TRIGGER_Always 的解决方案。 原因是我希望有一个精确的采样间隔、以便能够使用我已经设置的 CMSIS DSP 库执行信号处理。 我获取了原始代码并修改了 ConfigADC0函数、如下所示:
遗憾的是、ADC 触发似乎永远不会发生、返回的值始终为9999 (即在主循环之前初始化的值)。
是否有人看到我出错的地方?
是否有人成功创建了一个持续使用定时器触发的 ADC 执行 DMA 传输的 Tiva 项目?
谢谢、
Jim
Bob、
该代码太棒了。 我能够对其进行修改并启动并运行一个非常酷的实时 DSP 示例。
我要在这里展开的一件事是为 DMA 设置多个通道。 我不清楚如何使用您的代码来执行该操作。 给我一个指针吗?
祝您愉快的假期、
Jim
我正在尝试实现您提到的第一种解决方案、这种解决方案应导致在 ADC_OUT 缓冲器中出现交替采样。 我尝试更改 ADC_init 函数中的几行:
GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_2);
输入
GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_3 | GPIO_PIN_2);
和
ADCSequenceStepConfigure (ADC0_BASE、0U、0U、ADC_CTL_CH0| ADC_CTL_END | ADC_CTL_IE);
输入
ADCSequenceStepConfigure (ADC0_BASE、0U、0U、ADC_CTL_CH0);
ADCSequenceStepConfigure (ADC0_BASE、0U、1、ADC_CTL_CH1| ADC_CTL_END | ADC_CTL_IE);
再一次、目标是 ADC_OUT 缓冲器中的样本在 PE3和 PE2捕获的值之间交替。 但是、似乎只有两个通道的其中一个值进入缓冲器。 我错过了什么还是犯了个错误?
您的代码显示正确-但是对于“ ADCSequenceEnable()”的外观 ,它应该(跟在)您的最后一个, “ADCSequenceStepConfigure()”。
由于该函数显示(未显示)-它可能会在代码中的早期出现-因此这可能是可疑的。
您已经很好地添加 了"GPIOPinType ()" (针对您添加的 ADC 通道)-只要您使用"序列3以外的采样序列(其他)"-您转换第二个通道的能力应该是不受阻碍的...
Savo、
您是否能够运行 CMSIS 库中包含的示例代码? 查看此主题 中的 Bruno Saraiva 帖子:
我完全按照他的说明操作、并启动并运行示例代码。 我构建特定应用的方式是:
1.对我的用例进行轻微调整(需要一个 BPF)
3.使用 python 脚本解析该.txt 并将其转换为外部头文件 Coeffs.h
4.对上述 Coeffs.h 进行外部引用
5、拉入发布的代码 Bob 来设置 UDMA 并将其合并、使其以与 CMSIS 示例代码类似的方式运行。
6.将 Bob 的代码中的一些函数折叠到外部.h 文件中,以减少混乱并使其可移植到多个应用程序
就结构而言、我所做的就是"ping-ponging"、在两个通道的每个通道上运行相同的 BPF 滤波器(转换为浮点后)、然后运行 RMS 并检查阈值
我在尝试运行 FIRS 时注意到的一些"明白了":
您必须确保自己
a)为要使用的每个滤波器设置 ARM_fir 实例结构
b)使用所需系数通过 arm_fir 初始化上述结构
c)确保所有指针都正确
d)确保您的输入和输出缓冲器大小相同且正确
e)对足够大的 UDMA 缓冲器进行采样、这样您就可以在不丢失样本的情况下及时完成所需的 FIR (否则您将会得到混叠)。 我的滤波器是128个抽头、在48kHz 的采样率下足够好、但如果采样速度快于该速率、您可能希望开始减少抽头数
f)请记住、每次运行滤波器时、输出中都会出现零输入响应。 这就是为什么我使用"offset"变量来排除该响应并仅保留我信任的样本、这些样本更能指示我要测量的过程变量
总之、这是我的代码。 很抱歉、如果仍然有点马虎、我没有完全玩完
#include #include include "dma_helper.h" #define _FPU_Present 1 #include "TivaHelpers.h" #include "arm_math.h" #include "math_helper.h" //#include "data.h" #include "mceffs.h" #include "hw_ints.memh" #include "hw_map.h" #include "#h.h.intru.h"#include "#include "#h.h.natc.h"#include "#include "#include "#include "#h"#h.natmas.h.h"#include "#include "#include "#include "#include "#h.h.h"#include "#include "natc.h"#include "#include "#include "#include "#h.h.h"#include "#include "natc.h"#include "#include "#h.h"#include "#include "natc.h.h"#include "#include "#include "# "uartstdio.h" #define ADC_SAMPLE_BUF_SIZE 1024 无符号整型 samplingFrequency=48000; //----------------- //声明大小的状态缓冲区(numTaps + blocksize -1) //--------------- static float32_t firStateF32[ADC_SAMPLE_BUF_SIZE + NUM_TAPS - 1]; extern const float32_t firCoeffs32[NUM_TAPS]; //----- /// FIR LPF 的全局变量示例 //--------------------------------- uint32_t blocksize = adc_sample_BUF_size/2; enum BUFFERSTATUS {空, 灌装、 完全 }; #pragma DATA_ALIGN (ucControlTable、1024) uint8_t ucControlTable[1024]; //用于保存每个通道的交替样本 的缓冲器//双通道 静态 uint16_t ADC_Out1[ADC_SAMPLE_BUF_SIZE]; 静态 uint16_t ADC_OUT2[ADC_SAMPLE_OUTEST_LD];静态 U32_ADC_F_ADC_F_ADC_SAMPLE_LD32_ADC_SAMPLE_ADC_ENGE] ;静态 转换后的静态 uat1_ADC_F_ADC_F_OUT1_ADC_F_OUT3_ADC_OUTESHOLD32_ADC_F_ADC_OUT3_ADC_ADC_ADC_ADC_ADC_SAMPLE_OUTESHOLD32_ADC_ADC_ADC_ADC_ADC_ADC_ADC_ADC_ 静态 float32_t filtered_adc_Out2_PE3[adc_sample_bf_size/2]; 静态 float32_t converted_adc_Out1_PE2[adc_sample_bf_size/2]; 静态 float32_t filtered_adc_Out1_PE2[adc_sample_out2_t_size/t_adc_size_out2];静态 f_out2_t_atf_out2_adc_out2_t_sample_out2_t_sample_out2_at_out2_at_out2_at_out2_adc_out2_adc_out2_at_out2_at_out2_at_out2_at_out2_at_out2_at_ 静态枚举 BUFFERSTATUS 缓冲器状态[2]; 静态 uint32_t g_ui32DMAErrCount = 0U; 静态 uint32_t g_ui32SysTickCount; int firstLoop = 1; void init_dma (void); void uDMAErrorHandler (void) { uint32_t ui32Status; ui32Status = map_uDMAErrorStatusGet (); if (ui32状态) { map_uDMAErrorStatusClear (); G_ui32DMAErrCount++; } } //本例中未使用,但用于调试以确保计时器中断发生 void Timer0AIntHandler (void) { // //清除计时器中断标志。 // TimerIntClear (TIMER0_BASE、TIMER_TINA_TIMEOUT); } void SysTickIntHandler (void) { //更新我们的系统节拍计数器。 G_ui32SysTickCount++; } void ADCseq0Handler() { ADCIntClear (ADC0_BASE、0); 如果((uDMAChannelModeGet (UDMA_CHANGE_ADC0 | UDMA_PRI_SELECT)== UDMA_MODE_STOP) &&(缓冲器状态[0]=填充) { BufferStatus[0]=满; BufferStatus[1]=填充; } 否则、如果((uDMAChannelModeGet (uDMA_CHANGE_ADC0 | UDMA_ALT_SELECT)=UDMA_MODE_STOP) &&(缓冲器状态[1]==填充) { BufferStatus[0]=填充; BufferStatus[1]=满; } } int main (void) { // int debugFlag=0; uint32_t i、average1、average2、samples_taken; float32_t RMS1、RMS2; BufferStatus[0]=填充; BufferStatus[1]=空; samples_taken = 0U; //打开 GPIO C 引脚7、6、5 //分配: //引脚7 =转换 //引脚6 = FIR //引脚5 = RMS init_PortC_outputs(); //设置 FIR 填充// //为每个过滤器实例初始化结构 ARM_Fir 实例 F32 S; ////调用 FIR 初始化函数来初始化实例结构。 arm_fir_init_F32 (&S、NUM_TAPS、(float32_t *)&firCoeffs32[0]、&StatefirF32[0]、blocksize); DMA_prime (ADC_SAMPLE_BUF_SIZE、ADC_Out1、ADC_Out2、采样频率); uint32_t offset=128; float32_t 曲折1=0; float32_t 曲折2=0; while (1) { if (缓冲器状态[0U]==满) { //对 ADC_Out1_PE3中的数据执行一些操作 平均值1 = 0U; GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_7、0); 对于(I =0U;I < ADC_SAMPLE_BUF_SIZE;I=i+2) { conved_adc_Out1_PE3[I/2]=(float32_t) 3.3*adc_Out1[I]/4095; conved_adc_Out1_PE2[I/2]=(float32_t) 3.3*adc_Out1[I+1]/4095; } GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_7、GPIO_PIN_7); //对数据运行 FIR if (!firstLoop){ //待办事项: //1. 列出所有变量和方框图 //2. 创建必要的变量以存储有关 CH2的信息 //3. 执行滤波 //4. 输出电感值以及各个电压电平 GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_6、0); ARM_fir F32 (&S、converted_adc_Out1_PE3[0]、Filtered_adc_Out1_PE3[0]、blocksize); GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_6、GPIO_PIN_6); //计算 RMS 值 GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_5、0); arm_rms_F32 (已过滤的 ADC_Out1_PE3[offset]、blocksize-offset、&RMS1); arm_mean_F32 (&filtered_adc_Out1_PE3[offset]、blocksize-offset、&qualing1); RMS1=RMS1-曲折1; GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_5、GPIO_PIN_5); } average1=(uint32_t) 1000*RMS1; BufferStatus[0U]=空; //为另一个 uDMA 块传输启用 uDMAChannelTransferSet (UDMA_CHANGE_ADC0 | UDMA_PRI_SELECT、UDMA_MODE_PINGONG、(void *)(ADC0_BASE + ADC_O_SSFIFO0)、&ADC_Out1、ADC_SAMPLE_BUF_SIZE); uDMAChannelEnable (UDMA_CHANGE_ADC0 | UDMA_PRI_SELECT);//启用 DMA 通道以便它可以执行传输 samples_taken += ADC_sample_BUF_size; } if (缓冲器状态[1U]==满) { //对 ADC_Out2_PE3中的数据执行一些操作 平均值2 = 0U; GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_7、0); 对于(I =0U;I < ADC_SAMPLE_BUF_SIZE;I=i+2) { conved_adc_Out2_PE3[I/2]=(float32_t) 3.3*adc_Out2[I]/4095; conved_adc_Out1_PE2[I/2]=(float32_t) 3.3*adc_Out1[I+1]/4095; } GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_7、GPIO_PIN_7); //对数据运行 FIR if (!firstLoop){ GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_6、0); ARM_fir F32 (&S、converted_adc_Out2_PE3[0]、Filtered_adc_Out2_PE3[0]、blocksize); GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_6、GPIO_PIN_6); //计算 RMS 值 GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_5、0); arm_rms_F32 (已过滤的 ADC_Out2_PE3[offset]、blocksize-offset、&RMS2); arm_mean_F32 (&filtered_adc_Out2_PE3[offset]、blocksize-offset、&qual.2); RMS1=RMS2-曲折2; GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_5、GPIO_PIN_5); } average2=(uint32_t) 1000*RMS1; BufferStatus[1U]=空; //为另一个 uDMA 块传输启用 uDMAChannelTransferSet (UDMA_CHANGE_ADC0 | UDMA_ALT_SELECT、UDMA_MODE_PINGONG、(void *)(ADC0_BASE + ADC_O_SSFIFO0)、&ADC_Out2、ADC_SAMPLE_BUF_SIZE); // uDMAChannelTransferSet (UDMA_CHANGE_ADC0 | UDMA_ALT_SELECT、UDMA_MODE_PINGONG、(void *)(ADC0_BASE + ADC_O_SSFIFO3)、&ADC_Out2_PE2、ADC_SAMPLE_BUF_SIZE); uDMAChannelEnable (UDMA_CHANGE_ADC0 | UDMA_ALT_SELECT); samples_taken += adc_sample_BUF_size; ///清除第一个循环问题// if (firstLoop){ average1=0U; average2=0U; samples_take=0U; firstLoop = 0; } UARTprintf ("\t\t%d \t%d \t%d \t\t%d \t%d \r"、average1、average2、samples_taken); } } void init_dma (void) { uDMAEnable();//启用 UDMA uDMAControlBaseSet (ucControlTable); uDMAChannelAttributeDisable (UDMA_CHANGE_ADC0、UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIOR| UDMA_ATTR_REQMASK); uDMAChannelAttributeEnable (UDMA_CHANGE_ADC0、UDMA_ATTR_USEBURST); //仅允许突发传输 //单通道 // uDMAChannelControlSet (UDMA_CHANNE_ADC0 | UDMA_PRI_SELECT、UDMA_SIZE 16 | UDMA_SRC_DSP_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); // uDMAINC_CONTROL1 (UDMA_ADC0 | UINC_NONE | UDMA_SELECT 16 | UDMA_DMA_ADC_DMA uDMAChannelControlSet (UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT、UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_ARC_16 | UDMA_INC_2); uDMAChannelControlSet (UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT、UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_ARC_16 | UDMA_INC_2); uDMAChannelTransferSet (UDMA_CHANGE_ADC0 | UDMA_PRI_SELECT、UDMA_MODE_PINGONG、(void *)(ADC0_BASE + ADC_O_SSFIFO0)、&ADC_Out1、ADC_SAMPLE_BUF_SIZE); uDMAChannelTransferSet (UDMA_CHANGE_ADC0 | UDMA_ALT_SELECT、UDMA_MODE_PINGONG、(void *)(ADC0_BASE + ADC_O_SSFIFO0)、&ADC_Out2、ADC_SAMPLE_BUF_SIZE); uDMAChannelEnable (UDMA_CHANGE_ADC0);//启用 DMA 通道以便它可以执行传输 //ToDo 添加第二个频道 //需要相应地更改 ADC 设置 //需要更改仲裁数目 }
@海报 James、
"喜欢-喜欢-喜欢!"
杰出的帖子--"周到、细致、守卫班德(Gotcha's)和... (非仓促)... 真正的组织和关怀!"
干得好-远远地说、"恢复被禁止的样子"-你的努力 (显然)值得!
@ James、
我准备"借给"(或出租)我的手枪。 (快速/完全-"消除伤害"-此类(静音)赞赏...)