硬汉嵌入式论坛

 找回密码
 立即注册
查看: 476|回复: 5
收起左侧

使用STM32F429 ADC外部定时器T2触发采样问题

[复制链接]

9

主题

39

回帖

66

积分

初级会员

积分
66
发表于 2024-1-9 16:47:19 | 显示全部楼层 |阅读模式
各位大神好,我最近用STM32F429的标准库进行开发,用到ADC进行外部触发采样问题,发现外部触发只能进行转换一次,并不能随着TIMER进行触发。

下面贴上我的配置代码,各位帮忙看看,非常感谢


static void ADC2_DMA_Config(void)
{
  DMA_InitTypeDef DMA_InitStructure;
  ADC_InitTypeDef ADC_InitStructure;
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
  
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC2_DR_ADDR;
  DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ADC2_ConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//数据传输方向,外设到存储器
  DMA_InitStructure.DMA_BufferSize = ADC2_DMA_BUFFER_SIZE;//缓冲区大小,一次传输的数据
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设寄存器地址不变
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据大小,半字
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//存储器大小也为半字
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环传输模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA优先级设置底
  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_InitStructure.DMA_Channel = DMA_Channel_1;//选择DMA通道,通道存在于流中
  DMA_Init(DMA2_Stream2, &DMA_InitStructure);//流相当于一个大的管道,管道里面有很多通道
  DMA_Cmd(DMA2_Stream2, ENABLE);
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2 , ENABLE);
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立的ADC模式
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//时钟4分频
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;//禁止DMA直接访问
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//采样时间间隔
  ADC_CommonInit(&ADC_CommonInitStructure);
  
  ADC_StructInit(&ADC_InitStructure);
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12bit分辨率
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;//通道扫描模式
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//连续转换模式
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConv_T2_TRGO;//外部触发
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_Rising;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
  ADC_InitStructure.ADC_NbrOfConversion = ADC2_CHANNEL_NUM; //转换数据通道数                                   
  ADC_Init(ADC2, &ADC_InitStructure);
  
        ADC_RegularChannelConfig(ADC2,M4_VOL_SIN_ADC_CHANNEL,1,ADC_SampleTime_3Cycles);//负载电压输出波形
        ADC_RegularChannelConfig(ADC2,M4_CUR_SIN_ADC_CHANNEL,2,ADC_SampleTime_3Cycles);//负载电流输出波形
       
  ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE);
        ADC_DiscModeCmd(ADC2, DISABLE);
  ADC_DMACmd(ADC2, ENABLE);
  ADC_Cmd(ADC2, ENABLE);
}


static void ADC2_Timer2_TriggOutConfig(void)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
        GPIO_InitTypeDef   GPIO_InitStructure;
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_AHB1Periph_GPIOG,ENABLE);
       
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//用来定时器周期测试用PG0----->S1
  GPIO_Init(GPIOG, &GPIO_InitStructure);
  
  TIM_TimeBaseInitStructure.TIM_Period = 300-1; //自动重装载值,300KHz
  TIM_TimeBaseInitStructure.TIM_Prescaler = 0//定时器分频,时钟频率位90MHZ
  TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
  TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
  TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);// ②初始化定时器 TIM2
  
  TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //③允许定时器 2 更新中断
  
  NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; //定时器 2 中断
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x03; //抢占优先级 3
  NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x04; //响应优先级 3
  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  NVIC_Init(&NVIC_InitStructure);// ④初始化 NVIC
  TIM_Cmd(TIM2,ENABLE); //⑤使能定时器 2
}

回复

使用道具 举报

0

主题

124

回帖

124

积分

初级会员

积分
124
发表于 2024-1-9 19:04:05 | 显示全部楼层
DMA_InitStructure 里应有个DataLength 没赋值
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106847
QQ
发表于 2024-1-10 08:59:05 | 显示全部楼层

回帖奖励 +5 个金币

