硬汉嵌入式论坛

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

[STM32H7] 定时器触发ADC+DMA半传输完成中断,采样率不对的问题请教

[复制链接]

8

主题

50

回帖

79

积分

初级会员

积分
79
发表于 2023-4-14 08:32:19 | 显示全部楼层 |阅读模式

大家好,请教大家一个问题:
参考V7开发板ADC的章节,修改为TIM2定时触发ADC采样,ADC一次转换4个通道,采用DMA半传输完成中断,定时器中断函数也用上了,用于定期向GUIX发数据显示。

设置的采样率是100Hz,就是每秒触发100次ADC转换,DMA缓冲大小是4*128*2=1024(uint16_t),就是4个通道,半传输完成中断时,应该采集了4*128个数据,传输完成中断时就是4*128*2个数据,那么理论上半传输完成和传输完成之间的时间间隔就是128*10ms=1280ms,但是我设置在半传输完成和传输完成中断里都翻转一次IO口,通过示波器看,两次翻转的时间间隔是2560ms,恰好是2倍。设置在定时器中断里翻转IO口,两次翻转的时间间隔又是10ms,也就是说定时时间没问题。所以是哪里没配置好了?

半传输完成和传输完成IO口翻转的时间间隔是2560ms
半传输完成.png

定时器中断IO口翻转的时间间隔是10ms
定时器.png

附件是代码。

bsp_adc.c

16.39 KB, 下载次数: 7

bsp_adc.h

1.16 KB, 下载次数: 1

回复

使用道具 举报

335

主题

2037

回帖

3047

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3047
发表于 2023-4-14 08:58:47 | 显示全部楼层
搞了好几年的设计了,还从来没有用过这个“半传输完成中断”,没想到需要使用它的场景啊。
回复

使用道具 举报

8

主题

50

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2023-4-14 09:04:14 | 显示全部楼层
caicaptain2 发表于 2023-4-14 08:58
搞了好几年的设计了,还从来没有用过这个“半传输完成中断”,没想到需要使用它的场景啊。

我是用作数据存储和处理的,就是乒乓操作,一次存储或处理一半的数据,防止还没处理完就被新数据覆盖了。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2023-4-14 14:28:41 | 显示全部楼层
我测试下试试
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2023-4-14 15:32:41 | 显示全部楼层
测试了个可用,4通道的,TIM1触发,双缓冲


下载 (14).png

代码:
[C] 纯文本查看 复制代码
/*
*********************************************************************************************************
*
*        模块名称 : ADC驱动
*        文件名称 : bsp_adc.c
*        版    本 : V1.0
*        说    明 : ADC定时器触发+DMA双缓冲的实现
*              1. 例子默认用的AHB时钟供ADC使用,大家可以通过bsp_adc.c文件开头宏定义切换到PLL2专用时钟。
*              2、使用的TIM1的OC1作为ADC的外部触发源,触发速度是100KHz,即ADC的采样率也是100KHz。
*              3、使用DMA的半传输完成中断和传输完成中断实现数据的双缓冲更新。
*              4、采集引脚使用的PC0,另外特别注意开发板上的Vref稳压基准跳线帽短接的3.3V。
*
*        修改记录 :
*                版本号  日期        作者     说明
*                V1.0    2018-12-12 armfly  正式发布
*
*        Copyright (C), 2018-2030, 安富莱电子 [url=http://www.armfly.com]www.armfly.com[/url]
*
*********************************************************************************************************
*/
#include "bsp.h"



/* 选择ADC的时钟源 */
#define ADC_CLOCK_SOURCE_AHB     /* 选择AHB时钟源 */
//#define ADC_CLOCK_SOURCE_PLL     /* 选择PLL时钟源 */


/* 方便Cache类的API操作,做32字节对齐 */
#if defined ( __ICCARM__ )
#pragma location = 0x38000000
uint16_t ADCxValues[128];
#elif defined ( __CC_ARM )
ALIGN_32BYTES(__attribute__((section (".RAM_D3"))) uint16_t ADCxValues[128*32]);
#endif

__IO uint8_t s_DmaFlag = 0;  /* 1表示进DMA半传输完成中断,2表示进入DMA传输完成中断 */
DMA_HandleTypeDef   DmaHandle = {0};        

