硬汉嵌入式论坛

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

[ADC] STM32H723 多通道定时器触发ADC+DMA连续采样标准PWM信号的STM32Cubemx配置与代码问题(帮忙解决问题悬赏20¥,不够再加)

[复制链接]

0

主题

5

回帖

5

积分

新手上路

积分
5
发表于 2024-11-12 10:28:53 | 显示全部楼层 |阅读模式
采样信号源为100Hz的标准PWM信号,采用1khz的采样率,即每1ms采样一次,采集10个频点,计算采样点的平方和,求得结果为单周期内信号的有效值,STM32Cubemx配置与main函数代码如下:


时钟部分(25M与32.768k晶振均已接入):
1.png

ADC配置:
2.png

ADC传输DMA配置:
3.png

定时器配置(PSC为275,ARR为1000):
4.png

时钟分频配置:
5.png


主函数代码(已删去STM32Cubemx生成固定部分及部分时钟与硬件报错部分代码,方便阅读):
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "memorymap.h"
#include "tim.h"
#include "gpio.h"

// 定义每个通道的采样数
#define SAMPLES_PER_PERIOD 10

#define VREF 3.3f // ADC参考电压
#define ADC_MAX_VALUE 65535 // 12位ADC的最大值

#define ADC_CHANNEL_COUNT 3
uint32_t adc_buffer[ADC_CHANNEL_COUNT];

// 三个通道的采样数据缓冲区
uint32_t channel1_samples[SAMPLES_PER_PERIOD] = {0};
uint32_t channel2_samples[SAMPLES_PER_PERIOD] = {0};
uint32_t channel3_samples[SAMPLES_PER_PERIOD] = {0};

// 采样计数器
uint8_t sample_index = 0;

uint32_t time;

int i;

// RMS值变量
float channel1_rms = 0.0f;
float channel2_rms = 0.0f;
float channel3_rms = 0.0f;

// 主循环中的处理函数
void Process_ADC_Samples()
{
    // 累计平方和变量
    uint32_t sum1 = 0;
    uint32_t sum2 = 0;
    uint32_t sum3 = 0;

    // 累加每个采样点的平方和
    for (int i = 0; i < SAMPLES_PER_PERIOD; i++)
    {
        sum1 += channel1_samples * channel1_samples;
        sum2 += channel2_samples * channel2_samples;
        sum3 += channel3_samples * channel3_samples;
    }

    // 计算RMS电压值
    float rms_adc1 = sqrtf((float)sum1 / SAMPLES_PER_PERIOD);
    float rms_adc2 = sqrtf((float)sum2 / SAMPLES_PER_PERIOD);
    float rms_adc3 = sqrtf((float)sum3 / SAMPLES_PER_PERIOD);

    // 转换为电压值
    channel1_rms = (rms_adc1 * VREF) / ADC_MAX_VALUE;
    channel2_rms = (rms_adc2 * VREF) / ADC_MAX_VALUE;
    channel3_rms = (rms_adc3 * VREF) / ADC_MAX_VALUE;
}

// DMA完成后的回调函数
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if(hadc->Instance == ADC1)
    {
        // 将每个通道的采样值保存到各自的缓冲区中
        channel1_samples[sample_index] = adc_buffer[0];
        channel2_samples[sample_index] = adc_buffer[1];
        channel3_samples[sample_index] = adc_buffer[2];

        // 更新采样计数器
        sample_index++;

        // 检查是否完成10个采样点
        if (sample_index >= SAMPLES_PER_PERIOD)
        {
            // 计算有效值
            Process_ADC_Samples();

            // 打印或记录RMS值
//            printf("Channel 1 RMS: %.2f, Channel 2 RMS: %.2f, Channel 3 RMS: %.2f\n", channel1_rms, channel2_rms, channel3_rms);

            // 重置采样计数器
            sample_index = 0;
        }
    }
}

void SystemClock_Config(void);

int main(void)
{

  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_TIM2_Init();

        
        // 启动ADC并启用DMA传输
//  HAL_ADC_Start_DMA(&hadc1, (uint32_t *) adc_buffer, ADC_CHANNEL_COUNT);
        
//        HAL_TIM_Base_Start(&htim2);
        
        HAL_TIM_Base_Start_IT(&htim2);


  while (1)
  {
//                HAL_ADC_Start_DMA(&hadc1, (uint32_t *) adc_buffer, ADC_CHANNEL_COUNT);
               
                HAL_Delay(1000);
                i++;
               
  }

}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim == (&htim2))
    {
                        HAL_ADC_Start_DMA(&hadc1, (uint32_t *) adc_buffer, ADC_CHANNEL_COUNT);
                        time++;
    }
}

