OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3909|回复: 1

STM32F407 单路ADC+DMA定时器3TRGO触发转换

[复制链接]

3

主题

9

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2020-7-22
在线时间
9 小时
发表于 2022-1-30 11:03:44 | 显示全部楼层 |阅读模式
10金钱
【目的】:我想用 STM32F407内部ADC单路+定时器+DMA 采集100kHz的信号,读取一定数量的点并进行FFT分析。
【目前想的步骤】:1. 定时器3(定时器作用是控制采样频率)的TRGO触发ADC转换;2. ADC数据转换发出DMA请求;3. DMA搬移数据到存储区,搬移设定的数据量后开启DMA中断;4. DMA中断内部置标记位,读取数据,并关闭DMA(只采集一次)5. main中判断标记位并串口输出。
【异或】:
下面是我的代码
////////////////////////////////////////////////////////////////////////////////////////////////////////////////【adc.c】////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "adc.h"
#include "extern.h"

u16 ADC1_ConvertedValue[ ADC1_DMA_Size ];//目标寄存器,u16就是unsigned short int,u16这个数据大小与DMA_SxCR寄存器的MSIZE[1:0]位有关。

//ADC引脚配置
void ADC_GPIO_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE ); //使能AHB时钟
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//PA5引脚
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//输入模式
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//无上拉
        GPIO_Init(GPIOA, &GPIO_InitStructure );//初始化结构体
}


//TIM3初始化,作为ADC的采样触发源
void TIM3_Config( void )
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
       
        //TIM3时间基准配置
        RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3 , ENABLE );                           //使能时钟
        TIM_TimeBaseStructure.TIM_Period = 5-1 ;//自动重装载计数次数
        TIM_TimeBaseStructure.TIM_Prescaler = 84-1-1;//分频系数
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频因子
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
        TIM_TimeBaseInit( TIM3 , &TIM_TimeBaseStructure );
       
        TIM_SelectOutputTrigger( TIM3 , TIM_TRGOSource_Update );//选择TIM3的UPDATA事件更新为触发源
        TIM_ARRPreloadConfig( TIM3 , ENABLE );//允许TIM3定时重载
        TIM_Cmd( TIM3 , ENABLE );//使能TIM3
}


//ADC-DMA触发使能
//Size:单次传输的数据量
void ADC_DMA_Trig( u16 Size )                    
{
        DMA2_Stream0->CR &= ~((uint32_t)DMA_SxCR_EN); //DMA流失能
        while (DMA_GetCmdStatus(DMA2_Stream0) != DISABLE){}//等待DMA可配置
        DMA2_Stream0->NDTR = Size;//设置数量
        DMA_ClearITPendingBit( DMA2_Stream0 ,DMA_IT_TCIF0| DMA_IT_FEIF0|DMA_IT_DMEIF0|DMA_IT_TEIF0|DMA_IT_HTIF0);//清除DMA2的中断标记位
        ADC1->SR &= (uint32_t)(0x1F); //ADC所有状态清零
        DMA2_Stream0->CR |= (uint32_t)DMA_SxCR_EN; //DMA流使能
}