/*
*********************************************************************************************************
*        函 数 名: TIM1_Config
*        功能说明: 配置TIM1,用于触发ADC,当前配置的100KHz触发频率
*        形    参: 无                                                                          
*        返 回 值: 无
*********************************************************************************************************
*/
static void TIM1_Config(void)
{
        TIM_HandleTypeDef  htim ={0};
        TIM_OC_InitTypeDef sConfig = {0};


        /* 使能时钟 */  
        __HAL_RCC_TIM1_CLK_ENABLE();
      
    /*-----------------------------------------------------------------------
                bsp.c 文件中 void SystemClock_Config(void) 函数对时钟的配置如下: 

        System Clock source       = PLL (HSE)
        SYSCLK(Hz)                = 400000000 (CPU Clock)
        HCLK(Hz)                  = 200000000 (AXI and AHBs Clock)
        AHB Prescaler             = 2
        D1 APB3 Prescaler         = 2 (APB3 Clock  100MHz)
        D2 APB1 Prescaler         = 2 (APB1 Clock  100MHz)
        D2 APB2 Prescaler         = 2 (APB2 Clock  100MHz)
        D3 APB4 Prescaler         = 2 (APB4 Clock  100MHz)

        因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = APB1 x 2 = 200MHz;
        因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = APB2 x 2 = 200MHz;
        APB4上面的TIMxCLK没有分频,所以就是100MHz;

        APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14,LPTIM1
        APB2 定时器有 TIM1, TIM8 , TIM15, TIM16,TIM17

        APB4 定时器有 LPTIM2,LPTIM3,LPTIM4,LPTIM5

    TIM12CLK = 200MHz/(Period + 1) / (Prescaler + 1) = 200MHz / 2000 / 1 = 100KHz
        ----------------------------------------------------------------------- */  
    HAL_TIM_Base_DeInit(&htim);
    
    htim.Instance = TIM1;
        htim.Init.Period            = 1999;
        htim.Init.Prescaler         = 999;
        htim.Init.ClockDivision     = 0;
        htim.Init.CounterMode       = TIM_COUNTERMODE_UP;
        htim.Init.RepetitionCounter = 0;
        HAL_TIM_Base_Init(&htim);
    
    sConfig.OCMode     = TIM_OCMODE_PWM1;
    sConfig.OCPolarity = TIM_OCPOLARITY_LOW;

    /* 占空比50% */
    sConfig.Pulse = 1000;  
    if(HAL_TIM_OC_ConfigChannel(&htim, &sConfig, TIM_CHANNEL_1) != HAL_OK)
    {
                Error_Handler(__FILE__, __LINE__);
    }

    /* 启动OC1 */
    if(HAL_TIM_OC_Start(&htim, TIM_CHANNEL_1) != HAL_OK)
    {
                Error_Handler(__FILE__, __LINE__);
    }
}

/*
*********************************************************************************************************
*        函 数 名: bsp_InitADC
*        功能说明: 初始化ADC
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitADC(void)
{
    ADC_HandleTypeDef   AdcHandle = {0};
        ADC_ChannelConfTypeDef   sConfig = {0};
        GPIO_InitTypeDef         GPIO_InitStruct;

        
  /* ## - 1 - 配置ADC采样的时钟 ####################################### */
#if defined (ADC_CLOCK_SOURCE_PLL)
        /* 配置PLL2时钟为的72MHz,方便分频产生ADC最高时钟36MHz */
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
        PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
        PeriphClkInitStruct.PLL2.PLL2M = 25;
        PeriphClkInitStruct.PLL2.PLL2N = 504;
        PeriphClkInitStruct.PLL2.PLL2P = 7;
        PeriphClkInitStruct.PLL2.PLL2Q = 7;
        PeriphClkInitStruct.PLL2.PLL2R = 7;
        PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_0;
        PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
        PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
        PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
        if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);  
        }
#elif defined (ADC_CLOCK_SOURCE_AHB)
  
  /* 使用AHB时钟的话,无需配置,默认选择*/
  
