一、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-hk/n/242841.html
微信掃一掃
支付寶掃一掃