打印
[其他ST产品]

TIM + ADC +DMA 搬运设置求助

[复制链接]
2036|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
GZZXB|  楼主 | 2019-12-31 13:39 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
ADC, DMA, TI, ST, PWM
      芯片是用G030,用TIM3 触发ADC采集,DMA搬运数据到buf。cubeMX中配置了adc和dma中断。
  调试现象: 仿真观察 TIM3可以正常计数并触发ADC进入中断。是否可以说明TIM触发ADC采集这个通路是OK了?
                   buf数据一直没有得到更新始终为0,说明DMA并没有搬运数据。

以下是工程配置:
     


       然后在main函数里
        MX_GPIO_Init();
        MX_ADC1_Init();
        MX_TIM1_Init();
        MX_TIM3_Init();
        MX_TIM17_Init();
        MX_DMA_Init();
        MX_TIM16_Init();
        MX_TIM14_Init();
  /* USER CODE BEGIN 2 */

        HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&AdcBuf, ADC_BUF_SIZE);  //开ADC和DMA等待tim3触发.

        HAL_TIM_Base_Start(&htim1);  
        HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_2);  //开启pwm CH2输出
        HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3);  //开启pwm CH3输出
               //TIM_CCxNChannelCmd(&htim17,TIM_CHANNEL_1,TIM_CCxN_ENABLE);  //
        HAL_TIM_Base_Start(&htim17);  
        HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);  //开启pwm CH1输出
        HAL_TIMEx_PWMN_Start(&htim17,TIM_CHANNEL_1);//开启pwm CH1N输出
        htim17.Instance->BDTR &= 0xffffff00;
        htim17.Instance->BDTR |= 10;

        //打开定时器
        HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);  //开启pwm输出
        HAL_TIM_Base_Start_IT(&htim3);            //打开中断

使用特权

评论回复
沙发
yklstudent| | 2020-1-1 11:22 | 只看该作者
本帖最后由 yklstudent 于 2020-1-1 11:33 编辑

用LL库吧,HAL库一直不习惯用
#include "driver_adc.h"

//ADC1+DMA读取缓存器
uint16_t g_ADC_ConvertedValue[cADC_MAX_CHANNELS];