//ADC与DMA关联性配置
//注:2000K采样频率,采集6000个数据,需要花费3ms
void ADC_Config(void)
{
        ADC_InitTypeDef       ADC_InitStructure;
        ADC_CommonInitTypeDef ADC_CommonInitStructure;
        DMA_InitTypeDef       DMA_InitStructure;
        NVIC_InitTypeDef             NVIC_InitStructure;

        RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1 , ENABLE );//使能ADC1时钟
        ADC_DeInit( );//ADC复位
       
        /* Enable the DMA Stream IRQ Channel */
        NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

        /* DMA2 Stream0 channel0 configuration*/
       
        RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_DMA2 , ENABLE );//使能DMA2时钟
        DMA_DeInit( DMA2_Stream0 );//DMA复位,默认外设是流控制器
  while (DMA_GetCmdStatus(DMA2_Stream0) != DISABLE){}//等待DMA可配置
       
        DMA_InitStructure.DMA_Channel = DMA_Channel_0;//通道0
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;//外设地址
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ADC1_ConvertedValue;//寄存器地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//模式配置:外设->寄存器
        DMA_InitStructure.DMA_BufferSize = ADC1_DMA_Size;//DMA 传输数量
        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_InitStructure.DMA_Priority = DMA_Priority_High;
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;//FIFO关闭
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//寄存器单次传输
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设单次传输
        DMA_Init( DMA2_Stream0 , &DMA_InitStructure );//选择DMA2 流0
       
        DMA_ClearITPendingBit( DMA2_Stream0 ,DMA_IT_TCIF0| DMA_IT_FEIF0|DMA_IT_DMEIF0|DMA_IT_TEIF0|DMA_IT_HTIF0);//清除DMA2的中断标记位
        DMA_ITConfig( DMA2_Stream0 , DMA_IT_TC , ENABLE );//使能DMA2传输完成中断

        /* ADC Common Init */
        ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
        ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;//4分频,84M(APB2)/4=21M,ADC 时钟最好不要超过36Mhz
        ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;//DMA模式禁止(对多ADC模式),【ADC_CCR_DMA=0】
        ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//两个采样周期间间隔5个周期
        ADC_CommonInit( &ADC_CommonInitStructure );

        /* ADC1 Init */
        ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;//关闭扫描模式
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换
        ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;//外部上升沿
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;//TIM3作为ADC的触发源
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
        ADC_InitStructure.ADC_NbrOfConversion = 1;//规则通道序列长度,这里只有一个通道
        ADC_Init( ADC1, &ADC_InitStructure );
                       
        ADC_RegularChannelConfig( ADC1 , ADC_Channel_5 , 1 , ADC_SampleTime_3Cycles);//采样周期3
        ADC_DMARequestAfterLastTransferCmd( ADC1 , ENABLE );//1:只要发生数据转换且DMA = 1,便会发出DAM请求【ADC_CR2_DDS=1】
        ADC_DMACmd(ADC1, ENABLE);//ADC开启DMA功能,【CR2_DMA=1】
        ADC_Cmd(ADC1, ENABLE);//开启ADC,【ADC_CR2_ADON=1】
        ADC_SoftwareStartConv(ADC1);//ADC开始转换,我们每次单次转换模式下转换时都需要向该位写1,【ADC_CR2_SWSTART=1】
}

//DMA中断服务程序
void DMA2_Stream0_IRQHandler( void )
{
           u16 i=0;
     if(DMA_GetITStatus(DMA2_Stream0,DMA_IT_TCIF0))
                 {
                     DMA_ClearITPendingBit(DMA2_Stream0,DMA_IT_TCIF0);//清除中断标记位
                                 DMA_Cmd( DMA2_Stream0 , DISABLE );//关闭DMA2,,
                                 end=1;
                                 for(i=0;i<ADC1_DMA_Size;i++)
                                                Samp_Data=ADC1_ConvertedValue;
                 }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////【main.c】///////////////////////////

int main(void)
{
        u16 i;
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
        delay_init(168);    //初始化延时函数
        uart_init(115200);        //初始化串口波特率为115200
       
        AD9834_Init();  //初始化AD9834
        AD9834_Select_Wave(Sine_Wave);
        AD9834_Set_Freq(FREQ_1,1000); //20kHz
       
        ADC_GPIO_Init();                                // ADC引脚初始化。
        TIM3_Config( SAM_FRE );        // 触发ADC采样频率,采样频率
        ADC_Config();                                                // ADC
        ADC_DMA_Trig( ADC1_DMA_Size );          // 开始AD采集,设置采样点数

        while(1)
        {
                if(end==1)
                {
                  printf("\r\n------------converned-------------\r\nInter_Count=%d\r\n",Inter_Count);
                        for(i=0;i<ADC1_DMA_Size;i++)
                        {
                                printf("%f\r\n",Samp_Data*(3.3/4096));
                        }
                        end=0;
          }
        }
}

【下面这个是我采集的数据】

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

9

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2020-7-22
在线时间
9 小时
 楼主| 发表于 2022-1-30 11:20:20 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 02:56

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表