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.

EK-TM4C1294XL: ADC定时器触发,速率达不到2M

Part Number: EK-TM4C1294XL

#include "bsp.h"
#include "inc/hw_memmap.h"
#include "inc/hw_adc.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/adc.h"
#include "driverlib/udma.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "string.h"
#define DMA_CHANNEL UDMA_CHANNEL_ADC0

// 全局变量
uint16_t Data[ADC_SAMPLE_BUF_SIZE];  // 存储完整 ADC 数据的数组
volatile uint8_t flag = 0;           // 标志采集是否完成
uint16_t ADCBuffer1[DMA_TRANSFER_SIZE];  // 缓冲区1
uint16_t ADCBuffer2[DMA_TRANSFER_SIZE];  // 缓冲区2
uint16_t bufferIndex = 0;           // 当前搬移到 Data 数组的索引
uint16_t totalSamples = 0;          // 记录已搬移的总样本数
static uint8_t ControlTable[1024] __attribute__((aligned(1024)));  // DMA 控制表

BUFFER_STATUS BufferStatus[2];  // 缓冲区状态

// ADC 队列 0 中断服务程序
void ADC0SS0_Handler(void) {
    // 清中断标志
    ADCIntClear(ADC0_BASE, 0);
		ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS0);
    if ((uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT) ==
                            UDMA_MODE_STOP) && (BufferStatus[0] == FILLING)) {
        BufferStatus[0] = FULL;
        BufferStatus[1] = FILLING;
    } else if ((uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT) ==
                                 UDMA_MODE_STOP) && (BufferStatus[1] == FILLING)) {
        BufferStatus[0] = FILLING;
        BufferStatus[1] = FULL;
    }
		if(BufferStatus[0] == FULL) {
					BufferStatus[0] = EMPTY;
					//使能另一个传输块
					uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
																 UDMA_MODE_PINGPONG,
																 (void *)(ADC0_BASE + ADC_O_SSFIFO0),
																 ADCBuffer1, DMA_TRANSFER_SIZE);
					//启动DMA通道
					uDMAChannelEnable(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT);
//					for(uint16_t i =0 ;i<DMA_TRANSFER_SIZE ; i++)
//						Data[totalSamples++]=ADCBuffer1[i];
					memcpy(Data+totalSamples,ADCBuffer1,DMA_TRANSFER_SIZE*sizeof(uint16_t));
					totalSamples+=1024;
																 
			} else if(BufferStatus[1] == FULL) {

					BufferStatus[1] = EMPTY;

					uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
																 UDMA_MODE_PINGPONG,
																 (void *)(ADC0_BASE + ADC_O_SSFIFO0),
																 ADCBuffer2, DMA_TRANSFER_SIZE);
					uDMAChannelEnable(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT);
//					for(uint16_t i =0 ;i<DMA_TRANSFER_SIZE ; i++)
//						Data[totalSamples++]=ADCBuffer2[i];
					memcpy(Data+totalSamples,ADCBuffer2,DMA_TRANSFER_SIZE*sizeof(uint16_t));
					totalSamples+=1024;
			}
			if(totalSamples >=ADC_SAMPLE_BUF_SIZE){
				flag=1;
				StopADC();
			}
}


// 初始化 ADC 和 DMA
void bsp_InitAdc0(void) {
    BufferStatus[0] = FILLING;
    BufferStatus[1] = EMPTY;

    // 启用外设
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    // 配置 GPIO
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);  // PE3 作为 ADC 输入引脚

    // 启用并配置 DMA
    uDMAEnable();
    uDMAControlBaseSet(ControlTable);

    uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

    // 设置 DMA 主控制块
    uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);

    // 设置 DMA 副控制块
    uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);

    // 设置 DMA 传输(主缓冲区)
    uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADCBuffer1, DMA_TRANSFER_SIZE);

    // 设置 DMA 传输(副缓冲区)
    uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADCBuffer2, DMA_TRANSFER_SIZE);

    uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC0, UDMA_ATTR_USEBURST);
    uDMAChannelEnable(UDMA_CHANNEL_ADC0);

    // 配置 ADC
    ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_FULL, 1);
    SysCtlDelay(10);

    ADCSequenceDisable(ADC0_BASE, 0);
    ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0 | ADC_CTL_END);

    ADCSequenceEnable(ADC0_BASE, 0);
    ADCSequenceDMAEnable(ADC0_BASE, 0);
    ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS0);

    IntEnable(INT_ADC0SS0);
    IntMasterEnable();

    // 配置定时器
    TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC);
    TimerLoadSet(TIMER0_BASE, TIMER_A, (SystemCoreClock / 2000000) - 1);
    TimerControlTrigger(TIMER0_BASE, TIMER_A, true);
}

// 启动 ADC
void StartADC(void) {
    // 重置标志和计数器
    flag = 0;
    totalSamples = 0;

    // 重新初始化缓冲区状态
    BufferStatus[0] = FILLING;
    BufferStatus[1] = EMPTY;

    // 清除可能残留的中断标志
    ADCIntClear(ADC0_BASE, 0);


    // 启用 DMA 通道
    uDMAChannelEnable(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT);
    uDMAChannelEnable(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT);

    // 重新使能 ADC 采样序列
    ADCSequenceEnable(ADC0_BASE, 0);
		IntEnable(INT_ADC0SS0);
    // 启用定时器,触发 ADC 采样
    TimerEnable(TIMER0_BASE, TIMER_A);
}


// 停止 ADC
void StopADC(void) {
    
    // 禁用定时器
    TimerDisable(TIMER0_BASE, TIMER_A);
    
    // 禁用 DMA 通道
    uDMAChannelDisable(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT);
    uDMAChannelDisable(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT);


    // 禁用 ADC 中断
    ADCIntDisable(ADC0_BASE, 0);
    IntDisable(INT_ADC0SS0);

    // 确保清除所有中断标志
    ADCIntClear(ADC0_BASE, 0);
	
	
		
}
你好,我的ADC进行定时器触发时,速率最大只能达到1M,定时器频率超过1M后,采集的信号导出发现仍然是以1M采样率采样得到,小于1M时采样率正常。请问是什么原因,我应该如何改进?