Edmund1964 发表于 2024-1-9 19:04
DMA_InitStructure 里应有个DataLength 没赋值

标准库的是DMA_BufferSize = ADC2_DMA_BUFFER_SIZE

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106847
QQ
发表于 2024-1-10 09:05:52 | 显示全部楼层
1、定时器中断不用开,这个中断频率超级高。你的CPU吃不消的。
2、供参考

[C] 纯文本查看 复制代码
/*
*********************************************************************************************************
*
*        模块名称 : ADC驱动模块
*        文件名称 : bsp_adc.c
*        版    本 : V1.2
*        说    明 : 实现ADC1和ADC3的双通道示波器,ADC2用于简单的电压采集
*        修改记录 :
*                版本号    日期        作者       说明
*                V1.0    2015-01-05   Eric2013   正式发布
*                V1.1    2015-12-29   Eric2013   修改函数TIM1_Config中TIM1的初始化。
*                V1.2    2018-01-06   Eric2013   修改之前的代码用于二代双通道示波器。
*
*        Copyright (C), 2018-2028, 安富莱电子 [url=http://www.armfly.com]www.armfly.com[/url]
*
*********************************************************************************************************
*/
#include "bsp.h"
#include "MainTask.h"



/*
*********************************************************************************************************
*                                         ADC寄存器
*********************************************************************************************************
*/
#define ADC_CDR_ADDRESS    ((uint32_t)0x40012308)
#define ADC3_DR_ADDRESS    ((uint32_t)0x4001224C)
#define ADC1_DR_ADDRESS    ((uint32_t)0x4001204C)
#define ADC2_DR_ADDRESS    ((uint32_t)0x4001214C)

/*
*********************************************************************************************************
*                                   ADC1,ADC3的数据缓存,大小均为10240
*********************************************************************************************************
*/
uint16_t ADC1ConvertedValue[10240];
uint16_t ADC3ConvertedValue[10240];

/*
*********************************************************************************************************
*                                           变量和函数                           
*********************************************************************************************************
*/
static uint16_t g_usFirstTimeIRQFlag;  /* 第一次进入定时器8的中断标志 */
static uint16_t g_usTrigCount = 0;     /* 记录普通触发进入看门狗中断时,DMA传输的位置 */
static uint16_t g_usTrigTempFlag = 0;  /* 临时变量,用于ADC中断 */
static void Time8Recorder(void);

