目录(资料下载看最后)
源码下载
分享链接:PWM资料下载
密码:123456
一、PWM简介
简单来说,存在一个计数器,计数值随时间进行周期性变化。最小值和最大值之间存在一个自定的值,当计数器的值小于自定值时,I/O输出低电平,大于自定值则产生高电平。通过设置不同的最大值和自定值,可以控制I/O口输出不同时间宽度的高低电平。
图1.1 来自百度百科
二、硬件部分
-
摘要
运用定时器调整PWM输出值,使直流电机从慢到快,再从快到慢。 -
硬件设备:
名称 | 型号 | 数量 |
---|---|---|
STM32开发板 | STM32F407ZGT6 | 1 |
电机驱动 | L298N | 1 |
电机 | 普通直流 | 1 |
电池 | 9V锂电池 | 1 |
导线 | 杜邦线 | 若干 |
- 硬件连接
- (STM32) PA9-------IN1 (L298N)
- (STM32) PA10------IN2 (L298N)
- (STM32) PF9-------ENA (L298N)
- 直流电机------OUT1, OUT2 (L298N)
- 9V电池------12V、GND(L298N)
备注:
- 所有GND接口都应接在一起,不然会出现电机转动异常。
- L298N的12V口接输入电源(5V~12V均可)
- L298N的5V口接单片机5V口,用于给单片机供电
- 拔掉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. 备注
- PWM频率过高会导致电机发出蜂鸣声
- 电机转速较慢可能是因为GND接口没有接到一起
- 找不到头文件可能是因为没有设置包含路径
三、参考资料
B站视频:【正点原子】stm32f4视频教程(初级篇)
文字资料站:正点原子论坛
四、资料下载
分享链接:PWM资料下载
密码:123456
喜欢搞事情、DIY、学技术的同学可以关注下面这个的公众号,了解更多有更趣的项目。