STM32定时器应用——输出PWM给电机调速


源码下载
分享链接PWM资料下载
密码:123456


一、PWM简介

简单来说,存在一个计数器,计数值随时间进行周期性变化。最小值和最大值之间存在一个自定的值,当计数器的值小于自定值时,I/O输出低电平,大于自定值则产生高电平。通过设置不同的最大值和自定值,可以控制I/O口输出不同时间宽度的高低电平。

图1.1 来自百度百科

二、硬件部分

  • 摘要
    运用定时器调整PWM输出值,使直流电机从慢到快,再从快到慢。

  • 硬件设备:

名称 型号 数量
STM32开发板 STM32F407ZGT6 1
电机驱动 L298N 1
电机 普通直流 1
电池 9V锂电池 1
导线 杜邦线 若干
  • 硬件连接
  1. (STM32) PA9-------IN1 (L298N)
  2. (STM32) PA10------IN2 (L298N)
  3. (STM32) PF9-------ENA (L298N)
  4. 直流电机------OUT1, OUT2 (L298N)
  5. 9V电池------12V、GND(L298N)

备注:

  1. 所有GND接口都应接在一起,不然会出现电机转动异常。
  2. L298N的12V口接输入电源(5V~12V均可)
  3. L298N的5V口接单片机5V口,用于给单片机供电
  4. 拔掉ENA上的帽子,本实验中ENA接单片机的PWM输出口PF9

预览:
在这里插入图片描述

  • 现象
    打开电源,直流电机转动速度由慢到快,再由快到慢周期变化。

三、软件部分

1. PWM初始化 pwm.c

/**@file     pwm.c
* @brief     PWM初始化
* @author    BROSY
* @date      2020年4月19日
* @version   V1.0
* @copyright CSU | BROSY
*******************************************************************************
* @par 修改日志:
* <table>
* <tr><th>Date        <th>Version  <th>Author    <th>Description
* <tr><td>2018/08/17  <td>1.0      <td>songqijin  <td>创建初始版本
* </table>
*******************************************************************************
*/

/*=============================== 头文件包含 ================================*/
#include "pwm.h"

/*================================ 接口函数 =================================*/
/******************************************************************************
 * @brief   PWM初始化
 * @details 初始化定时器14,I/O口F9,PWM设置
 * @param   [in]arr   定时器分频(u32)
 * @param   [in]psc   自动重装载值(u32)
 * @return  void
 *****************************************************************************/
void TIM14_PWM_Init(u32 arr, u32 psc)
{
	GPIOF9_Init(); 		  ///< 初始化PWM输出口GPIOF9
	TIM14_Init(arr, psc); ///< 初始化定时器TIM14
	PWM_Init(); 		  ///< 初始化PWM	
}

/******************************************************************************
 * @brief   GPIOF9初始化
 * @details 复用映射到TIM14,F9作为PWM输出口
 * @param   void
 * @return  void
 *****************************************************************************/
void GPIOF9_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; ///< 定义GPIO初始化结构体
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); ///<使能GPIOF时钟
	
	/*!
	* GPIOF9初始化设置
	*/
	{
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;           ///< GPIOF9
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        ///< 复用功能
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	///< 速度100MHz
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      ///< 推挽复用输出
		GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        ///< 上拉
		GPIO_Init(GPIOF,&GPIO_InitStructure);               ///< 初始化PF9
	}
	
	/*GPIOF9复用映射到定时器14*/
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_TIM14);
}

/******************************************************************************
 * @brief   定时器14初始化
 * @param   [in]arr   定时器分频(u32)
 * @param   [in]psc   自动重装载值(u32)  
 * @return  void
 *****************************************************************************/
void TIM14_Init(u32 arr, u32 psc)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; ///< 定义定时器初始化结构体
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE); ///< 使能TIM14时钟
	
	/*!
	* 初始化定时器TIM14
	*/
	{
		TIM_TimeBaseStructure.TIM_Prescaler=psc;  				  ///< 定时器分频
		TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; ///< 向上计数模式
		TIM_TimeBaseStructure.TIM_Period=arr;   				  ///< 自动重装载值
		TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 	  ///< 分频模式
		TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStructure);			  ///< 初始化定时器14
	}
	
}

/******************************************************************************
 * @brief   PWM初始设置
 * @param   void
 * @return  void
 *****************************************************************************/