/*
*********************************************************************************************************
*        函 数 名: TIM1_Config
*        功能说明: 配置定时器1,用于触发ADC1和ADC3。
*             当外部触发信号被选为ADC规则或注入转换时,只有它的上升沿可以启动转换。
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
static void TIM1_Config(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    
        /* 使能定时器1 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);        
    
        /* 先禁能再配置 */
    TIM_Cmd(TIM1, DISABLE);        
        
    /*
     ********************************************************************************
    system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:

    HCLK = SYSCLK / 1     (AHB1Periph)
    PCLK2 = HCLK / 2      (APB2Periph)
    PCLK1 = HCLK / 4      (APB1Periph)

    因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;
    因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;

    APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14
    APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
          
    TIM1 更新周期是 = TIM1CLK / (TIM_Period + 1)/(TIM_Prescaler + 1)
    ********************************************************************************
    */
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);                                            //初始化定时器1的寄存器为复位值
    TIM_TimeBaseStructure.TIM_Period =  168000000/g_SampleFreqTable[TimeBaseId][0] - 1;    //ARR自动重装载寄存器周期的值(定时时间)到设置频率后产生个更新或者中断(也是说定时时间到)
    TIM_TimeBaseStructure.TIM_Prescaler = g_SampleFreqTable[TimeBaseId][1]-1;                      //PSC时钟预分频数 例如:时钟频率=TIM1CLK/(时钟预分频+1)
    TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;                        //CR1->CKD时间分割值
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;     //CR1->CMS[1:0]和DIR定时器模式 向上计数
        TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000;                    /* TIM1 和 TIM8 必须设置 */        
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

    /**************ADC1的触发***********************************************/
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                                    //CCMR2在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;      //CCER 输出使能          
    TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period/2;//CCR3同计数器TIMx_CNT的比较,并在OC1端口上产生输出信号 
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;               //CCER输出极性设置
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;           /* only for TIM1 and TIM8. 此处和正相引脚不同 */        
        TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;                   /* only for TIM1 and TIM8. */                 
        TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;           /* only for TIM1 and TIM8. */
        TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;           /* only for TIM1 and TIM8. */        
        TIM_OC1Init(TIM1, &TIM_OCInitStructure);
        
        /**************ADC3的触发***********************************************/
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                                   
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;     
    TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period-1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; 
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;           /* only for TIM1 and TIM8. 此处和正相引脚不同 */        
        TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;                   /* only for TIM1 and TIM8. */                 
        TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;           /* only for TIM1 and TIM8. */
        TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;           /* only for TIM1 and TIM8. */                
    TIM_OC3Init(TIM1, &TIM_OCInitStructure);
    //TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);                //CMR2 设置预装载使能  更新事件产生时写入有效
    //TIM_ARRPreloadConfig(TIM1, ENABLE);                                            //CR1  设置ARR自动重装 更新事件产生时写入有效
    TIM_Cmd(TIM1, ENABLE);        
        
    /* 使能PWM输出 */        
    TIM_CtrlPWMOutputs(TIM1, ENABLE);                  
}

/*
*********************************************************************************************************
*        函 数 名: bsp_InitADC
*        功能说明: ADC初始化
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitADC(void)
{  
        ADC_InitTypeDef       ADC_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    DMA_InitTypeDef       DMA_InitStructure;
    GPIO_InitTypeDef      GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        
    /* 配置模拟看门狗中断NVIC */
    NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
        
    /* 使能 ADC1, ADC2, DMA2 和 GPIO 时钟 ****************************************/
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE);
        
        /* DMA2 Stream1 channel1 配置用于ADC3 **************************************/
        //DMA_DeInit(DMA2_Stream1); 
    DMA_InitStructure.DMA_Channel = DMA_Channel_2;  
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
        DMA_InitStructure.DMA_BufferSize = 1024*10;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
        DMA_Init(DMA2_Stream1, &DMA_InitStructure);
    DMA_Cmd(DMA2_Stream1, ENABLE);
        
        /* DMA2 Stream0 channel0 配置用于ADC1 **************************************/
        //DMA_DeInit(DMA2_Stream0); 
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;  
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
        DMA_InitStructure.DMA_BufferSize = 1024*10;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
        DMA_Init(DMA2_Stream0, &DMA_InitStructure);
    DMA_Cmd(DMA2_Stream0, ENABLE);

    /* 配置ADC引脚为模拟输入模式******************************/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
        
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
                
    /*
        ***************************************************************************   
          PCLK2 = HCLK / 2 
          下面选择的是2分频
          ADCCLK = PCLK2 /2 = HCLK / 4 = 168 / 4 = 42M
      ADC采样频率: Sampling Time + Conversion Time = 3 + 12 cycles = 15cyc
                    Conversion Time = 42MHz / 15cyc = 2.8Mbps.
        ****************************************************************************
        */
    
    /* ADC公共部分初始化**********************************************************/
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_8Cycles;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
    ADC_CommonInit(&ADC_CommonInitStructure); 
        
        /////////////////////////////////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////////////////////////////////

         /*ADC3的配置*****************************************************************/
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
        ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC3;
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
        ADC_InitStructure.ADC_NbrOfConversion = 1;
    
    /* ADC3 规则通道配置 */
        ADC_Init(ADC3, &ADC_InitStructure);
        ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);

    /* 使能 ADC3 DMA */
        ADC_DMACmd(ADC3, ENABLE);
        
        /* 配置模拟看门狗的阀值 注意别配置反了,要不一直进入中断 */
    ADC_AnalogWatchdogThresholdsConfig(ADC3, 4095, 0);
    
    /* 配置模拟看门狗监测ADC3的通道10 */
    ADC_AnalogWatchdogSingleChannelConfig(ADC3, ADC_Channel_10);
    
    /* 使能一个规则通道的看门狗 */
    ADC_AnalogWatchdogCmd(ADC3, ADC_AnalogWatchdog_SingleRegEnable);

    /* 使能模拟看门狗中断 */
    ADC_ITConfig(ADC3, ADC_IT_AWD, ENABLE);
    
        /* 使能DMA请求 (多ADC模式) --------------------------------------------------*/
        ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

        /* 使能 ADC3 --------------------------------------------------------------*/
        ADC_Cmd(ADC3, ENABLE);
        
        /////////////////////////////////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////////////////////////////////
        
        /*ADC1的配置******************************************************************/
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
        ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
        ADC_InitStructure.ADC_NbrOfConversion = 1;
    
    /* ADC1 规则通道配置 -------------------------------------------------------*/
        ADC_Init(ADC1, &ADC_InitStructure);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 1, ADC_SampleTime_3Cycles);

    /* 使能 ADC1 DMA */
        ADC_DMACmd(ADC1, ENABLE);
        
        /* 使能DMA请求 (多ADC模式) --------------------------------------------------*/
        ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);

        /* 使能 ADC1 --------------------------------------------------------------*/
        ADC_Cmd(ADC1, ENABLE);
        
        /////////////////////////////////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////////////////////////////////

    /*ADC2的配置*****************************************************************/
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
        ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC2;
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
        ADC_InitStructure.ADC_NbrOfConversion = 1;
    
    /* ADC2 规则通道配置 */
        ADC_Init(ADC2, &ADC_InitStructure);
        ADC_RegularChannelConfig(ADC2, ADC_Channel_10, 1, ADC_SampleTime_480Cycles);

        /* 使能 ADC2 */
        ADC_Cmd(ADC2, ENABLE);
        
        /**定时器配置********************************************************************/
        TIM1_Config();
}

