一、ADCDMA概述
ADCDMA是指将模拟信号转换成数字信号,然后通过DMA技术将数字信号直接传输到内存中的一种技术。
ADCDMA技术在分布式控制系统、自动化控制、通信系统等领域得到广泛应用。
二、ADCDMA显示波形
通过ADCDMA技术可以获取模拟信号的数字信号,然后将其显示成波形。
/* ADCDMA显示波形代码示例 */ #include #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "inc/hw_adc.h" #include "inc/hw_ints.h" #include "driverlib/adc.h" #include "driverlib/gpio.h" #include "driverlib/sysctl.h" #include "driverlib/interrupt.h" /* ADC初始化,设置采样率为250KSPS */ void ADC_Init(void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0); ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH0|ADC_CTL_IE|ADC_CTL_END); ADCSequenceEnable(ADC0_BASE, 1); } /* DMA初始化 */ void DMA_Init(void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_DMA); SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); uDMAEnable(); uDMAControlBaseSet(g_psDMAControlTable); uDMAChannelAssign(UDMA_CH13_ADC0_1); uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0, UDMA_ATTR_ALL); uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_64); uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void*)(ADC0_BASE + ADC_O_SSFIFO1), g_adcBuffer, ADC_BUFFER_SIZE/2); uDMAChannelEnable(UDMA_CHANNEL_ADC0); } /* 开始采样 */ void ADC_Sample(void) { /* ADCDMA采样开始 */ ADCProcessorTrigger(ADC0_BASE, 1); /* 等待DMA传输完成 */ while(!uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT)); }
三、ADCDMA中断多通道采集
ADCDMA中断采集时,可以同步采集多个通道的信号。
/* ADCDMA中断多通道采集代码示例 */ #include #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "inc/hw_adc.h" #include "inc/hw_ints.h" #include "driverlib/adc.h" #include "driverlib/gpio.h" #include "driverlib/sysctl.h" #include "driverlib/interrupt.h" #define ADC_CHANNEL_NUM 2 uint32_t g_adcValues[ADC_CHANNEL_NUM]; void ADCInit(void) { /* ADC0采样率配置 */ SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0); ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 3, 1, ADC_CTL_CH1|ADC_CTL_IE|ADC_CTL_END); ADCSequenceEnable(ADC0_BASE, 3); /* 中断配置 */ ADCIntEnable(ADC0_BASE, 3); ADCIntRegister(ADC0_BASE, 3, ADCIntHandler); IntPrioritySet(INT_ADC0SS3, 0x00); IntEnable(INT_ADC0SS3); } void ADCIntHandler(void) { /* 清除中断标志位 */ ADCIntClear(ADC0_BASE, 3); /* 获取ADC数值 */ ADCSequenceDataGet(ADC0_BASE, 3, g_adcValues); } void ADCCollect(void) { /* ADC中断采样开始 */ ADCProcessorTrigger(ADC0_BASE, 3); /* 等待中断完成 */ while(ADCIntStatus(ADC0_BASE, 3, false) == 0) {} }
四、ADCDMA数据错位
当ADCDMA采集数据出现错位时,需要对数据进行调整或再次采样。
五、ADCDMA只转换了一次
如果只进行一次采集和转换,可以采用CPU读取方式,不需要使用DMA。
六、ADCDMA应用实例
以ADCDMA采集电流电压信号并实时显示为例,代码如下:
/* ADCDMA电流电压采集和显示代码示例 */ #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_adc.h" #include "driverlib/adc.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/sysctl.h" #include "driverlib/timer.h" #include "utils/uartstdio.h" /* 定义ADC通道以及数组 */ #define ADC_SEQUENCE_NUM 0 #define ADC_SEQUENCE_PRIORITY ADC_CTL_CH0 #define ADC_SEQUENCE_SAMPLE_RATE 8000 #define ADC_STATUS_BUF_DEPTH 8 #define ADC_RESULT_BUF_DEPTH 8 int32_t pui32ADC0Status[ADC_STATUS_BUF_DEPTH]; int32_t pui32ADC0Value[ADC_RESULT_BUF_DEPTH]; int32_t i32ADCSum; uint32_t ADCCurrentValue; uint32_t ADCVoltageValue; uint32_t ui32ADCSampleCount = 0; void ADCIntHandler(void) { ADCSequenceDataGet(ADC0_BASE, ADC_SEQUENCE_NUM, pui32ADC0Value); ADCSequenceDataGet(ADC0_BASE, ADC_SEQUENCE_NUM | ADC_CTL_CMP0, pui32ADC0Status); ui32ADCSampleCount++; /* 计算平均值 */ for(uint8_t i = 0; i < ADC_STATUS_BUF_DEPTH; i++) { i32ADCSum += pui32ADC0Status[i]; } ADCCurrentValue = i32ADCSum/ADC_STATUS_BUF_DEPTH; i32ADCSum = 0; for(uint8_t i = 0; i < ADC_RESULT_BUF_DEPTH; i++) { i32ADCSum += pui32ADC0Value[i]; } ADCVoltageValue = i32ADCSum/ADC_RESULT_BUF_DEPTH; i32ADCSum = 0; } void TimerIntHandler(void) { /* 显示电流电压 */ UARTprintf("Current is %d mA, voltage is %d mV\n", ADCCurrentValue, ADCVoltageValue); /* 清除中断标志位 */ TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); } int main(void) { /* 系统时钟设置至80MHz */ SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ); /* IO口设置为ADC输入 */ SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2); /* ADC采样初始化 */ SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 8); ADCSequenceConfigure(ADC0_BASE, ADC_SEQUENCE_NUM, ADC_TRIGGER_PROCESSOR | ADC_SEQUENCE_PRIORITY, 0); ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQUENCE_NUM, 0, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END); ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQUENCE_NUM | ADC_CTL_CMP0, 0, ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END); ADCSequenceOverflowConfigure(ADC0_BASE, ADC_SEQUENCE_NUM, ADC_OVS_FIELD_NONE | ADC_OVS_RATE_HALF); ADCSequenceOverflowConfigure(ADC0_BASE, ADC_SEQUENCE_NUM | ADC_CTL_CMP0, ADC_OVS_FIELD_NONE | ADC_OVS_RATE_HALF); ADCSequenceDMAEnable(ADC0_BASE, ADC_SEQUENCE_NUM); ADCSequenceDMAEnable(ADC0_BASE, ADC_SEQUENCE_NUM | ADC_CTL_CMP0); ADCIntRegister(ADC0_BASE, ADC_SEQUENCE_NUM, ADCIntHandler); ADCIntEnable(ADC0_BASE, ADC_SEQUENCE_NUM | ADC_CTL_CMP0); ADCSequenceEnable(ADC0_BASE, ADC_SEQUENCE_NUM | ADC_CTL_CMP0); ADCProcessorTrigger(ADC0_BASE, ADC_SEQUENCE_NUM); int32_t i32Err; i32Err = TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet()/100); // 1秒钟100次 TimerIntRegister(TIMER0_BASE, TIMER_A, TimerIntHandler); TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); TimerEnable(TIMER0_BASE, TIMER_A); /* 初始化UART输出 */ SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); UARTStdioConfig(0, 115200, SysCtlClockGet()); while(1) { } }
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/242841.html