一、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
微信扫一扫
支付宝扫一扫