/*
*********************************************************************************************************
*        函 数 名: DMA_Open
*        功能说明: 使能ADC1,ADC2,ADC3的DMA
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void ADC_DMA_Open(void)
{
    DMA_InitTypeDef       DMA_InitStructure;

        /* DMA2 Stream1 channel1 配置用于ADC3 **************************************/
    DMA_DeInit(DMA2_Stream1);  /* 在DMA的DMA_Mode_Normal模式,一定要使用这个函数,循环模式可以不用 */
        DMA_InitStructure.DMA_Channel = DMA_Channel_2;  
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
        DMA_InitStructure.DMA_BufferSize = 1024*10;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
        DMA_Init(DMA2_Stream1, &DMA_InitStructure);
    DMA_Cmd(DMA2_Stream1, ENABLE);
        
        /* DMA2 Stream0 channel0 配置用于ADC1 **************************************/
    DMA_DeInit(DMA2_Stream0);
        DMA_InitStructure.DMA_Channel = DMA_Channel_0;  
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
        DMA_InitStructure.DMA_BufferSize = 1024*10;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
        DMA_Init(DMA2_Stream0, &DMA_InitStructure);
    DMA_Cmd(DMA2_Stream0, ENABLE);

        ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);

        /* 使能 ADC3 --------------------------------------------------------------*/
        ADC_Cmd(ADC3, ENABLE);
        
        ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 1, ADC_SampleTime_3Cycles);

        /* 使能 ADC1 --------------------------------------------------------------*/
        ADC_Cmd(ADC1, ENABLE);

        /**定时器配置,一定要重新的初始化从而保证同时触发 **/
        TIM1_Config();

        /* 只有在普通触发模式在启动TIM8的计时功能 */
        if(TriggerFlag != 0)
        {
                Time8Recorder();
        }
}