目前现象为:定时器定周期触发正常,ADC采样异常,代码优化等级为O0,通道2引脚接入3V占空比满的PWM信号,Debug采样数据如下:
下载 (9).png

请问各位大佬配置或代码哪部分出问题了,应该如何修改?
有大佬看到求求解答一下,感激不尽,悬赏嫌少了我再加



回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2024-11-12 13:12:22 | 显示全部楼层
使用方法不太合理。
1、没看到你的DMA RAM空间分配到那个地址了,注意不要分配到DTCM RAM空间了,这个空间不支持通用DMA
2、这个定时器中断HAL_TIM_PeriodElapsedCallback,定时触发一次就进入这个中断了。你的中断里面又调用了一次HAL_ADC_Start_DMA,应该是DMA传输完毕后,再开重新开始。
回复

使用道具 举报

6

主题

306

回帖

324

积分

高级会员

积分
324
发表于 2024-11-12 15:40:05 | 显示全部楼层
我觉得没必要定时器触发,连续触发即可,设置ADC时钟,采样时间,过采样等参数,你想要的效果。
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 2024-11-13 20:01:56 | 显示全部楼层
eric2013 发表于 2024-11-12 13:12
使用方法不太合理。
1、没看到你的DMA RAM空间分配到那个地址了,注意不要分配到DTCM RAM空间了,这个空间 ...

大佬你好,我的H7并没有开始内存保护,默认是不写入Cache内存区,而是直接写入数组的内存所在的地址的,我想请问一下
1、对于我1楼描述的PWM信号,如果想使用定时器定周期采样,使用STM32Cubemx配置的时候,应该修改为怎样的配置
2、我的设想是定时器1ms触发一次采样,ADC扫描3个通道并触发DMA传输,将频点存储起来,采集10次为单个周期的信号,处理一次。由于我ADC配置的是非连续采样,DMA配置为单次传输,加上ADC对3通道轮询一次并转换的时间是小于1ms的,所以我认为这样是可行的
我之前有使用过ADC连续采样并配置DMA为循环模式,这样ADC一直转换,无法定周期采样,对于ADC采样的配置这一块,各种文章都看过,包括安富莱的H7手册,但一直不是很能完全理解几种模式之间的协同配合,希望大佬能够就本次的问题做进一步的指点
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2024-11-14 09:14:02 | 显示全部楼层
haigulingfeng 发表于 2024-11-13 20:01
大佬你好,我的H7并没有开始内存保护,默认是不写入Cache内存区,而是直接写入数组的内存所在的地址的, ...

1、我没用过CubeMX配置ADC
2、这种的仅开启DMA传输完成中断即可。定时器中断不需要开。DMA传输完成后处理数据即可。以后再用,直接在中断外再启动。
3、定时器+ADC DMA也可以循环模式,配合双缓冲即可,这个V7的用户手册有个例子的,比较适合你的这个场景,不需要频繁重启。
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 2024-11-14 10:11:09 | 显示全部楼层
eric2013 发表于 2024-11-14 09:14
1、我没用过CubeMX配置ADC
2、这种的仅开启DMA传输完成中断即可。定时器中断不需要开。DMA传输完成后处 ...

如果我将ADC配置成了扫描模式+连续转换,DMA配置为循环模式,调用一次HAL_ADC_Start_DMA函数后,ADC不是会一直连续转换吗,这样我要如何确定采样的周期呢
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 2024-11-14 15:19:17 | 显示全部楼层
顶一下,以下是更新过后的配置,还是不行

关闭CaChe:


ADC主频96M,4分频(24M):


配置为扫描模式,关闭连续转换模式,DMA配置为循环模式,触发方式为定时器1内部输入捕获:




定时器配置为1khz频率,内部输入周期触发:


main函数代码:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "memorymap.h"
#include "tim.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

int s_time = 0;
int ms_time = 0;

#define ADC_CHANNEL_NUM    3       // ADC通道数量
#define ADC_SAMPLE_COUNT   10      // 每通道采样次数

#define VREF 3.3f // ADC参考电压
#define ADC_MAX_VALUE 65535 // 16位ADC的最大值

uint32_t adcBuffer[ADC_CHANNEL_NUM * ADC_SAMPLE_COUNT];  // 用于存储DMA采集的数据
uint32_t adcAverage[ADC_CHANNEL_NUM];                    // 用于存储每个通道的平均值
float Voltage[ADC_CHANNEL_NUM];        //真实电压