void sADC_Configuration(void)
{
        LL_GPIO_InitTypeDef GPIO_InitStructure;
        LL_ADC_InitTypeDef ADC_InitStructure;
        LL_ADC_REG_InitTypeDef ADC_REG_InitStructure;
    LL_DMA_InitTypeDef DMA_InitStructure;
        LL_TIM_InitTypeDef TIM_TimeStructInit;
        LL_TIM_OC_InitTypeDef TIM_OC_InitStructInit;
       
        /* Enable ADC1 Clock */
    RCC->APBENR2 |= RCC_APBENR2_ADCEN;
        RCC->AHBENR |= RCC_AHBENR_DMA1EN;
       
        /* Enable GPIO Clock */
        RCC->IOPSMENR |= cADC1_CHANNEL00_CLK | cADC1_CHANNEL01_CLK | cADC1_CHANNEL02_CLK | cADC1_CHANNEL03_CLK /
                                        cADC1_CHANNEL04_CLK | cADC1_CHANNEL05_CLK | cADC1_CHANNEL06_CLK | cADC1_CHANNEL07_CLK;
       
        /*ADC12_Channel0*/
        GPIO_InitStructure.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStructure.Pin = cADC1_CHANNEL00_PIN;
        GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStructure.Pull = LL_GPIO_PULL_UP;
        LL_GPIO_Init(cADC1_CHANNEL00_PORT, &GPIO_InitStructure);
        /*ADC12_Channel1*/
        GPIO_InitStructure.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStructure.Pin = cADC1_CHANNEL01_PIN;
        GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStructure.Pull = LL_GPIO_PULL_UP;
        LL_GPIO_Init(cADC1_CHANNEL01_PORT, &GPIO_InitStructure);
        /*ADC12_Channel2*/
        GPIO_InitStructure.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStructure.Pin = cADC1_CHANNEL02_PIN;
        GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStructure.Pull = LL_GPIO_PULL_UP;
        LL_GPIO_Init(cADC1_CHANNEL02_PORT, &GPIO_InitStructure);
        /*ADC12_Channel3*/
        GPIO_InitStructure.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStructure.Pin = cADC1_CHANNEL03_PIN;
        GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStructure.Pull = LL_GPIO_PULL_UP;
        LL_GPIO_Init(cADC1_CHANNEL03_PORT, &GPIO_InitStructure);
        /*ADC12_Channel4*/
        GPIO_InitStructure.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStructure.Pin = cADC1_CHANNEL04_PIN;
        GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStructure.Pull = LL_GPIO_PULL_UP;
        LL_GPIO_Init(cADC1_CHANNEL04_PORT, &GPIO_InitStructure);
        /*ADC12_Channel5*/
        GPIO_InitStructure.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStructure.Pin = cADC1_CHANNEL05_PIN;
        GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStructure.Pull = LL_GPIO_PULL_UP;
        LL_GPIO_Init(cADC1_CHANNEL05_PORT, &GPIO_InitStructure);
        /*ADC12_Channel6*/
        GPIO_InitStructure.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStructure.Pin = cADC1_CHANNEL06_PIN;
        GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStructure.Pull = LL_GPIO_PULL_UP;
        LL_GPIO_Init(cADC1_CHANNEL06_PORT, &GPIO_InitStructure);
        /*ADC12_Channel7*/
        GPIO_InitStructure.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStructure.Pin = cADC1_CHANNEL07_PIN;
        GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStructure.Pull = LL_GPIO_PULL_UP;
        LL_GPIO_Init(cADC1_CHANNEL07_PORT, &GPIO_InitStructure);
       
        LL_DMA_DeInit(DMA1, LL_DMA_CHANNEL_1);
        DMA_InitStructure.PeriphOrM2MSrcAddress  = cADC1_DR_Address;
    DMA_InitStructure.MemoryOrM2MDstAddress  = (uint32_t)&g_ADC_ConvertedValue[0];
    DMA_InitStructure.Direction              = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
    DMA_InitStructure.NbData                 = (uint32_t)cADC_MAX_CHANNELS;
    DMA_InitStructure.PeriphOrM2MSrcIncMode  = LL_DMA_PERIPH_NOINCREMENT;
    DMA_InitStructure.MemoryOrM2MDstIncMode  = LL_DMA_MEMORY_INCREMENT;
    DMA_InitStructure.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD;
    DMA_InitStructure.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD;
    DMA_InitStructure.Mode                   = LL_DMA_MODE_CIRCULAR;
        DMA_InitStructure.PeriphRequest                         = LL_DMAMUX_REQ_ADC1;
    DMA_InitStructure.Priority               = LL_DMA_PRIORITY_HIGH;
    LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &DMA_InitStructure);

    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
       
        /* Set ADC group regular sequence: channel on the selected sequence rank. */
        if (LL_ADC_IsEnabled(ADC1) == 0)
        {
                ADC_InitStructure.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
                ADC_InitStructure.LowPowerMode = LL_ADC_LP_MODE_NONE;
                ADC_InitStructure.Clock = LL_ADC_CLOCK_SYNC_PCLK_DIV1;
                ADC_InitStructure.Resolution = LL_ADC_RESOLUTION_12B;
                LL_ADC_Init(ADC1, &ADC_InitStructure);
               
                ADC_REG_InitStructure.TriggerSource = LL_ADC_REG_TRIG_EXT_TIM3_TRGO;
                ADC_REG_InitStructure.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_8RANKS;
                ADC_REG_InitStructure.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
                ADC_REG_InitStructure.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS;
                ADC_REG_InitStructure.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;
                ADC_REG_InitStructure.Overrun = 0;
                LL_ADC_REG_Init(ADC1, &ADC_REG_InitStructure);
               
                /* Set ADC group regular sequencer length and scan direction */
                //LL_ADC_REG_SetSequencerLength(ADC1, LL_ADC_REG_SEQ_SCAN_ENABLE_8RANKS);
               
                LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_0);
                LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_1);
                LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_3, LL_ADC_CHANNEL_2);
                LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_4, LL_ADC_CHANNEL_3);
                LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_5, LL_ADC_CHANNEL_4);
                LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_6, LL_ADC_CHANNEL_5);
                LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_7, LL_ADC_CHANNEL_6);
                LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_8, LL_ADC_CHANNEL_7);
        }
       
        if (LL_ADC_IsEnabled(ADC1) == 0)
        {
                LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_0, LL_ADC_SAMPLINGTIME_COMMON_1);
                LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_COMMON_1);
                LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_2, LL_ADC_SAMPLINGTIME_COMMON_1);
                LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_3, LL_ADC_SAMPLINGTIME_COMMON_1);
                LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_4, LL_ADC_SAMPLINGTIME_COMMON_1);
                LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_5, LL_ADC_SAMPLINGTIME_COMMON_1);
                LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_6, LL_ADC_SAMPLINGTIME_COMMON_1);
                LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_7, LL_ADC_SAMPLINGTIME_COMMON_1);
        }
       
        /* Set ADC group regular conversion data transfer */
    LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);