/*
*********************************************************************************************************
*        函 数 名: DMA_Close
*        功能说明: 关闭ADC1,ADC2,ADC3及其DMA
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void ADC_DMA_Close()
{
        TIM_Cmd(TIM1, DISABLE);
        
        DMA_Cmd(DMA2_Stream1, DISABLE);
        
        DMA_Cmd(DMA2_Stream0, DISABLE);
        
        /* 禁止 ADC1 ---------------------------------------------------------------------*/
        ADC_Cmd(ADC1, DISABLE);
        
        /* 禁止 ADC3 ---------------------------------------------------------------------*/
        ADC_Cmd(ADC3, DISABLE);
}

/*
*********************************************************************************************************
*        函 数 名: ADC_IRQHandler
*        功能说明: 模拟看门狗中断服务程序。
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void ADC_IRQHandler()
{ 
        /* 读取DMA剩余要传输的数目 */
        g_usTrigCount = DMA2_Stream1->NDTR;

        /* 确认是否是ADC3的看门狗中断 */
        if((ADC3->SR)&0x01)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
    {
                /* 取触发值的前一个点,查看是否是在阀值范围内,从而判断是上升沿还是下降沿 */
                if(g_usTrigCount == 10240)
                {
                        /* 剩余10240表示触发值是ADC3ConvertedValue[10239]是触发值,那么上一个点就是10238 */
                        g_usTrigTempFlag = ADC3ConvertedValue[10238]; 
                }
                else if(g_usTrigCount == 10239)
                {
                        /* 剩余10239表示触发值是ADC3ConvertedValue[0]是触发值,那么上一个点就是10239 */
                        g_usTrigTempFlag = ADC3ConvertedValue[10239]; 
                }
                else
                {
                        /* 剩余10239表示触发值是ADC3ConvertedValue[0]是触发值,那么上一个点就是10239 */
                        g_usTrigTempFlag = ADC3ConvertedValue[10238 - g_usTrigCount]; 
                }
                
                /* 判断是否是上升沿,是的话开启定时器记录ADC数据 */
                if(g_usTrigTempFlag <= g_TrigVol->usTrigValue)
                {
                        /* 关闭ADC3的看门狗中断 */
                        ADC3->CR1 &= 0xffffffbf;
                        TriggerFlag = 1;
                        
                        /* 启动定时器计数 */
                        TIM8->CR1 |= 0x01;
                }
        /* 清除挂起标志 */
                ADC3->SR &= 0xfe;
    }
}

/*
*********************************************************************************************************
*        函 数 名: TIM8_MeasureTrigConfig
*        功能说明: 使用TIM8为普通触发模式下数据采集计时,定时采集触发值前后的1024个ADC数据
*        形    参:无
*        返 回 值: 无                        
*********************************************************************************************************
*/
/* 
        每次捕获采集触发值前后的1024个ADC数据(单通道)。
*/
const uint32_t g_TrigFreqTable[][2] =
{
        {60,   1024},    //2.8Msps  168000000/2800000 = 60  => 60 * 1024 
        {84,   1024},    //2Msps    168000000/2000000 = 84  => 84 * 1024 
        {168,  1024},    //1Msps    168000000/1000000 = 168 => 168 * 1024
        {336,  1024},    //500Ksps  168000000/500000  = 336 => 336 * 1024
        {840,  1024},    //200Ksps  168000000/200000  = 840 => 840 * 1024
        
        {1680,  1024},   //100Ksps 168000000/100000  = 1680  => 1680 * 1024
        {3360,  1024},   //50Ksps  168000000/50000   = 3360  => 3360 * 1024 
        {8400,  1024},   //20Ksps  168000000/20000   = 8400  => 8400 * 1024
        {16800, 1024},   //10Ksps  168000000/10000   = 16800 => 16800 * 1024 
        {33600, 1024},   //5Ksps   168000000/5000    = 33600 => 33600 * 1024 

        /* 下面5种采样频率下刷新较慢,因为采集前后1024个ADC的时间较长 */
        {42000,    2048},    //2Ksps 168000000/2000  = 84000 => 84000 * 1024
        {42000,    4096},    //1Ksps 168000000/1000  = 168000 => 168000 * 1024 
        {42000,    8192},    //500sps 168000000/500  = 336000 => 336000 * 1024 
        {42000,    20480},   //200sps 168000000/200  = 840000 => 840000 * 1024 
        {42000,    40960},   //100sps 168000000/100  = 1680000 => 1680000 * 1024
        
        /* 下面这几种采样率不做触发支持 */
        {42000,    40960},   //50sps 
        {42000,    40960},   //20sps
        {42000,    40960},   //10sps 
        {42000,    40960},   //5sps 
        {42000,    40960},   //2sps 
        {42000,    40960},   //1sps         
};