#endif

        /* ## - 2 - 配置ADC采样使用的引脚 ####################################### */
        __HAL_RCC_GPIOC_CLK_ENABLE();

        GPIO_InitStruct.Pin = GPIO_PIN_0;
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        /* ## - 3 - 配置ADC采样使用的时钟 ####################################### */
        __HAL_RCC_DMA1_CLK_ENABLE();
        DmaHandle.Instance                 = DMA1_Stream1;            /* 使用的DMA1 Stream1 */
        DmaHandle.Init.Request             = DMA_REQUEST_ADC1;            /* 请求类型采用DMA_REQUEST_ADC1 */  
        DmaHandle.Init.Direction           = DMA_PERIPH_TO_MEMORY;    /* 传输方向是从外设到存储器 */  
        DmaHandle.Init.PeriphInc           = DMA_PINC_DISABLE;        /* 外设地址自增禁止 */ 
        DmaHandle.Init.MemInc              = DMA_MINC_ENABLE;         /* 存储器地址自增使能 */  
        DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  /* 外设数据传输位宽选择半字,即16bit */     
        DmaHandle.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;  /* 存储器数据传输位宽选择半字,即16bit */    
        DmaHandle.Init.Mode                = DMA_CIRCULAR;            /* 循环模式 */   
        DmaHandle.Init.Priority            = DMA_PRIORITY_LOW;        /* 优先级低 */  
        DmaHandle.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;    /* 禁止FIFO*/
        DmaHandle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL; /* 禁止FIFO此位不起作用,用于设置阀值 */
        DmaHandle.Init.MemBurst            = DMA_MBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于存储器突发 */
        DmaHandle.Init.PeriphBurst         = DMA_PBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于外设突发 */
 
    /* 初始化DMA */
    if(HAL_DMA_Init(&DmaHandle) != HAL_OK)
    {
                Error_Handler(__FILE__, __LINE__);     
    }
    
    /* 开启DMA1 Stream1的中断 */
    HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 2, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
    
    /* 关联ADC句柄和DMA句柄 */
        __HAL_LINKDMA(&AdcHandle, DMA_Handle, DmaHandle);

        /* ## - 4 - 配置ADC ########################################################### */
        __HAL_RCC_ADC12_CLK_ENABLE();
        AdcHandle.Instance = ADC1;
        
#if defined (ADC_CLOCK_SOURCE_PLL)
        AdcHandle.Init.ClockPrescaler        = ADC_CLOCK_ASYNC_DIV2;          /* 采用PLL异步时钟,2分频,即72MHz/2 = 36MHz */
#elif defined (ADC_CLOCK_SOURCE_AHB)
        AdcHandle.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV4;      /* 采用AHB同步时钟,4分频,即200MHz/4 = 50MHz */