#if (cADCISR==1)
        /* Enable JEOC interrupt */
        ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE);
#endif
#if (cADCDMAISR==1)
    /*Clear DMA1_FLAG_TC1*/
    LL_DMA_ClearFlag_TC1(DMA1);
    /*Enable DMA1_Channe1 Interrupt*/
        LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
#endif

        /* Enable ADC1 */
        LL_ADC_Enable(ADC1);
       
        /*ADC1 Calibration*/
        LL_ADC_StartCalibration(ADC1);
        while(LL_ADC_IsCalibrationOnGoing(ADC1));
       
        /*Start ADC1 Software Conversion*/
        LL_ADC_REG_StartConversion(ADC1);
       
        /* Enable TIM3 Clock */
        RCC->APBENR1 |= RCC_APBSMENR1_TIM3SMEN;
    LL_TIM_StructInit(&TIM_TimeStructInit);
    TIM_TimeStructInit.Autoreload = 50 - 1;                /*50us*/
        TIM_TimeStructInit.Prescaler = 72 - 1;           /*1us*/
    TIM_TimeStructInit.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
        TIM_TimeStructInit.CounterMode   = LL_TIM_COUNTERMODE_UP;
        TIM_TimeStructInit.RepetitionCounter = 0;
    LL_TIM_Init(TIM3, &TIM_TimeStructInit);

        LL_TIM_OC_StructInit(&TIM_OC_InitStructInit);
    TIM_OC_InitStructInit.OCMode = LL_TIM_OCMODE_PWM1;
        TIM_OC_InitStructInit.OCState = LL_TIM_OCSTATE_ENABLE;
    TIM_OC_InitStructInit.OCNState = LL_TIM_OCSTATE_ENABLE;
    TIM_OC_InitStructInit.CompareValue = 25;
    TIM_OC_InitStructInit.OCPolarity = LL_TIM_OCPOLARITY_LOW;
        TIM_OC_InitStructInit.OCNPolarity = LL_TIM_OCPOLARITY_LOW;
        TIM_OC_InitStructInit.OCIdleState = LL_TIM_OCIDLESTATE_LOW;
        TIM_OC_InitStructInit.OCNIdleState = LL_TIM_OCIDLESTATE_LOW;
    LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStructInit);

    LL_TIM_EnableCounter(TIM3);
       
        /* Enable the ADC1 gloabal Interrupt */
       
        /*Enable the USART Interrupt*/
        //NVIC_SetPriority(ADC1_2_IRQn, 2);
        //NVIC_EnableIRQ(ADC1_2_IRQn);
       
        /*Enable the USART DMA Interrupt*/
        NVIC_SetPriority(DMA1_Channel1_IRQn, 2);
        NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}