void TIM8_MeasureTrigConfig(void)
{
        TIM_TimeBaseInitTypeDef TIM_BaseInitStructure; 
        NVIC_InitTypeDef NVIC_InitStructure;
        
        /* 开启时钟 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
        
        /* 加上第一次进入中断的标志,进入中断后将其置1 */
        g_usFirstTimeIRQFlag = 0;

        /* 使能定时器8中断  */
        NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_TIM13_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

        /* 定时器配置 */
        TimeBaseId = 1;        /* 开机后按照ADC单通道1Msps进行配置 */
        TIM_DeInit(TIM8);  
        TIM_BaseInitStructure.TIM_Period = g_TrigFreqTable[TimeBaseId][0] - 1;
        TIM_BaseInitStructure.TIM_Prescaler = g_TrigFreqTable[TimeBaseId][1] - 1;
        TIM_BaseInitStructure.TIM_ClockDivision = 0;
        TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM8, &TIM_BaseInitStructure); 
        TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE);
        TIM_Cmd(TIM8, DISABLE);
}

/*
*********************************************************************************************************
*        函 数 名: Time8Recorder
*        功能说明: 使用TIM8为普通触发模式下数据采集计时,定时采集触发值前后的1024个ADC数据
*        形    参:无
*        返 回 值: 无                        
*********************************************************************************************************
*/
static void Time8Recorder(void)
{
        TIM_TimeBaseInitTypeDef TIM_BaseInitStructure; 
        
        /* 加上第一次进入中断的标志 */
        g_usFirstTimeIRQFlag = 0;
        
        TIM_DeInit(TIM8);  
        TIM_BaseInitStructure.TIM_Period = g_TrigFreqTable[TimeBaseId][0] - 1;
        TIM_BaseInitStructure.TIM_Prescaler = g_TrigFreqTable[TimeBaseId][1] - 1;
        TIM_BaseInitStructure.TIM_ClockDivision = 0;
        TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM8, &TIM_BaseInitStructure); 
        TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE);
        TIM_Cmd(TIM8, DISABLE);
}

