#include "dma_adc.h"
#include "SysTick.h"
#include "led.h"
u16 temp;
void DMA_ADC_NIVC_Init(void){
//定义结构体变量
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//时钟配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//DMA1时钟使能
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//GPIO配置
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1;//ADC
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AIN; //模拟输入
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//ADC配置
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//开启连续转换
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不使用外部触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1;//1个转换在规则序列中 也就是只转换规则序列1
ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化
//ADC中断使能模块
ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);
ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);
//中断结构体配置
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;//ADC1中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
//ADC规则通道配置、DAM开启、ADC开启
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
ADC_DMACmd(ADC1,ENABLE);
ADC_Cmd(ADC1, ENABLE);//开启AD转换器
//ADC复位配置
ADC_ResetCalibration(ADC1);//重置指定的ADC的校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1));//获取ADC重置校准寄存器的状态
ADC_StartCalibration(ADC1);//开始指定ADC的校准状态
while(ADC_GetCalibrationStatus(ADC1));//获取指定ADC的校准程序
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
//DMA配置
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//DMA-ADC1外设地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&temp;//DMA存储器地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//存储器到外设模式
DMA_InitStructure.DMA_BufferSize = 1;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据长度:16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//存储器数据长度:16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 使用循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//中等优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);//初始化DMA
}
//中段函数的配置
void ADC1_2_IRQHandler(void){
float vol;
if(ADC_GetITStatus(ADC1,ADC_IT_EOC)){//ADC发生中断
DMA_Cmd(DMA1_Channel1,DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel1,1);
DMA_Cmd(DMA1_Channel1,ENABLE);//开启DMA
if(DMA_GetFlagStatus(DMA1_FLAG_TC1)){//传输完成
DMA_ClearFlag(DMA1_FLAG_TC1);//清除标志
vol = (float)temp*(3.3/4096);//转换电压
if(vol > 2.4){//电压处理
led2 = !led2;
}
else{
led3 = !led3;
}
delay_ms(5);
}
}
ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);//清除中断标志
}
头文件
#ifndef _dma_adc_H
#define _dma_adc_H
#include "system.h"
void DMA_ADC_NIVC_Init(void);
#endif
main函数
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "dma_adc.h"
int main()
{
u8 i=0;
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
LED_Init();
DMA_ADC_NIVC_Init();
while(1)
{
i++;
if(i%20==0)
{
led1=!led1;
}
delay_ms(10);
}
}
我是用的是ADC1通道1通过声音传感器采集电压来控制led2的熄灭。程序写入单片机内,只有显示系统正常运行的led1闪烁和led3常亮,按道理应该是如果没有电压转换超过2.4V的话led3也是闪烁的才对,求大家赐教。
不知道你这个问题是否已经解决, 如果还没有解决的话: