stm32f407 adc的dma中断方式

2019-10-08来源: eefocus关键字:stm32f407  adc  dma  中断方式

#include "adc.h"

/* 数据定义 */
u8 UpdataTIM = 0;        //更新TIM2定时器标志
u16 CurrentFreq = 500;//默认市电频率,单位为0.1hz
ADBASE_TYPE uAD_Buff_A[ADC_CHANNEL];        //ADC采集缓存A
ADBASE_TYPE uAD_Buff_B[ADC_CHANNEL];        //ADC采集缓存B
//考虑到可能出现的数据处理时间较长的问题,临时添加缓存
//u16 uAD_IN_BUFF[ADC_BUFFSIZE][ADC_CHANNEL];
ADBASE_TYPE *CurrentBuffPtr = NULL;        //当前缓存指针
/*
 * Function    : static void ADCInit_GPIO(void)
 * Description : ADCGPIO初始化
 * Arguments   : 无
 * Returns     : 无
 * Other       :
 */
static void ADCInit_GPIO(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟

    //ADC通道初始化
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|  
                                    GPIO_Pin_9|GPIO_Pin_10; //PF3,PF4,PF5,PF6,PF7,PF8,PF9,PF10 ADC通道
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;  //模拟输入
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  //不带上下拉
    GPIO_Init(GPIOF, &GPIO_InitStructure);  //初始化     
}
/*
 * Function    : static void ADCInit_ADC(void)
 * Description : ADC模式初始化
 * Arguments   : 无
 * Returns     : 无
 * Other       :
 */
static void ADCInit_ADC(void)
{
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    ADC_InitTypeDef       ADC_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); //使能ADC3时钟
    
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE);      //ADC3复位
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE); //复位结束     

    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; //两个采样阶段之间的延迟5个时钟(三重模式或双重模式下使用)
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能(对于多个ADC模式)
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz 
    ADC_CommonInit(&ADC_CommonInitStructure);//初始化
    
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;//扫描模式(多通道ADC采集要用扫描模式)    
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换
//    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //软件触发
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising; //上升沿触发
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;  //定时器事件2触发ADC
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐    
    ADC_InitStructure.ADC_NbrOfConversion = ADC_CHANNEL;    //8个转换在规则序列中
    ADC_Init(ADC3, &ADC_InitStructure);//ADC初始化
    
    //连续模式下,通道的配置
    ADC_RegularChannelConfig(ADC3, ADC_Channel_9, 1, ADC_SampleTime_15Cycles);  //PF3,VIN1,通道9,UA,rank=1,表示连续转换中第一个转换的通道,采样时间15个周期(如果数据不稳定可以延时采样时间)
    ADC_RegularChannelConfig(ADC3, ADC_Channel_14, 2, ADC_SampleTime_15Cycles); //PF4,VIN2,通道14,UB
    ADC_RegularChannelConfig(ADC3, ADC_Channel_15, 3, ADC_SampleTime_15Cycles); //PF5,VIN3,通道15,AC220
    ADC_RegularChannelConfig(ADC3, ADC_Channel_4, 4, ADC_SampleTime_15Cycles);     //PF6,VIN4,通道4,I0
    ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 5, ADC_SampleTime_15Cycles);     //PF7,VIN5,通道5,IA
    ADC_RegularChannelConfig(ADC3, ADC_Channel_6, 6, ADC_SampleTime_15Cycles);     //PF8,VIN6,通道6,IB
    ADC_RegularChannelConfig(ADC3, ADC_Channel_7, 7, ADC_SampleTime_15Cycles);     //PF9,VIN7,通道7,IC
    ADC_RegularChannelConfig(ADC3, ADC_Channel_8, 8, ADC_SampleTime_15Cycles);     //PF10,VIN8,通道8,暂时未接入信号

    ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); //连续使能DMA
    ADC_DMACmd(ADC3, ENABLE);  //使能ADC_DMA
    ADC_Cmd(ADC3, ENABLE);//开启AD转换器    
}
/*
 * Function    : static void ADCInit_DMA(void)
 * Description : ADC使能DMA模式
 * Arguments   : 无
 * Returns     : 无
 * Other       :
 */