// ADC转换完成回调函数
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if (hadc->Instance == ADC1)
    {
        for (int channel = 0; channel < ADC_CHANNEL_NUM; channel++)
        {
            uint32_t sum = 0;
            for (int sample = 0; sample < ADC_SAMPLE_COUNT; sample++)
            {
                sum += adcBuffer[channel + sample * ADC_CHANNEL_NUM];
            }
            adcAverage[channel] = sum / ADC_SAMPLE_COUNT;  // 计算平均值
                                                Voltage[channel] = (float)adcAverage[channel]*VREF/ADC_MAX_VALUE;
        }
                               
                                ms_time++;

        // 处理完数据后,可以重新启动ADC DMA采集
//        if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcBuffer, ADC_CHANNEL_NUM * ADC_SAMPLE_COUNT) != HAL_OK)
//        {
//            Error_Handler();
//        }
    }
}

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
       
        /* 启动 OC1 */
        if(HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
        {
                Error_Handler();
        }
       
        // 启动ADC并启用DMA传输
        if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcBuffer, ADC_CHANNEL_NUM * ADC_SAMPLE_COUNT) != HAL_OK)
        {
                Error_Handler();
        }
       
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
                HAL_Delay(1000);

                s_time++;
               
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Supply configuration update enable
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = 64;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 34;
  RCC_OscInitStruct.PLL.PLLP = 1;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 3072;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{

}

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
               
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */


运行效果:DMA指向的数组前一半有数据,且全为异常数据,后一半没有数据,定时器周期触发频率正常,实在是找不到原因,弄了两天搞的焦头烂额,心态要爆炸了......
运行效果如下图:


提高悬赏到50,有搞过的大佬麻烦帮帮忙看一下是哪里出了问题

STM32Cubemx生成的配置代码如下:
adc.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    adc.c
  * @brief   This file provides code for the configuration
  *          of the ADC instances.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "adc.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

/* ADC1 init function */
void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_16B;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 3;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.NbrOfDiscConversion = 1;
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_CC1;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
  hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc1.Init.OversamplingMode = DISABLE;
  hadc1.Init.Oversampling.Ratio = 1;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  sConfig.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */
       
        /* 校准ADC,采用偏移校准 */
        if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
        {
                Error_Handler();
        }
  /* USER CODE END ADC1_Init 2 */

}

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(adcHandle->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspInit 0 */

  /* USER CODE END ADC1_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    PeriphClkInitStruct.PLL2.PLL2M = 4;
    PeriphClkInitStruct.PLL2.PLL2N = 12;
    PeriphClkInitStruct.PLL2.PLL2P = 2;
    PeriphClkInitStruct.PLL2.PLL2Q = 2;
    PeriphClkInitStruct.PLL2.PLL2R = 2;
    PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
    PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
    PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    /* ADC1 clock enable */
    __HAL_RCC_ADC12_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOF_CLK_ENABLE();
    /**ADC1 GPIO Configuration
    PA6     ------> ADC1_INP3
    PC4     ------> ADC1_INP4
    PF11     ------> ADC1_INP2
    */
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

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

    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

    /* ADC1 DMA Init */
    /* ADC1 Init */
    hdma_adc1.Instance = DMA1_Stream0;
    hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_adc1.Init.Mode = DMA_CIRCULAR;
    hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
    hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);

    /* ADC1 interrupt Init */
    HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(ADC_IRQn);
  /* USER CODE BEGIN ADC1_MspInit 1 */

  /* USER CODE END ADC1_MspInit 1 */
  }
}

void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{

  if(adcHandle->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspDeInit 0 */

  /* USER CODE END ADC1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_ADC12_CLK_DISABLE();

    /**ADC1 GPIO Configuration
    PA6     ------> ADC1_INP3
    PC4     ------> ADC1_INP4
    PF11     ------> ADC1_INP2
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_6);

    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_4);

    HAL_GPIO_DeInit(GPIOF, GPIO_PIN_11);

    /* ADC1 DMA DeInit */
    HAL_DMA_DeInit(adcHandle->DMA_Handle);

    /* ADC1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(ADC_IRQn);
  /* USER CODE BEGIN ADC1_MspDeInit 1 */

  /* USER CODE END ADC1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */


tim.c
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    tim.c
  * @brief   This file provides code for the configuration
  *          of the TIM instances.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "tim.h"


/* USER CODE BEGIN 0 */


/* USER CODE END 0 */


TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;


/* TIM1 init function */
void MX_TIM1_Init(void)
{


  /* USER CODE BEGIN TIM1_Init 0 */


  /* USER CODE END TIM1_Init 0 */


  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};


  /* USER CODE BEGIN TIM1_Init 1 */


  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 275-1;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 1000-1;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 500-1;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.BreakFilter = 0;
  sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
  sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
  sBreakDeadTimeConfig.Break2Filter = 0;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */
       
//        /* 启动 OC1 */
//        if(HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
//        {
//                Error_Handler();
//        }
       
  /* USER CODE END TIM1_Init 2 */
  HAL_TIM_MspPostInit(&htim1);


}
/* TIM2 init function */
void MX_TIM2_Init(void)
{


  /* USER CODE BEGIN TIM2_Init 0 */


  /* USER CODE END TIM2_Init 0 */


  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};


  /* USER CODE BEGIN TIM2_Init 1 */


  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 275-1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 1000-1;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 500-1;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */


  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);


}


