如何采用STM32单片机产生PWM

stm32产生pwm是非常的方便的,要需要简单的设置定时器,即刻产生!
(1)使能定时器时钟:rcc_apb1periphclockcmd(rcc_apb1periph_tim3, enable);
(2)定义相应的gpio:
/* pa2,3,4,5,6输出-》key_up,key_down,key_left,key_right,key_ctrl */
gpio_initstructure.gpio_pin = gpio_pin_2|gpio_pin_3|gpio_pin_4|gpio_pin_5|gpio_pin_6;
gpio_initstructure.gpio_mode = gpio_mode_ipu; //下拉接地,检测输入的高电平
gpio_initstructure.gpio_speed = gpio_speed_50mhz; //50m时钟速度
gpio_init(gpioa, &gpio_initstructure);
/* pa7用于发出pwm波 */
gpio_initstructure.gpio_pin = gpio_pin_7;
gpio_initstructure.gpio_mode = gpio_mode_af_pp;gpio_initstructure.gpio_speed = gpio_speed_50mhz; //50m时钟速度
gpio_init(gpioa, &gpio_initstructure);
(3)如果是产生pwm(频率不变,占空比可变),记得打开pwm控制,在tim_configuration()中。
tim_cmd(tim3,enable);
/* tim1 main output enable */
tim_ctrlpwmoutputs(tim1,enable);
利用定时器产生不同频率的pwm有时候,需要产生不同频率的pwm,这个时候,设置与产生相同pwm的程序,有关键的不一样。
(一) 设置的原理
利用改变定时器输出比较通道的捕获值,当输出通道捕获值产生中断时,在中断中将捕获值改变,这时, 输出的i/o会产生一个电平翻转,利用这种办法,实现不同频率的pwm输出。
(二)关键设置
在定时器设置中:tim_oc2preloadconfig(tim3, tim_ocpreload_disable);
在中断函数中:
if (tim_getitstatus(tim3, tim_it_cc2) != reset)
{
tim_clearitpendingbit(tim3, tim_it_cc2);
capture = tim_getcapture2(tim3);
tim_setcompare2(tim3, capture + key_value);
}
一个定时器四个通道,分别产生不同频率(这个例子网上也有)
vu16 ccr1_val = 32768;
vu16 ccr2_val = 16384;
vu16 ccr3_val = 8192;
vu16 ccr4_val = 4096;
void tim_configuration(void)
{
tim_timebaseinittypedef tim_timebasestructure;
tim_ocinittypedef tim_ocinitstructure;
/* tim2 clock enable */
rcc_apb1periphclockcmd(rcc_apb1periph_tim2, enable);
/* ---------------------------------------------------------------
tim2 configuration: output compare toggle mode:
tim2clk = 36 mhz, prescaler = 0x2, tim2 counter clock = 12 mhz
cc1 update rate = tim2 counter clock / ccr1_val = 366.2 hz
cc2 update rate = tim2 counter clock / ccr2_val = 732.4 hz
cc3 update rate = tim2 counter clock / ccr3_val = 1464.8 hz
cc4 update rate = tim2 counter clock / ccr4_val = 2929.6 hz
--------------------------------------------------------------- */
/* time base configuration */
tim_timebasestructure.tim_period = 65535;
tim_timebasestructure.tim_prescaler = 2;
tim_timebasestructure.tim_clockdivision = 0;
tim_timebasestructure.tim_countermode = tim_countermode_up;
tim_timebaseinit(tim2, &tim_timebasestructure);
/* channel 1 configuration in pwm mode */
tim_ocinitstructure.tim_ocmode = tim_ocmode_toggle; //pwm模式2
tim_ocinitstructure.tim_outputstate = tim_outputstate_enable; //正向通道有效
tim_ocinitstructure.tim_outputnstate = tim_outputnstate_disable;//反向通道无效
tim_ocinitstructure.tim_pulse = ccr1_val;//占空时间
tim_ocinitstructure.tim_ocpolarity = tim_ocpolarity_low; //输出极性
tim_ocinitstructure.tim_ocnpolarity = tim_ocnpolarity_high; //互补端的极性
tim_ocinitstructure.tim_ocidlestate = tim_ocidlestate_set;
tim_ocinitstructure.tim_ocnidlestate = tim_ocidlestate_reset;
tim_oc1init(tim2,&tim_ocinitstructure); //通道1
tim_oc1preloadconfig(tim2, tim_ocpreload_disable);
tim_ocinitstructure.tim_pulse = ccr2_val; //占空时间
tim_oc2init(tim2,&tim_ocinitstructure);//通道2
tim_oc2preloadconfig(tim2, tim_ocpreload_disable);
tim_ocinitstructure.tim_pulse = ccr3_val; //占空时间
tim_oc3init(tim2,&tim_ocinitstructure); //通道3
tim_oc3preloadconfig(tim2, tim_ocpreload_disable);
tim_ocinitstructure.tim_pulse = ccr4_val; //占空时间
tim_oc4init(tim2,&tim_ocinitstructure);//通道4
tim_oc4preloadconfig(tim2, tim_ocpreload_disable);
/* tim2 counter enable */
tim_cmd(tim2,enable);
/* tim2 main output enable */
//tim_ctrlpwmoutputs(tim2,enable);
/* tim it enable */
tim_itconfig(tim2, tim_it_cc1 | tim_it_cc2 | tim_it_cc3 | tim_it_cc4, enable);
}
void gpio_configuration(void)
{
gpio_inittypedef gpio_initstructure;
/*允许总线clock,在使用gpio之前必须允许相应端的时钟。
从stm32的设计角度上说,没被允许的端将不接入时钟,也就不会耗能,
这是stm32节能的一种技巧,*/
rcc_apb2periphclockcmd(rcc_apb2periph_gpioa, enable);
rcc_apb2periphclockcmd(rcc_apb2periph_gpiob, enable);
rcc_apb2periphclockcmd(rcc_apb2periph_gpioc, enable);
rcc_apb2periphclockcmd(rcc_apb2periph_gpiod, enable);
/* pa2,3,4,5,6,7输出-》led1,led2,led3,led4,led5,led6 */
gpio_initstructure.gpio_pin = gpio_pin_2|gpio_pin_3|gpio_pin_4|gpio_pin_5|gpio_pin_6|gpio_pin_7;
gpio_initstructure.gpio_mode = gpio_mode_out_od; //开漏输出
gpio_initstructure.gpio_speed = gpio_speed_50mhz; //50m时钟速度
gpio_init(gpioa, &gpio_initstructure);
/* pb0,1输出-》led7,led8*/
gpio_initstructure.gpio_pin = gpio_pin_0|gpio_pin_1;
gpio_initstructure.gpio_mode = gpio_mode_out_od; //开漏输出
gpio_initstructure.gpio_speed = gpio_speed_50mhz; //50m时钟速度
gpio_init(gpiob, &gpio_initstructure);
/* pa0,1-》key_left,key_right*/
gpio_initstructure.gpio_pin = gpio_pin_0|gpio_pin_1;
gpio_initstructure.gpio_mode = gpio_mode_ipu;? //上拉输入
gpio_init(gpioa, &gpio_initstructure);
/* pc13-》key_up*/
gpio_initstructure.gpio_pin = gpio_pin_13;
gpio_initstructure.gpio_mode = gpio_mode_ipu;? //上拉输入
gpio_init(gpioc, &gpio_initstructure);
/* pb5-》key_down*/
gpio_initstructure.gpio_pin = gpio_pin_5;
gpio_initstructure.gpio_mode = gpio_mode_ipu;? //上拉输入
gpio_init(gpiob, &gpio_initstructure);
/* gpioa configuration:tim2 channel1, 2, 3 and 4 in output */
gpio_initstructure.gpio_pin = gpio_pin_0 | gpio_pin_1 | gpio_pin_2 | gpio_pin_3;
gpio_initstructure.gpio_mode = gpio_mode_af_pp;
gpio_initstructure.gpio_speed = gpio_speed_50mhz;
gpio_init(gpioa, &gpio_initstructure);
}
void nvic_configuration(void)
{
nvic_inittypedef nvic_initstructure;
/* configure one bit for preemption priority */
nvic_prioritygroupconfig(nvic_prioritygroup_1);
nvic_initstructure.nvic_irqchannel=tim2_irqn;
nvic_initstructure.nvic_irqchannelpreemptionpriority=0;
nvic_initstructure.nvic_irqchannelsubpriority=1;
nvic_initstructure.nvic_irqchannelcmd=enable;
nvic_init(&nvic_initstructure);
}
u16 capture = 0;
extern vu16 ccr1_val;
extern vu16 ccr2_val;
extern vu16 ccr3_val;
extern vu16 ccr4_val;
void tim2_irqhandler(void)
{
/* tim2_ch1 toggling with frequency = 183.1 hz */
if (tim_getitstatus(tim2, tim_it_cc1) != reset)
{
tim_clearitpendingbit(tim2, tim_it_cc1 );
capture = tim_getcapture1(tim2);
tim_setcompare1(tim2, capture + ccr1_val );
}
/* tim2_ch2 toggling with frequency = 366.2 hz */
if (tim_getitstatus(tim2, tim_it_cc2) != reset)
{
tim_clearitpendingbit(tim2, tim_it_cc2);
capture = tim_getcapture2(tim2);
tim_setcompare2(tim2, capture + ccr2_val);
}
/* tim2_ch3 toggling with frequency = 732.4 hz */
if (tim_getitstatus(tim2, tim_it_cc3) != reset)
{
tim_clearitpendingbit(tim2, tim_it_cc3);
capture = tim_getcapture3(tim2);
tim_setcompare3(tim2, capture + ccr3_val);
}
/* tim2_ch4 toggling with frequency = 1464.8 hz */
if (tim_getitstatus(tim2, tim_it_cc4) != reset)
{
tim_clearitpendingbit(tim2, tim_it_cc4);
capture = tim_getcapture4(tim2);
tim_setcompare4(tim2, capture + ccr4_val);
}
}
一个定时器一个通道,产生不同频率
其它的设置都一样,就是在主函数中修改一个参数,然后在定时器中断中,根据这个参数,改变频率。
#include “stm32lib\\stm32f10x.h”
#include “hal.h”
volatile u16 key_value=1000;? //用于保存按键相应的pwm波占空比值
int main(void)
{
chiphalinit();
chipouthalinit();
while(1)
{?
? if( (!get_key_up)&(!get_key_down)&(!get_key_left)&(!get_key_right)&(!get_key_ctrl) )
? {
? ? key_value=12000;
? }
? else
? {
? ? if(get_key_up)? ? //按键前进按下 ,对应1khz
? ? {
? ? key_value=6000;
? ? }
? ? else if(get_key_down)? //按键后退按下 ,对应2khz
? ? {
? ? ? key_value=3000;
? ? }
? ? delay_ms(20);? ? ? //10ms延时
? ? if(get_key_left)? ? //按键左转按下,对应3khz
? ? {
? ? key_value=2000;
? ? }
? ? else if(get_key_right) //按键右转按下,对应4khz
? ? {
? ? ? key_value=1500;
? ? }?
? ? delay_ms(20);? ? ? //10ms延时
? ? if(get_key_ctrl)? ? //按键控制按下,对应5khz
? ? {
? ? ? key_value=1200;
? ? }
? ? delay_ms(20);? ? ? //10ms延时
? }
}
}
extern volatile u16 key_value;
u16 capture=0;
void tim3_irqhandler(void)
{
/* tim2_ch2 toggling with frequency = 366.2 hz */
if (tim_getitstatus(tim3, tim_it_cc2) != reset)
{
? ? tim_clearitpendingbit(tim3, tim_it_cc2);
capture = tim_getcapture2(tim3);
? ? tim_setcompare2(tim3, capture + key_value);
}
}
void tim3_configuration(void)
{
tim_timebaseinittypedef tim_timebasestructure;
tim_ocinittypedef tim_ocinitstructure;
/* tim2 clock enable */
rcc_apb1periphclockcmd(rcc_apb1periph_tim3, enable);
/*tim1时钟配置*/
tim_timebasestructure.tim_prescaler = 5;? ? ? //预分频(时钟分频)72m/6=12m
tim_timebasestructure.tim_countermode = tim_countermode_up;? //向上计数
tim_timebasestructure.tim_period = 65535;? ? ? ? //装载值选择最大
tim_timebasestructure.tim_clockdivision = tim_ckd_div1;
tim_timebasestructure.tim_repetitioncounter = 0x0;
tim_timebaseinit(tim3,&tim_timebasestructure);
/* channel 1 configuration in pwm mode */
tim_ocinitstructure.tim_ocmode = tim_ocmode_toggle; //pwm模式2
tim_ocinitstructure.tim_outputstate = tim_outputstate_enable; //正向通道有效
tim_ocinitstructure.tim_outputnstate = tim_outputnstate_disable;//反向通道无效
tim_ocinitstructure.tim_pulse = key_value; //占空时间
tim_ocinitstructure.tim_ocpolarity = tim_ocpolarity_low; //输出极性
tim_ocinitstruct

3D打印电力风车,未来将应用于海岸发电
人工智能的前世今生:三起两落,几经波折
蓝光激光焊接机在焊接发卡电机的行业应用
CPLD和FPGA两者的区别
车载毫米波雷达产业链大盘点
如何采用STM32单片机产生PWM
英睿达P2上架 250GB连续读取速度最大2100MB/s
Marvell“四驾马车”并驱,开拓LED智能照明未来
智能家居领域ZigBee协议为何备受青睐?
一种反激同步整流DC-DC变换器设计
基于大功率三电平IGBT模块并联的参考设计
激光打印机的优缺点
共建开放,共享未来!OpenHarmony安全委员会亮相2023开放原子全球开源峰会
防过电压放大器输出保护电路
如何离线运行pulp代码?
中兴通讯:新导入的5nm芯片技术
BBA真正的白热化较量 仅存于宝马5系L和奥迪A6L之间
Mouser备货Amphenol Commercial 高性能USB Type-C连接器
ASIC与FPGA的最大区别是什么 可否相互替代
2019年小米和OPPO在屏幕指纹识别技术上都更进了一步