目錄(資料下載看最後)
源碼下載
分享鏈接:PWM資料下載
密碼:123456
一、PWM簡介
簡單來說,存在一個計數器,計數值隨時間進行週期性變化。最小值和最大值之間存在一個自定的值,當計數器的值小於自定值時,I/O輸出低電平,大於自定值則產生高電平。通過設置不同的最大值和自定值,可以控制I/O口輸出不同時間寬度的高低電平。
二、硬件部分
-
摘要
運用定時器調整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、學技術的同學可以關注下面這個的公衆號,瞭解更多有更趣的項目。