目錄
一、PWM驅(qū)動(dòng)LED呼吸燈(燈接在PA0)
1、PWM波和GPIO的對(duì)應(yīng)關(guān)系參考引腳定義表
2、計(jì)數(shù)器的計(jì)算
3、TIM輸出PWM波使用步驟?編輯
4、代碼
(1)輸出化比較單元
(2) PWM.c
(3)main.c
5、重映射更換成PA15亮燈
二、PWM驅(qū)動(dòng)舵機(jī)(舵機(jī)接在PA1、按鍵在PB1)?
1、電路圖
2、參數(shù)計(jì)算
3、代碼
(1) PWM.c修改的地方
(2)PWM.c完整代碼
(3)Servo.c
(4)main.c
三、PWM驅(qū)動(dòng)直流電機(jī)
1、原理圖
2、代碼
(1)PWM.c中改的地方
(2)Motor.c
(3)main.c
四、基礎(chǔ)知識(shí)
一、PWM驅(qū)動(dòng)LED呼吸燈(燈接在PA0)
1、PWM波和GPIO的對(duì)應(yīng)關(guān)系參考引腳定義表
(1)TIM2的引腳復(fù)用在了PA0引腳上,故要是要TIM2的OC1也就是CH1通道,輸出PWM,那它只能在PA0的引腳上輸出,而不能任意選擇引腳輸出
(2)同樣,若選擇 TIM2的是CH2通道,那只能在PA1端口輸出,以此類推
(3)但還是有一次重映射的機(jī)會(huì),可以在其他引腳上輸出?
2、計(jì)數(shù)器的計(jì)算
PWM的頻率=計(jì)數(shù)器的更新頻率
若要產(chǎn)生一個(gè)頻率為1kHz,占空比為50%,分辨率為1%的PWM波形
帶入公式:72M/(PSC+1)/(ARR+1)=1000
? ? ? ? ? ? ? ? ? CCR/(ARR+1) = 50%
? ? ? ? ? ? ? ? ? 1/(ARR+1)=1%
則計(jì)算出:ARR+1=100,CCR=50,PSC+1=720?
則等以1kHZ的頻率閃爍,但是我們看不出來
?? ?TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;?? ??? ?//ARR
?? ?TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;?? ??? ?//PSC
?? ?TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
3、TIM輸出PWM波使用步驟
第一步:RCC開啟時(shí)鐘,打開TIM外設(shè)和GPIO外設(shè)的時(shí)鐘
第二步:配置時(shí)基單元,包括時(shí)基單元和時(shí)基單元前的時(shí)鐘源選擇
第三步:配置輸出比較單元,里面包括CCR的值、輸出比較模式、極性選擇、輸出使能(結(jié)構(gòu)體配置)
第四步:配置GPIO口,初始化為復(fù)用推挽輸出的配置
第五步:運(yùn)行控制,啟動(dòng)計(jì)數(shù)器,就能輸出PWM波
4、代碼
(1)輸出化比較單元
TIM_OCInitTypeDef TIM_OCInitStructure;//定義結(jié)構(gòu)體
TIM_OCStructInit(&TIM_OCInitStructure);//初始化所有結(jié)構(gòu)題
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//設(shè)置輸出比較的模式
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//設(shè)置比較的極性
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//設(shè)置輸出使能
TIM_OCInitStructure.TIM_Pulse = 0; //設(shè)置CCR的值0-ffff
TIM_OC1Init(TIM2, &TIM_OCInitStructure);//用結(jié)構(gòu)體初始化
(2) PWM.c
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
// GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
//對(duì)于普通的開漏推挽輸出,引腳的控制權(quán)是來自于輸出數(shù)據(jù)寄存器,
//若想要定時(shí)器控制引腳,需要使用復(fù)用開漏/推挽輸出的模式
//此時(shí),輸出數(shù)據(jù)寄存器將被斷開,輸出控制權(quán)將轉(zhuǎn)移到片上外設(shè)
//本實(shí)驗(yàn)中片上外設(shè)引腳連接的就是TIM2的CH1通道,所以只有把GPIO設(shè)置程復(fù)用推挽輸出
//引腳的控制權(quán)才能交給片上外設(shè),PWM波形才能通過引腳輸出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//時(shí)基單元初始化
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
//初始化輸出比較單元
//PA0口對(duì)應(yīng)1通道
TIM_OCInitTypeDef TIM_OCInitStructure;
//不想把所有成員都列出來賦一個(gè)初始值,就用TIM_OCStructInit初始化值,防止出現(xiàn)奇怪的錯(cuò)誤
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式1和PWM模式2
//輸出比較極性:
//TIM_OCPolarity_High高級(jí)性,就是極性不翻轉(zhuǎn),REF波形直接輸出,或者說有效電平是高電平
//TIM_OCPolarity_Low低極性,就是REF波形電平取反,有效電平為低電平
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; //設(shè)置CCR的值0-ffff
TIM_OC1Init(TIM2, &TIM_OCInitStructure);//用結(jié)構(gòu)體初始化
TIM_Cmd(TIM2, ENABLE);//啟動(dòng)定時(shí)器
}
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2, Compare);//設(shè)置占空比
}
(3)main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
uint8_t i;
int main(void)
{
OLED_Init();
PWM_Init();
while (1)
{
for (i = 0; i <= 100; i++)
{
PWM_SetCompare1(i);//更改占空比的函數(shù)
Delay_ms(10);
}
for (i = 0; i <= 100; i++)
{
PWM_SetCompare1(100 - i);
Delay_ms(10);
}
}
}
5、重映射更換成PA15亮燈
?想要把PA0改成PA15,就可以選重映射方式1或者完全重映射
在"GPIO_InitTypeDef GPIO_InitStructure;"前面添加
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);? ? ? ? ? ? ? (1)
GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);? ? ? ? ? ? ? ? ? ? (2)
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE)? ? ? ? ? ?(3)
PA15是調(diào)試端口,所以要解除調(diào)試端口?GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE)
- 若想要讓PA15、PB3、PB4這三個(gè)引腳當(dāng)作普通GPIO來使用,則加第一、三句,打開AFIO時(shí)鐘,讓AFIO時(shí)鐘將JTAG復(fù)用解除掉
- 如果想要重映射定時(shí)器或者其他外設(shè)的復(fù)用引腳,加第一句和第二句,就要先打開AFIO時(shí)鐘,再用AFIO重映射外設(shè)復(fù)用的引腳,
- 若重映射的引腳正好是調(diào)試端口,則三句全加上
改變引腳:
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
改為
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
此時(shí)PA0的燈不亮,而PA15的燈亮了
二、PWM驅(qū)動(dòng)舵機(jī)(舵機(jī)接在PA1、按鍵在PB1)?
1、電路圖
2、參數(shù)計(jì)算
- 舵機(jī)要求的頻率:20ms,故為50Hz
- 占空比:舵機(jī)要求高電平時(shí)間是0.5ms~2.5ms
- 計(jì)算出來的PSC和ARR不固定
- 測試PSC+1=72,ARR+1=20k時(shí)比較方便,此時(shí),CCR=500,則0.5ms,CCR=2500,則2.5ms
- CCR=500,0度,CRR=2500,180度
3、代碼
(1) PWM.c修改的地方
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC
void PWM_SetCompare2(uint16_t Compare)//從通道1改為使用通道2
{
TIM_SetCompare2(TIM2, Compare);
}
(2)PWM.c完整代碼
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; //CCR
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE);
}
void PWM_SetCompare2(uint16_t Compare)//使用通道2
{
TIM_SetCompare2(TIM2, Compare);
}
(3)Servo.c
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Servo_Init(void)
{
PWM_Init();
}
void Servo_SetAngle(float Angle)
{
PWM_SetCompare2(Angle / 180 * 2000 + 500);
}
(4)main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include "Key.h"
uint8_t KeyNum;
float Angle;
int main(void)
{
OLED_Init();
Servo_Init();
Key_Init();
OLED_ShowString(1, 1, "Angle:");
while (1)
{
KeyNum = Key_GetNum();
if (KeyNum == 1)
{
Angle += 30;
if (Angle > 180)
{
Angle = 0;
}
}
Servo_SetAngle(Angle);
OLED_ShowNum(1, 7, Angle, 3);
}
}
三、PWM驅(qū)動(dòng)直流電機(jī)
1、原理圖
- ?紅色的是TB6612電機(jī)驅(qū)動(dòng)模塊
- 連接電機(jī)的兩根線不分正反,對(duì)調(diào)知識(shí)反過來轉(zhuǎn)動(dòng),AIN1和AIN2是方向控制,任意連接兩個(gè)GPIO就行(此處接PA4、PA5),PWMA是速度控制,需要接PWM的輸出腳(PA2,PA2對(duì)應(yīng)的是TIM2的通道3,到時(shí)候初始化通道三即可)
2、代碼
(1)PWM.c中改的地方
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//(0改為2)
TIM_OC3Init(TIM2, &TIM_OCInitStructure);//(1改為3)
TIM_TimeBaseInitStructure.TIM_Period = 1000 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC
//改頻率,將1kHZ改為20kHz
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1; //PSC
void PWM_SetCompare3(uint16_t Compare)//(1改為3)
{
TIM_SetCompare3(TIM2, Compare);
}
(2)Motor.c
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Motor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
PWM_Init();
}
void Motor_SetSpeed(int8_t Speed)
{
if (Speed >= 0)//正轉(zhuǎn)
{
GPIO_SetBits(GPIOA, GPIO_Pin_4);
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
PWM_SetCompare3(Speed);
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_4);//反轉(zhuǎn)
GPIO_SetBits(GPIOA, GPIO_Pin_5);
PWM_SetCompare3(-Speed);
}
}
(3)main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Motor.h"
#include "Key.h"
uint8_t KeyNum;
int8_t Speed;
int main(void)
{
OLED_Init();
Motor_Init();
Key_Init();
OLED_ShowString(1, 1, "Speed:");
while (1)
{
KeyNum = Key_GetNum();
if (KeyNum == 1)
{
Speed += 20;
if (Speed > 100)
{
Speed = -100;
}
}
Motor_SetSpeed(Speed);
OLED_ShowSignedNum(1, 7, Speed, 3);
}
}
四、基礎(chǔ)知識(shí)
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState)文章來源:http://www.zghlxwxcb.cn/news/detail-627285.html
僅高級(jí)定時(shí)器使用,在使用高級(jí)定時(shí)器輸出PWM時(shí),需要調(diào)用這個(gè)函數(shù),使能主輸出,否則PWM將不能正常輸出文章來源地址http://www.zghlxwxcb.cn/news/detail-627285.html
到了這里,關(guān)于10、江科大stm32視頻學(xué)習(xí)筆記——PWM驅(qū)動(dòng)led呼吸燈、驅(qū)動(dòng)舵機(jī)、驅(qū)動(dòng)直流機(jī)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!