STM32 HAL PWM DMA 传输数据

本文探讨了一种使用HAL库进行DMA传输时遇到的问题,并详细记录了如何通过调整数组最后一个元素来修正异常波形的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、设置pwm dma配置

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

/* USER CODE END PFP */

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

  uint16_t buffer[10];

/* 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_TIM2_Init();
  /* USER CODE BEGIN 2 */
	
		for(int i = 0;i<10;i++)
		{
			buffer[i] = 20 + i*5;
		}		
 
  /* USER CODE END 2 */

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

	HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_1, (uint32_t *)&buffer,10);
 
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

示波器波形如图:

不过我数组定义的是  uint16_t buffer[10];

数组初始化累加

		for(int i = 0;i<10;i++)
		{
			buffer[i] = 20 + i*5;
		}	

数据发送是

        HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_1, (uint32_t *)&buffer,10);

按照道理 是10个方波 周期是 800k  【mcu 主频64M】

10个占空比依次增大。但是上图的现象不是这样的。

本着求知的心态,希望找出问题

首先 我们设置了uint16 的数组,也设置了dma 半字的传输方式,按理来说应该是正常的输出波形

难道是HAL_TIM_PWM_Start_DMA 这个 (uint32_t *) 字符指针?我修改成 void *  波形也没有变化,我查了网上的资料,这个可以不用管。

主要是dma传输 设置 和数组定义。

后面在网上找到问题的解决方法。

		for(int i = 0;i<10;i++)
		{
			buffer[i] = 20 + i*5;
		}		
    	buffer[9] = 0;

定义的传输数组的最后一个数组,设置为零,这样传输数据就可以正常现象了。

【比如需要10个字符,可以定义11个,最后一个设置为0就好了】

 

### STM32 HAL库使用DMA实现PWMSTM32微控制器系列中,利用硬件抽象层(HAL)库可以简化对外设的操作。对于需要高效处理的任务,如PWM波形生成,结合DMA技术能够显著提升性能和稳定性[^1]。 #### 初始化配置 为了使能DMA功能并将其与TIM定时器关联用于PWM输出,需先完成基本初始化设置: ```c // 定义 TIM_HandleTypeDef 和 DMA_HandleTypeDef 结构体变量 TIM_HandleTypeDef htimX; DMA_HandleTypeDef hdma_timX_chY; void MX_TIMx_PWM_Init(void){ __HAL_RCC_TIMx_CLK_ENABLE(); // 启用定时器时钟 /* 配置定时器 */ htimX.Instance = TIMx; htimX.Init.Prescaler = 79; htimX.Init.CounterMode = TIM_COUNTERMODE_UP; htimX.Init.Period = 999; if (HAL_TIM_PWM_Init(&htimX) != HAL_OK){ Error_Handler(); } /* 设置 PWM 输出通道 */ TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htimX, &sConfigOC, TIM_CHANNEL_Y) != HAL_OK){ Error_Handler(); } } ``` #### DMA配置 接着要为上述定时器实例化对应的DMA请求,并指定其工作模式以及中断回调函数来管理数据传输过程中的事件通知: ```c static void MX_DMA_Init(void){ __HAL_RCC_DMA1_CLK_ENABLE(); /*** 配置 DMA 请求 ***/ hdma_timX_chY.Instance = DMA1_ChannelZ; hdma_timX_chY.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_timX_chY.Init.PeriphInc = DMA_PINC_DISABLE; hdma_timX_chY.Init.MemInc = DMA_MINC_ENABLE; hdma_timX_chY.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_timX_chY.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_timX_chY.Init.Mode = DMA_CIRCULAR; hdma_timX_chY.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_timX_chY) != HAL_OK){ Error_Handler(); } /** 关联 DMA 到定时器 **/ __HAL_LINKDMA(htimX, hdmar, hdma_timX_chY); } /* 中断服务程序定义 */ void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim){ if(htim->Instance==TIMx){ /* 开启 DMA 时钟 */ __HAL_RCC_DMA1_CLK_ENABLE(); /* 配置 NVIC 对应的 IRQ Channel */ HAL_NVIC_SetPriority(DMA1_ChannelZ_IRQn, 0, 1); HAL_NVIC_EnableIRQ(DMA1_ChannelZ_IRQn); } } ``` #### 数据准备与启动 最后,在应用程序逻辑里准备好待发送的数据缓冲区,并调用`HAL_TIMEx_PWM_Start_DMA()`方法触发DMA操作: ```c uint16_t aPwmDutyCycle[ARR_SIZE]; int main(){ ... MX_TIMx_PWM_Init(); MX_DMA_Init(); // 填充占空比数组... for(int i=0;i<ARR_SIZE;i++){ aPwmDutyCycle[i]=... ; // 用户自定义值 } if(HAL_TIMEx_PWM_Start_DMA(&htimX,TIM_CHANNEL_Y,(uint32_t*)aPwmDutyCycle, ARR_SIZE)!= HAL_OK){ Error_Handler(); } while(1){} } ``` 此段代码展示了如何基于STM32 HAL库构建一个简单的DMA驱动型PWM发生器框架。实际应用中可能还需要考虑更多细节调整以满足特定需求。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值