#endif
        AdcHandle.Init.Resolution            = ADC_RESOLUTION_16B;            /* 16位分辨率 */
        AdcHandle.Init.ScanConvMode          = ADC_SCAN_ENABLE;              /* 禁止扫描,因为仅开了一个通道 */
        AdcHandle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;           /* EOC转换结束标志 */
        AdcHandle.Init.LowPowerAutoWait      = DISABLE;                       /* 禁止低功耗自动延迟特性 */
        AdcHandle.Init.ContinuousConvMode    = DISABLE;                       /* 禁止自动转换,采用的定时器触发转换 */
        AdcHandle.Init.NbrOfConversion       = 4;                             /* 使用了1个转换通道 */
        AdcHandle.Init.DiscontinuousConvMode = DISABLE;                       /* 禁止不连续模式 */
        AdcHandle.Init.NbrOfDiscConversion   = 1;                             /* 禁止不连续模式后,此参数忽略,此位是用来配置不连续子组中通道数 */
        AdcHandle.Init.ExternalTrigConv      = ADC_EXTERNALTRIG_T1_CC1;            /* 定时器1的CC1触发 */
        AdcHandle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_RISING;    /* 上升沿触发 */
        AdcHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; /* DMA循环模式接收ADC转换的数据 */
        AdcHandle.Init.BoostMode                = ENABLE;                          /* ADC时钟超过20MHz的话,使能boost */
        AdcHandle.Init.Overrun                  = ADC_OVR_DATA_OVERWRITTEN;        /* ADC转换溢出的话,覆盖ADC的数据寄存器 */
        AdcHandle.Init.OversamplingMode         = DISABLE;                         /* 禁止过采样 */

    /* 初始化ADC */
        if (HAL_ADC_Init(&AdcHandle) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
  
        /* 校准ADC,采用偏移校准 */
        if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
  
  
        /* 配置ADC通道,序列1,采样PC0引脚 */
        sConfig.Channel      = ADC_CHANNEL_10;              /* 配置使用的ADC通道 */
        sConfig.Rank         = ADC_REGULAR_RANK_1;          /* 采样序列里的第1个 */
        sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;  /* 采样周期 */
        sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
        sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */ 
        sConfig.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
        sConfig.OffsetRightShift       = DISABLE;           /* 禁止右移 */
        sConfig.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
        
        if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
        
        /* 配置ADC通道,序列2,采样Vbat/4 */
        sConfig.Channel      = ADC_CHANNEL_VBAT_DIV4;       /* 配置使用的ADC通道 */
        sConfig.Rank         = ADC_REGULAR_RANK_2;          /* 采样序列里的第1个 */
        sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;  /* 采样周期 */
        sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
        sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */ 
        sConfig.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
        sConfig.OffsetRightShift       = DISABLE;           /* 禁止右移 */
        sConfig.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
        
        if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
  
        /* 配置ADC通道,序列3,采样VrefInt */
        sConfig.Channel      = ADC_CHANNEL_VREFINT;         /* 配置使用的ADC通道 */
        sConfig.Rank         = ADC_REGULAR_RANK_3;          /* 采样序列里的第1个 */
        sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;  /* 采样周期 */
        sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
        sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */ 
        sConfig.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
        sConfig.OffsetRightShift       = DISABLE;           /* 禁止右移 */
        sConfig.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
        
        if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }

        /* 配置ADC通道,序列4,采样温度 */
        sConfig.Channel      = ADC_CHANNEL_TEMPSENSOR;      /* 配置使用的ADC通道 */
        sConfig.Rank         = ADC_REGULAR_RANK_4;          /* 采样序列里的第1个 */
        sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;  /* 采样周期 */
        sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
        sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */ 
        sConfig.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
        sConfig.OffsetRightShift       = DISABLE;           /* 禁止右移 */
        sConfig.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
        
        if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }        
  
  
        /* ## - 5 - 配置ADC的定时器触发 ####################################### */
        TIM1_Config();
  
        /* ## - 6 - 启动ADC的DMA方式传输 ####################################### */
        if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)ADCxValues, 128*8) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }
}

/*
*********************************************************************************************************
*        函 数 名: DMA1_Stream1_IRQHandler
*        功能说明: DMA1 Stream1中断服务程序
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void DMA1_Stream1_IRQHandler(void)
{
        /* 传输完成中断 */
        if((DMA1->LISR & DMA_FLAG_TCIF1_5) != RESET)
        {
                /*
                   1、使用此函数要特别注意,第1个参数地址要32字节对齐,第2个参数要是32字节的整数倍。
                   2、进入传输完成中断,当前DMA正在使用缓冲区的前半部分,用户可以操作后半部分。
                */
                SCB_InvalidateDCache_by_Addr((uint32_t *)(&ADCxValues[64]), 128);
                
                s_DmaFlag = 2;
                HC574_TogglePin(GPIO_PIN_31);
                
                /* 清除标志 */
                DMA1->LIFCR = DMA_FLAG_TCIF1_5;
        }

        /* 半传输完成中断 */    
        if((DMA1->LISR & DMA_FLAG_HTIF1_5) != RESET)
        {
                /*
                   1、使用此函数要特别注意,第1个参数地址要32字节对齐,第2个参数要是32字节的整数倍。
                   2、进入半传输完成中断,当前DMA正在使用缓冲区的后半部分,用户可以操作前半部分。
                */
                SCB_InvalidateDCache_by_Addr((uint32_t *)(&ADCxValues[0]), 128);
                
                s_DmaFlag = 1;
                HC574_TogglePin(GPIO_PIN_31);
        
                /* 清除标志 */
                DMA1->LIFCR = DMA_FLAG_HTIF1_5;
        }

        /* 传输错误中断 */
        if((DMA1->LISR & DMA_FLAG_TEIF1_5) != RESET)
        {
                /* 清除标志 */
                DMA1->LIFCR = DMA_FLAG_TEIF1_5;
        }

        /* 直接模式错误中断 */
        if((DMA1->LISR & DMA_FLAG_DMEIF1_5) != RESET)
        {
                /* 清除标志 */
                DMA1->LIFCR = DMA_FLAG_DMEIF1_5;
        }
}

