#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时采样率正常。请问是什么原因,我应该如何改进?