/*
*********************************************************************************************************
*        函 数 名: TIM8_UP_TIM13_IRQHandler
*        功能说明: 定时器中断函数
*        形    参: 无
*        返 回 值: 无                        
*********************************************************************************************************
*/
void TIM8_UP_TIM13_IRQHandler(void)
{
        uint16_t i, k, usCurPos;
        
        /* 第一次进入TIM8中断执行退出操作,因为定时器更新中断有个小bug,
           一旦初始化了定时器并且使能中断就会有立即进入一次中断的情况,为了防止这种情况的
           出现,作如下操作:
        */
        if(g_usFirstTimeIRQFlag == 0)
        {
                g_usFirstTimeIRQFlag = 1;
                
                TIM_ClearITPendingBit(TIM8, TIM_IT_Update);
                
                /* 如果是第一次进入就退出 */
                return;
        }
        
        /* 定时器时间中断 */
        if (TIM_GetITStatus(TIM8, TIM_IT_Update) != RESET)
        {
                /* 先关闭定时器 */
                TIM_Cmd(TIM8, DISABLE);
        
                /* 确保开启的定时器计时采集ADC数据 */
                if(TriggerFlag == 1)
                {
                        /* 定时器采集ADC数据结束 */
                        TriggerFlag = 2;
                        
                        /* 开启定时器计数前DMA传输数据的位置 */
                        usCurPos = 10240 - g_usTrigCount;
                        
                        /*
                                下面分为三种情况获取6K的数据(三通道,单通道就是前后1024个ADC数据):
                             1. 当前的位置 < 1024.
                             2. 1024 <= 当前的位置 <= 10240 - 1024(9216)
                                 3. 当前位置 > 10240 - 1024(9216)
                        */
                        /* 第一种情况:当前的位置 < 1024. */
                        if(usCurPos < 1024)
                        {
                                k = 1024 - usCurPos;
                                usCurPos = 10240 - k;
                                
                                /* 前部分数据 */
                                for(i = 0; i < k; i++)
                                {
                                        g_DSO1->usWaveBufTemp[i] = ADC3ConvertedValue[i+usCurPos];
                                }
                                
                                usCurPos = i;
                                k = 10240 - g_usTrigCount + 1024;
                                
                                /* 后部分数据 */
                                for(i = 0; i < k; i++)
                                {
                                        g_DSO1->usWaveBufTemp[i + usCurPos] = ADC3ConvertedValue[i];
                                }
                        }
                        /* 第三种情况:当前位置 > 10240 - 1024(9216) */
                        else if(usCurPos > 9216)
                        {
                                usCurPos = usCurPos - 1024;
                                
                                /* 采集前1024+g_usTrigCount的数据 */
                                for(i = 0; i < (g_usTrigCount + 1024); i++)
                                {
                                        g_DSO1->usWaveBufTemp[i] = ADC3ConvertedValue[i+usCurPos];
                                }
                                
                                k = i;
                                usCurPos = (1024 - g_usTrigCount);
                                
                                /* 剩余数据的采集 */
                                for(i = 0; i < usCurPos; i++)
                                {
                                        g_DSO1->usWaveBufTemp[i + k] = ADC3ConvertedValue[i]; 
                                }
                        }
                        /* 第二种情况:1024 <= 当前的位置 <= 10240 - 1024(9216)  */
                        else
                        {
                                usCurPos = usCurPos - 1024;
                                for(i = 0; i < 2048; i++)
                                {
                                        g_DSO1->usWaveBufTemp[i] = ADC3ConvertedValue[i+usCurPos];
                                }
                        }
                        
                }
        
                TIM_ClearITPendingBit(TIM8, TIM_IT_Update);
        }
}

/***************************** 安富莱电子 [url=http://www.armfly.com]www.armfly.com[/url] (END OF FILE) *********************************/
回复

使用道具 举报

9

主题

39

回帖

66

积分

初级会员

积分
66
 楼主| 发表于 2024-1-10 11:13:59 | 显示全部楼层
eric2013 发表于 2024-1-10 09:05
1、定时器中断不用开,这个中断频率超级高。你的CPU吃不消的。
2、供参考

好的,谢谢硬汉哥。
回复

使用道具 举报

9

主题

39

回帖

66

积分

初级会员

积分
66
 楼主| 发表于 2024-1-12 15:39:27 | 显示全部楼层
eric2013 发表于 2024-1-10 09:05
1、定时器中断不用开,这个中断频率超级高。你的CPU吃不消的。
2、供参考

经过测试我的adc之所以不能实现循环采样,是因为缺少了一句TIM_SelectOutputTrigger。因为我选择的触发源是TRGO,感谢硬汉哥的回复,非常感谢
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-7 13:41 , Processed in 0.503585 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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