static void ADCInit_DMA(void)
{
    DMA_InitTypeDef  DMA_InitStructure;
    
    //时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    
    //DMA设置
    DMA_InitStructure.DMA_Channel = DMA_Channel_2; //选择通道号
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC3->DR); //外围设备地址,ADC_DR_DATA规则数据寄存器
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(u16 *)uAD_Buff_A; //DMA存储器地址,自己设置的缓存地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //传输方向,外设->存储器
    DMA_InitStructure.DMA_BufferSize = ADC_BUFFSIZE * ADC_CHANNEL; //DMA缓存大小,数据传输量32*8
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设是否为增量模式
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器是否为增量模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据长度半个字(16位)
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //存储器数据长度半字(16位)
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA模式,普通模式、循环模式,还有双缓冲模式,需要特殊设置
    DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA优先级,高优先级
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //不使用FIFO
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; //FIFO阈值
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发,单次传输
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发,单次传输
    DMA_Init(DMA2_Stream0, &DMA_InitStructure); //初始化DMA2_Stream0,对应为ADC3

    //双缓冲模式设置
    DMA_DoubleBufferModeConfig(DMA2_Stream0,(uint32_t)(u16 *)(uAD_Buff_B),DMA_Memory_0);    //DMA_Memory_0首先被传输
    DMA_DoubleBufferModeCmd(DMA2_Stream0,ENABLE);
    
    //设置DMA中断
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TC); //清除中断标志   
    DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE); //传输完成中断                                       
    DMA_Cmd(DMA2_Stream0, ENABLE); //使能DMA
    
}
/*
 * Function    : void ADCInit_Timer(void)
 * Description : ADC触发定时器的设置
 * Arguments   : 无
 * Returns     : 无
 * Other       :
 */
void ADCInit_Timer(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    //时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);          

    //失能定时器
    TIM_Cmd(TIM2, DISABLE);
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); //初始化定时器
    
    //定时器设置,T=(84 * 625) / 84M = 625us = 20ms/32,50Hz信号,每周期采样32个点,采样频率1600
    TIM_TimeBaseStructure.TIM_Prescaler = 84-1; //分频系数,TIM2时钟在分频系数不为1时,时钟是APB1时钟的两倍84M
    TIM_TimeBaseStructure.TIM_Period = 312500/CurrentFreq - 1; //周期值1M/32=31250,CurrentFreq单位为0.1hz,因此需扩大10倍
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频因子
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up ; //向上计数模式
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定时器2
    
    //使能定时器中断    
    TIM_ARRPreloadConfig(TIM2, ENABLE); //允许TIM2定时重载
    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);  //选择TIM2的UPDATA事件更新为触发源
//    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //配置TIM2中断类型
    
    //使能TIM2
    TIM_Cmd(TIM2, ENABLE); 
    DebugLog("Enable TIM2, Set frequency is %d.", CurrentFreq);
}
/*
 * Function    : void ADCInit_Nvic(void)
 * Description : 中断初始化
 * Arguments   : 无
 * Returns     : 无
 * Other       :
 */
static void ADCInit_Nvic(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    
    //定时器中断设置
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //定时器TIM2中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;  //抢占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;        //子优先级1
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化NVIC寄存器    
    
    //DMA中断设置
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;  //DMA2_Stream0中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;  //抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;        //子优先级1
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化NVIC寄存器    
}
/*
 * Function    : void  ADCInit(void)
 * Description : ADC初始化函
 * Arguments   : 无
 * Returns     : 无
 * Other       :
 */                                                           
void ADCInit(void)
{
    ADCInit_GPIO();
    ADCInit_DMA();
    ADCInit_ADC();
    ADCInit_Nvic();
    DebugLog("ADC Init is finish.");
}    
/*
 * Function    : void TIM2_IRQHandler(void) 
 * Description : TIM2中断触发函数
 * Arguments   : 无
 * Returns     : 无
 * Other       :
 */
void TIM2_IRQHandler(void)  
{
  OSIntEnter(); //进入中断    
    
    if(TIM_GetITStatus(TIM2, TIM_IT_Update))  //判断发生update事件中断  
    {         
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除update事件中断标志
//    ADC_SoftwareStartConv(ADC1);      
    }
    
    OSIntExit();  //退出中断  
}
/*
 * Function    : void DMA2_Stream0_IRQHandler(void) 
 * Description : DMA2_Stream0中断
 * Arguments   : 无
 * Returns     : 无
 * Other       :
 */
