一、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/zh-tw/n/242841.html