/*
*********************************************************************************************************
*        函 数 名: bsp_GetAdcValues
*        功能说明: 获取ADC的数据并打印
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void bsp_GetAdcValues(void)
{
        uint32_t values;
        float  temp;
        
//        /* 当前DMA操作是后半个缓冲,读取前半个缓冲的前4个数值求平均 */
//        if(s_DmaFlag == 1)
//        {
//                DISABLE_INT();
//                s_DmaFlag = 0;
//                values = (ADCxValues[0] + ADCxValues[1] + ADCxValues[2] + ADCxValues[3])/4;

//                ENABLE_INT();
//        }
//        /* 当前DMA操作是后前个缓冲,读取后半个缓冲的前4个数值求平均 */
//        else if(s_DmaFlag == 2)
//        {
//                DISABLE_INT();
//                s_DmaFlag = 0;
//                values = (ADCxValues[64] + ADCxValues[65] + ADCxValues[66] + ADCxValues[67])/4;
//                ENABLE_INT();
//        }
//        
//        /* 打印读出的串口值 */
//        temp = values *3.3 / 65536;
//        
//        printf("ADCxValues = %d, %5.3f\r\n", values, temp);
}

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

回复

使用道具 举报

8

主题

50

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2023-4-14 18:42:41 | 显示全部楼层
eric2013 发表于 2023-4-14 15:32
测试了个可用,4通道的,TIM1触发,双缓冲

我看了下,好像就这里有点区别
微信截图_20230414183902.png
但是我的代码改成这样,定时器中断和DMA中断都进不去了...我再找找原因,教程的单个通道的DMA半传输完成的例子也是对的,就是不知道是不是换了定时器哪里没配置好
回复

使用道具 举报

210

主题

1045

回帖

1685

积分

至尊会员

More we do, more we can do.

积分
1685
发表于 2023-4-14 23:03:05 | 显示全部楼层
从调试来说,你可以把频率改小,比如1Hz,这样仿真观察特别明显
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2023-4-15 03:18:03 | 显示全部楼层
wling597074509 发表于 2023-4-14 18:42
我看了下,好像就这里有点区别

但是我的代码改成这样,定时器中断和DMA中断都进不去了...我再找找原因 ...

你的是TIM2,32bit定时器,我用的TIM1,16bit定时器。
回复

使用道具 举报

8

主题

50

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2023-4-15 18:01:42 | 显示全部楼层
eric2013 发表于 2023-4-15 03:18
你的是TIM2,32bit定时器,我用的TIM1,16bit定时器。

把定时器改成TIM1了,结果也是一样的,始终是2倍理论时间。
只把我的ADC代码复制到“V7-019_ADC定时器触发+DMA双缓冲实现”,用V7的板子,时间是对的;
把“V7-019_ADC定时器触发+DMA双缓冲实现”工程的HAL库和CMSIS版本更新到跟我的工程版本一样,时间还是对的;
把“V7-019_ADC定时器触发+DMA双缓冲实现”工程systemclock和MPU配置改成跟我的工程一样,时间仍然是对的;
然后干脆把我的工程下载到V7开发板,时间又是理论时间的2倍。
区别就是我的工程里用了ThreadX,GUIX,FILEX和USBx,不过感觉不应该有影响呀。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2023-4-16 00:21:47 | 显示全部楼层
wling597074509 发表于 2023-4-15 18:01
把定时器改成TIM1了,结果也是一样的,始终是2倍理论时间。
只把我的ADC代码复制到“V7-019_ADC定时器触 ...