void PWM_Init()
{
	TIM_OCInitTypeDef TIM_OCInitStructure;

	/*!
	* 初始化PWM输出通道
	*/
	{
		TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 				///< PWM模式1,“小于”有效
		TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_Low; 		///< 低电平有效
		TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 	///< 输出使能
		TIM_OC1Init(TIM14, &TIM_OCInitStructure); 						///< 初始化PWM输出通道
	}
		
	/*!
	* 使能预装载寄存器
	*/
	{
		TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); ///< 使能TIM14在CCR1上的预装载寄存器
		TIM_ARRPreloadConfig(TIM14,ENABLE); 			   ///< ARPE使能
	}
	
	TIM_Cmd(TIM14, ENABLE);  ///< 使能TIM14
}

2. PWM初始化pwm.h

/**@file     pwm.h
* @brief     PWM初始化
* @author    BROSY
* @date      2020年4月19日
* @version   V1.0
* @copyright CSU | BROSY
*******************************************************************************
* @par 修改日志:
* <table>
* <tr><th>Date        <th>Version  <th>Author    <th>Description
* <tr><td>2018/08/17  <td>1.0      <td>songqijin  <td>创建初始版本
* </table>
*******************************************************************************
*/

#ifndef __PWM_
#define __PWM_

/*=============================== 头文件包含 ================================*/
#include "sys.h"

/*===============================函数声明 ===================================*/
void GPIOF9_Init(void); ///< 初始化GPIOF9
void TIM14_Init(u32 arr, u32 psc); ///< 初始化定时器TIM14
void PWM_Init(void); ///< PWM初始设置
void TIM14_PWM_Init(u32 arr, u32 psc); ///< 初始化PWM
#endif

3. 电机控制motor.c

/**@file     motor.c
* @brief     电机对应I/O口初始化
* @author    BROSY
* @date      2020年4月19日
* @version   V1.0
* @copyright CSU | BROSY
*******************************************************************************
* @par 修改日志:
* <table>
* <tr><th>Date        <th>Version  <th>Author    <th>Description
* <tr><td>2018/08/17  <td>1.0      <td>songqijin  <td>创建初始版本
* </table>
*******************************************************************************
*/

/*=============================== 头文件包含 ================================*/
#include "motor.h"
#include "sys.h"

/*================================ 接口函数 =================================*/
/******************************************************************************
 * @brief   PA9, PA10初始化
 * @details PA9输出高电平,PA10输出低电平。
 * @param   void
 * @return  void
 *****************************************************************************/
void MOTOR_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructrue; ///> 定义GPIO结构体
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); ///> 使能GPIOA时钟
	
	/*!
	* 初始化GPIOA9, GPIOA10
	*/
	{
		GPIO_InitStructrue.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; ///> 初始化PA9, PA10
		GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_OUT; 			///> 普通输出模式
		GPIO_InitStructrue.GPIO_OType = GPIO_OType_PP; 			///> 推挽输出
		GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_100MHz; 		///> 输出频率为100MHz
		GPIO_InitStructrue.GPIO_PuPd = GPIO_PuPd_UP; 			///> 上拉,输出高电平
		GPIO_Init(GPIOA, &GPIO_InitStructrue); 					///> 初始化GPIO
	}
	
	GPIO_SetBits(GPIOA, GPIO_Pin_9); 	///> P9设置为高电平
	GPIO_ResetBits(GPIOA, GPIO_Pin_10); ///> P10设置为低电平
}

4. 电机控制motor.h

/**@file     motor.h
* @brief     电机对应I/O口初始化
* @author    BROSY
* @date      2020年4月19日
* @version   V1.0
* @copyright CSU | BROSY
*******************************************************************************
* @par 修改日志:
* <table>
* <tr><th>Date        <th>Version  <th>Author    <th>Description
* <tr><td>2018/08/17  <td>1.0      <td>songqijin  <td>创建初始版本
* </table>
*******************************************************************************
*/
#ifndef __MOTOR_
#define __MOTOR_

/*===============================函数声明 ======================================*/
void MOTOR_Init(void); ///< 初始化电机对应I/O口 PA9, PA10
#endif

5. 备注

  1. PWM频率过高会导致电机发出蜂鸣声
  2. 电机转速较慢可能是因为GND接口没有接到一起
  3. 找不到头文件可能是因为没有设置包含路径

三、参考资料

B站视频:【正点原子】stm32f4视频教程(初级篇)
文字资料站:正点原子论坛


四、资料下载

分享链接PWM资料下载
密码:123456


喜欢搞事情、DIY、学技术的同学可以关注下面这个的公众号,了解更多有更趣的项目。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45780842/article/details/105660223