板子:野火指南者
芯片:STM32f103VET6
PWM通道:TIM3的通道1和通道3
GPIO:PA6和PB0
前言
本文主要講需要怎么做,簡要講解原理,提供全部代碼,有利于快速上手。
一、PWM輸出1kHz方波的實現(xiàn)
1.選一個可以輸出PWM的GPIO
打開STM32f103VET6的芯片數(shù)據(jù)手冊,打開目錄Pinouts and pindescriptions——High-density STM32F103xC/D/E pin definitions,如圖所示。
這里選擇可以復(fù)用為TIM3通道1的PA6,如圖所示。
2.寫代碼:初始化GPIO
打開GPIOA的時鐘和復(fù)用時鐘,初始化PA6為復(fù)用推挽輸出。
static void TIM3_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);//打開GPIO時鐘和復(fù)用時鐘
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //配置為復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
3.配置定時器模式
簡要介紹一下部分參數(shù)。
首先是時基初始化結(jié)構(gòu)體的TIM_Period,它代表定時器的計數(shù)周期,即時鐘跳動多少次后溢出,這里賦值為1000-1。
其次是時基初始化結(jié)構(gòu)體的TIM_Prescaler,它代表定時器的預(yù)分頻系數(shù),定時器的時鐘是72MHz,所以這里填72-1,所以TIM3的時鐘為72÷72=1MHz,時鐘周期為10-6s,那么一個計數(shù)周期需要10-6x1000=10-3s,即頻率為103Hz=1kHz。
最后是輸出比較初始化結(jié)構(gòu)體的TIM_Pulse,它代表比較值,在PWM模式1下,當(dāng)定時器的計數(shù)值小于比較值時輸出有效電平,例程中有效電平是低電平(TIM_OCPolarity_Low),這里設(shè)置比較值為500,而定時器的計數(shù)周期為1000,當(dāng)計數(shù)值小于比較值500時輸出低電平,大于500時輸出高電平,而計數(shù)周期為10-3s,因此生成了頻率為1kHz、占空比為50%的方波。
static void TIM3_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = (1000-1); //當(dāng)定時器從0計數(shù)到 TIM_Period+1 ,為一個定時周期
TIM_TimeBaseStructure.TIM_Prescaler = (72-1); //設(shè)置預(yù)分頻
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ; //設(shè)置時鐘分頻系數(shù):不分頻(這里用不到)
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計數(shù)模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //配置為PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能輸出
TIM_OCInitStructure.TIM_Pulse = 500; //設(shè)置初始PWM脈沖寬度為0
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //當(dāng)定時器計數(shù)值小于比較值時為低電平
TIM_OC1Init ( TIM3, &TIM_OCInitStructure ); //使能通道,通道幾就是OCx,例如通道2就是TIM_OC2Init
TIM_OC1PreloadConfig ( TIM3, TIM_OCPreload_Enable ); //使能預(yù)裝載
TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIM重載寄存器ARR
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
}
4.下載程序觀察現(xiàn)象
二、呼吸燈的實現(xiàn)
如果我們用PWM來控制LED,在一段波形中高電平占比越多,人眼看到LED就越亮,我們只要不停的改變高電平的占比,LED就會一會變亮一會變暗,就形成了呼吸燈。呼吸燈的編程要點就是使用定時器中斷,實現(xiàn)每隔一定時間就進入中斷改變PWM的比較值,使輸出波形占空比不斷變化。
這里我們選擇可以復(fù)用為TIM3的通道3的PB0控制LED。
1.計算獲取PWM數(shù)據(jù)表
既然要在中斷里經(jīng)常改變PWM的占空比,總不可能實時計算吧,肯定需要提前計算好放入STM32中,需要時直接調(diào)用即可,我們可以采樣在[0,10)范圍下的2x和(10,20)2(20-x),在函數(shù)上取100個點。
編寫c語言函數(shù)如下。
#include <stdio.h>
#include <math.h>
int main()
{
float i = 0;
int indexWave[100], x=0;
for(i=0;i<10;i+=0.2)
{
indexWave[x++]=(int)(pow(2,i));
}
for (x=0;x<=50;x++)
{
printf("%d, ", indexWave[x]);
}
printf("\r\n");
x=50;
for(i=10;i<20;i+=0.2)
{
indexWave[x++]=(int)(pow(2,(20-i)));
}
for (x=51;x<100;x++)
{
printf("%d, ", indexWave[x]);
}
return 0;
}
將打印出來的數(shù)據(jù)存入STM32。
2.初始化GPIO
同上
static void TIM3_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
3.配置NVIC
NVIC_InitTypeDef NVIC_Initstructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_Initstructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_Initstructure.NVIC_IRQChannelSubPriority = 2;
NVIC_Initstructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_Initstructure);
4.配置TIM3模式
TIM_Period配置為1024-1,與PWM數(shù)據(jù)最大值相同。文章來源:http://www.zghlxwxcb.cn/news/detail-755687.html
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = (1024-1); //當(dāng)定時器從0計數(shù)到 TIM_Period+1 ,為一個定時周期
TIM_TimeBaseStructure.TIM_Prescaler = (72-1); //設(shè)置預(yù)分頻
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ; //設(shè)置時鐘分頻系數(shù):不分頻(這里用不到)
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計數(shù)模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //配置為PWM模式1,CNT比比較值小為有效電平
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能輸出
TIM_OCInitStructure.TIM_Pulse = 500; //設(shè)置初始PWM脈沖寬度為0
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //當(dāng)定時器計數(shù)值小于比較值時為低電平
TIM_OC3Init ( TIM3, &TIM_OCInitStructure ); //使能通道, 通道幾就是OCx,例如通道2就是 TIM_OC2Init
TIM_OC3PreloadConfig ( TIM3, TIM_OCPreload_Enable ); //使能預(yù)裝載
TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIM重載寄存器ARR
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM3_NVIC_Config();
總結(jié)
完整工程連接:百度網(wǎng)盤下載鏈接文章來源地址http://www.zghlxwxcb.cn/news/detail-755687.html
到了這里,關(guān)于STM32實現(xiàn)PWM輸出頻率1kHz占空比50%的方波和呼吸燈的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!