void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
{


  if(tim_pwmHandle->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspInit 0 */


  /* USER CODE END TIM1_MspInit 0 */
    /* TIM1 clock enable */
    __HAL_RCC_TIM1_CLK_ENABLE();


    /* TIM1 interrupt Init */
    HAL_NVIC_SetPriority(TIM1_BRK_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM1_BRK_IRQn);
    HAL_NVIC_SetPriority(TIM1_UP_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
    HAL_NVIC_SetPriority(TIM1_TRG_COM_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM1_TRG_COM_IRQn);
    HAL_NVIC_SetPriority(TIM1_CC_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
  /* USER CODE BEGIN TIM1_MspInit 1 */


  /* USER CODE END TIM1_MspInit 1 */
  }
  else if(tim_pwmHandle->Instance==TIM2)
  {
  /* USER CODE BEGIN TIM2_MspInit 0 */


  /* USER CODE END TIM2_MspInit 0 */
    /* TIM2 clock enable */
    __HAL_RCC_TIM2_CLK_ENABLE();
  /* USER CODE BEGIN TIM2_MspInit 1 */


  /* USER CODE END TIM2_MspInit 1 */
  }
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{


  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(timHandle->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspPostInit 0 */


  /* USER CODE END TIM1_MspPostInit 0 */
    __HAL_RCC_GPIOE_CLK_ENABLE();
    /**TIM1 GPIO Configuration
    PE9     ------> TIM1_CH1
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);


  /* USER CODE BEGIN TIM1_MspPostInit 1 */


  /* USER CODE END TIM1_MspPostInit 1 */
  }
  else if(timHandle->Instance==TIM2)
  {
  /* USER CODE BEGIN TIM2_MspPostInit 0 */


  /* USER CODE END TIM2_MspPostInit 0 */


    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**TIM2 GPIO Configuration
    PA0     ------> TIM2_CH1
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


  /* USER CODE BEGIN TIM2_MspPostInit 1 */


  /* USER CODE END TIM2_MspPostInit 1 */
  }


}


void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle)
{


  if(tim_pwmHandle->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspDeInit 0 */


  /* USER CODE END TIM1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM1_CLK_DISABLE();


    /* TIM1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(TIM1_BRK_IRQn);
    HAL_NVIC_DisableIRQ(TIM1_UP_IRQn);
    HAL_NVIC_DisableIRQ(TIM1_TRG_COM_IRQn);
    HAL_NVIC_DisableIRQ(TIM1_CC_IRQn);
  /* USER CODE BEGIN TIM1_MspDeInit 1 */


  /* USER CODE END TIM1_MspDeInit 1 */
  }
  else if(tim_pwmHandle->Instance==TIM2)
  {
  /* USER CODE BEGIN TIM2_MspDeInit 0 */


  /* USER CODE END TIM2_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM2_CLK_DISABLE();
  /* USER CODE BEGIN TIM2_MspDeInit 1 */


  /* USER CODE END TIM2_MspDeInit 1 */
  }
}


/* USER CODE BEGIN 1 */


/* USER CODE END 1 */

感激不尽



回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2024-11-15 09:03:43 | 显示全部楼层
haigulingfeng 发表于 2024-11-14 15:19
顶一下,以下是更新过后的配置,还是不行

关闭CaChe:

你这个变量正常递增没有ms_time

不行的话,直接用我们V7板子配套的定时器+DMA触发试试。

回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 2024-11-22 09:37:58 | 显示全部楼层
找到原因了,数组忘记改成uint16_t了,使用uint32_t的数组叠到一起去了
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2024-11-23 09:37:53 | 显示全部楼层
haigulingfeng 发表于 2024-11-22 09:37
找到原因了,数组忘记改成uint16_t了,使用uint32_t的数组叠到一起去了

谢谢告知最终原因。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-14 03:07 , Processed in 0.434820 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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