可以考虑仅创建一个任务,里面仅执行ADC,其它任务创建都注释掉试试。
回复

使用道具 举报

8

主题

50

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2023-4-16 19:06:08 | 显示全部楼层
eric2013 发表于 2023-4-16 00:21
可以考虑仅创建一个任务,里面仅执行ADC,其它任务创建都注释掉试试。

其实ADC都不在任务里,就是DMA中断里发了事件标志,我把GUIX和USBX的任务都注释了,还是一样的。
但是我把ADC的通道数改成1-2个就是对的,3、4个都不行。
回复

使用道具 举报

335

主题

2037

回帖

3047

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3047
发表于 2023-4-17 07:37:34 | 显示全部楼层
wling597074509 发表于 2023-4-15 18:01
把定时器改成TIM1了,结果也是一样的,始终是2倍理论时间。
只把我的ADC代码复制到“V7-019_ADC定时器触 ...

几个ADC是共用一个时钟设定的。 是不是你的其他ADC重设了时钟分频什么的。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2023-4-17 09:39:03 | 显示全部楼层
wling597074509 发表于 2023-4-16 19:06
其实ADC都不在任务里,就是DMA中断里发了事件标志,我把GUIX和USBX的任务都注释了,还是一样的。
但是我 ...

干脆,直接把我bsp_adc.c的实现全部覆盖你的实现,通过逐步修改成你的实现方式来排查。
回复

使用道具 举报

8

主题

50

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2023-4-17 10:40:47 | 显示全部楼层
eric2013 发表于 2023-4-17 09:39
干脆,直接把我bsp_adc.c的实现全部覆盖你的实现,通过逐步修改成你的实现方式来排查。

差不多也是这么干的了,我想问下硬汉兄ADC的值保存的区域是不是有影响(我是直接这么用的:ALIGN_32BYTES (uint16_t ADCxValues[ADCNUM]);),因为我是在“18.ThreadX+Filex+GUIX+NetXDUO+USBX综合模板,含MDK AC5,AC6,IAR和GCC”这个工程的基础上建立的我的工程(AC6),只是把各种库都更新到了最新版,这个工程没有用stm32-v7.sct这个分散加载文件,但是ADC的例程里是用的,我试图用stm32-v7.sct,但是老是报错,还没调好。
回复

使用道具 举报

8

主题

50

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2023-4-17 10:42:04 | 显示全部楼层
caicaptain2 发表于 2023-4-17 07:37
几个ADC是共用一个时钟设定的。 是不是你的其他ADC重设了时钟分频什么的。

其他地方没用到ADC了,感觉不应该跟ADC的时钟有关系,倒是TIMER的时钟不知道会不会发生什么变化,不过用TIMER中断看,定时时间也是对的
回复

使用道具 举报

2

主题

16

回帖

22

积分

新手上路

积分
22
发表于 2023-4-18 16:55:49 | 显示全部楼层
我用H723也遇到了类似问题,速度少了一半。
回复

使用道具 举报

8

主题

50

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2023-4-24 18:09:11 | 显示全部楼层
zcbclin 发表于 2023-4-18 16:55
我用H723也遇到了类似问题,速度少了一半。

你好,请问是否解决了这个问题?
回复

使用道具 举报

8

主题

50

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2023-4-24 18:15:58 | 显示全部楼层
工程链接,还请各位大神帮忙看看,百思不得其解。。。
链接:https://pan.baidu.com/s/1oOX894sBxH4VROaDCb_WOg?pwd=s53u
提取码:s53u
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2023-4-25 10:02:53 | 显示全部楼层
wling597074509 发表于 2023-4-24 18:15
工程链接,还请各位大神帮忙看看,百思不得其解。。。
链接:https://pan.baidu.com/s/1oOX894sBxH4VROaDC ...

看着没什么问题。
回复

使用道具 举报

8

主题

50

回帖

79

积分

初级会员

积分
79
 楼主| 发表于 2023-4-25 15:36:22 | 显示全部楼层
eric2013 发表于 2023-4-25 10:02
看着没什么问题。

算了,不折腾了,就把定时器的定时周期减少一半吧。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-12 23:44 , Processed in 0.236589 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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