#if (cADCISR==1)
uint8_t Index = 0;
uint32_t ADC_InjectedConvertedValueTab[32];

void sADC1_2_ISR(void)
{
        /* Get injected channel11 converted value */
        ADC_InjectedConvertedValueTab[Index++] = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1);
        if(Index >= sizeof(ADC_InjectedConvertedValueTab)/sizeof(uint32_t))
        {
                Index = 0;
        }
        /* Clear ADC1 JEOC pending interrupt bit */
        ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC);
}
#endif

#if (cADCDMAISR==1)
/**
  * @brief  DMA transfer complete callback
  * @NOTE   This function is executed when the transfer complete interrupt
  *         is generated
  * @retval None
  */
void AdcDmaTransferComplete_Callback()
{
       
}

/**
  * @brief  DMA half transfer callback
  * @note   This function is executed when the half transfer interrupt
  *         is generated
  * @retval None
  */
void AdcDmaTransferHalf_Callback()
{
       
}

/**
  * @brief  DMA transfer error callback
  * @note   This function is executed when the transfer error interrupt
  *         is generated during DMA transfer
  * @retval None
  */
void AdcDmaTransferError_Callback()
{
        /* Error detected during DMA transfer */
}

void sDMA1_Channel1_ISR(void)
{
        /* Check whether DMA transfer complete caused the DMA interruption */
        if(LL_DMA_IsActiveFlag_TC1(DMA1) == 1)
        {
                /* Clear flag DMA transfer complete */
                LL_DMA_ClearFlag_TC1(DMA1);

                /* Call interruption treatment function */
                AdcDmaTransferComplete_Callback();
        }

        /* Check whether DMA half transfer caused the DMA interruption */
        if(LL_DMA_IsActiveFlag_HT1(DMA1) == 1)
        {
                /* Clear flag DMA half transfer */
                LL_DMA_ClearFlag_HT1(DMA1);

                /* Call interruption treatment function */
                AdcDmaTransferHalf_Callback();
        }

        /* Check whether DMA transfer error caused the DMA interruption */
        if(LL_DMA_IsActiveFlag_TE1(DMA1) == 1)
        {
                /* Clear flag DMA transfer error */
                LL_DMA_ClearFlag_TE1(DMA1);

                /* Call interruption treatment function */
                AdcDmaTransferError_Callback();
        }       
}
#endif

使用特权

评论回复
板凳
GZZXB|  楼主 | 2020-1-1 18:51 | 只看该作者
感谢楼上码这么多字回复。其实我对HAL和LL一点都不熟悉,切换到G系列的一个原因也是想试试Stm32cubeMX的应用。想着以后用cubeMX应该是趋势吧,所以主要目的还是想学习cubeMX配置代码

使用特权

评论回复
地板
cry1109| | 2020-1-3 15:42 | 只看该作者
没做过定时器触发的,做过ADC双通道+DMA软件触发。ADC_Settings配置下的Scan Conversion Mode和Continuous Conversion Mode需要Enable,Discontinuous Conversion Mode需要Disable。

464175e0eef65861a7.png (20.15 KB )

464175e0eef65861a7.png

使用特权

评论回复
5
香水城| | 2020-1-6 17:11 | 只看该作者
我这里用STM32G070做了个测试例程。你可以参考。用到ADC1的ch8/9/10, 基于HAL库,使用CubeMx进行配置。TIM15定时触发ADC的转换。




使用特权

评论回复
6
東南博士| | 2020-1-7 10:34 | 只看该作者
一直没有搞懂 F042 F030 串口IAP的应用。尤其是FLASH 的偏移 以及写法的改造。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

96

主题

331

帖子

10

粉丝