void DMA2_Stream0_IRQHandler(void)  
{
    u16 period = 0;
    
  OSIntEnter(); //进入中断 
    if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))  //判断DMA传输完成中断  
    {
         DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
//         DMA_Cmd(DMA2_Stream0, ENABLE); //使能DMA,连续模式下不需要该使能
         //数据转移程序
         if(DMA_GetCurrentMemoryTarget(DMA2_Stream0) == DMA_Memory_0)
         {
             CurrentBuffPtr = uAD_Buff_A;
         }
         else
         {
             CurrentBuffPtr = uAD_Buff_B;
         }
         //遥测任务等待该信号量
         OSSemPost(SemAD);
         
         //判断是否更新TIM2
         if(UpdataTIM)
         {
             period = 312500/CurrentFreq - 1;        //计算采样频率1M/32=31250;32为采样点数,31250/freq=采样周期
             TIM_ARRPreloadConfig(TIM2, DISABLE); //关闭TIM2定时重载
             TIM2->ARR = period ;        //更新定时器周期
             TIM_ARRPreloadConfig(TIM2, ENABLE);     //打开TIM2定时重载
         }
    }
    OSIntExit();  //退出中断  
}

关键字:stm32f407  adc  dma  中断方式 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic476356.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:stm32 freertos 之串口中断
下一篇:STM32中断及FreeRTOS中断优先级配置知识

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

stm32f0 hal adc配置
Clock Prescaler:和系统时钟同步并且二分频Sampling Time :采样时间,采样时间是你通过寄存器告诉STM32采样模拟量的时间,设置越长越精确
发表于 2019-11-11
stm32f0 hal adc配置
STM32F0xx_看门狗(独立+窗口)配置详细过程
Ⅰ、概述对于看门狗,我觉得做单片机或者嵌入式开发的人员来说并不陌生,今天总结STM32F0看门狗的功能,F0的看门狗有两种:独立和窗口看门狗。今天提供两种看门狗的软件工程实例,供大家下载。两种看门狗各有各的特点,应用在不同的场合,下面将分别简单总结一下独立和窗口看门狗的功能。Ⅱ、下载文章提供的“软件工程”都是在硬件板子上进行多次测试、并保证没问题才上传至360云盘,请放心下载测试,如有问题请检查一下你的板子是否有问题。ST标准外设库和参考手册、数据手册等都可以在ST官网下载,你也可以到我的360云盘下载。关于F0系列芯片的参考手册有多个版本(针对F0不同芯片),但有一个通用版本,就是“STM32F0x128参考手册V8(英文
发表于 2019-11-08
STM32F0xx_看门狗(独立+窗口)配置详细过程
stm32f030cc 替换 stm32f030c8 后程序下载失败问题
最近手头有个项目,开始用的是STM32F030C8T6 这款芯片,但随着后期程序代码增加以及功能增加,发现片上的RAM及FLASH均不够用,第一想到的是找ST中引脚兼容的同系列MCU替换,很自然地找到了STM32F030CCT6这款芯片。替换之前特意看了一下两款芯片是硬件资源是兼容的还用STCUBE配了一个功能引脚 ,功能配置没有问题,ok接下来就是买芯片给换上,。。。。当把芯片换上后,来试试烧录,出现 cannot reset target 错误,一开始还以为是芯片没焊好,重新焊,还是不行,找个新板子再焊一块,还是同样的问题,然后是换个JLINK, 用STLINK等等....无语,都有一中怀疑芯片是假的了。最后重新对比两个芯片
发表于 2019-11-08
stm32f030cc 替换 stm32f030c8 后程序下载失败问题
STM32F030使用RTC周期性唤醒STOP模式
首先,F030与F072的RTC唤醒功能是不一样的,在相关定义文件stm32f0xx_exti.h中有如下定义:#define EXTI_Line17      ((uint32_t)0x00020000)  /*!< Internal interrupt line 17                                            
发表于 2019-11-08
STM32F030 使用引脚输入
GPIO_InitTypeDef GPIO_InitStructure;  /* Enable the BUTTON Clock */  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);   /* Configure Button pin as input */  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  GPIO_InitStructure.GPIO_Pin = GPI
发表于 2019-11-08
【stm32f407】窗口看门狗 wwdog
在文件stm32f4xx_wwdg.c文件和头文件stm32f4xx_wwdg.h中二.窗口看门狗应用1)使能WWDG时钟WWDG不同于IWDG,IWDG 有自己独立的32Khz时钟,不存在使能问题。而WWDG使用的是PCLK1的时钟,需要先使能时钟。方法是:RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); //WWDG时钟使能2)设置窗口值和分频数设置窗口值的函数是:voidWWDG_SetWindowValue(uint8_t WindowValue);这个函数就一个入口参数为窗口值,很容易理解。设置分频数的函数是:voidWWDG_SetPrescaler(uint32
发表于 2019-11-07
【stm32f407】窗口看门狗 wwdog
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved