stm32系列基于专为要求高性能、低成本、低功耗的嵌入式应用专门设计的arm cortex-m3 内核。按性能分成两个不同的系列: stm32f103 “增强型”系列和stm32f101“基本型”系列。增强型系列时钟频率达到72mhz,是同类产品中性能最高的产品。
基本型时钟频率为36mhz,以16位产品的价格得到比16位产品大幅提升的性能,是16位产品用户的最佳选择。两个系列都内置32k到128k的闪存,不同的是sram的最大容量和外设接口的组合。时钟频率72mhz时,从闪存执行代码,stm32功耗36ma,是32位市场上功耗最低的产品。
脉冲宽度调制(pwm),是英文“pulse width modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。一般用来控制步进电机的速度等等。
stm32的定时器除了tim6和tim7之外,其他的定时器都可以用来产生pwm输出,其中高级定时器tim1和tim8可以同时产生7路的pwm输出,而通用定时器也能同时产生4路的pwm输出。
pwm输出介绍
pwm输出模式
stm32的pwm输出有两种模式,模式1和模式2,由timx_ccmrx寄存器中的ocxm位确定的(“110”为模式1,“111”为模式2)。模式1和模式2的区别如下:
110:pwm模式1-在向上计数时,一旦timx_cnt《timx_ccr1时通道1为有效电平,否则为无效电平;在向下计数时,一旦timx_cnt》timx_ccr1时通道1为无效电平(oc1ref=0),否则为有效电平(oc1ref=1)。
111:pwm模式2-在向上计数时,一旦timx_cnt《timx_ccr1时通道1为无效电平,否则为有效电平;在向下计数时,一旦timx_cnt》timx_ccr1时通道1为有效电平,否则为无效电平。
由此看来,模式1和模式2正好互补,互为相反,所以在运用起来差别也并不太大。
而从计数模式上来看,pwm也和timx在作定时器时一样,也有向上计数模式、向下计数模式和中心对齐模式,关于3种模式的具体资料,可以查看《stm32参考手册》的“14.3.9 pwm模式”一节,在此就不详细赘述了。
pwm输出管脚
pwm的输出管脚是确定好的,具体的引脚功能可以查看《stm32参考手册》的“8.3.7 定时器复用功能重映射”一节。在此需要强调的是,不同的timx有分配不同的引脚,但是考虑到管脚复用功能,stm32提出了一个重映像的概念,就是说通过设置某一些相关的寄存器,来使得在其他非原始指定的管脚上也能输出pwm。
但是这些重映像的管脚也是由参考手册给出的。比如说tim3的第2个通道,在没有重映像的时候,指定的管脚是pa.7,如果设置部分重映像之后,tim3_ch2的输出就被映射到pb.5上了,如果设置了完全重映像的话,tim3_ch2的输出就被映射到pc.7上了。
pwm输出信号
pwm输出的是一个方波信号,信号的频率是由timx的时钟频率和timx_arr预分频器所决定的,具体设置方法在前面一个学习笔记中有详细的交代。而输出信号的占空比则是由timx_crrx寄存器确定的。
其公式为“占空比=(timx_crrx/timx_arr)*100%”,因此,可以通过向crr中填入适当的数来输出自己所需的频率和占空比的方波信号。
timer输出pwm实现步骤
第1步、设置rcc时钟已经在前文中给出了详细的代码,在此就不再多说了。需要注意的是通用定时器timx是由apb1提供时钟,而gpio则是由apb2提供时钟。注意,如果需要对pwm的输出进行重映像的话,还需要开启引脚复用时钟afio。
第2步、设置gpio时钟时,gpio模式应该设置为复用推挽输出gpio_mode_af_pp,如果需要引脚重映像的话,则需要用gpio_pinremapconfig()函数进行设置。
第3步、设置timx定时器的相关寄存器时,和前一篇学习笔记一样,设置好相关的timx的时钟和技术模式等等。具体设置参看“timer基本定时功能”的学习笔记。
第4步、设置pwm相关寄存器,首先要设置pwm模式(默认情况下pwm是冻结的),然后设置占空比(根据前面所述公式进行计算),再设置输出比较极性:当设置为high时,输出信号不反相,当设置为low时,输出信号反相之后再输出。最重要是是要使能timx的输出状态和使能timx的pwm输出使能。
相关设置完成之后,就可以通过tim_cmd()来打开timx定时器,从而得到pwm输出了。
timer输出pwm源代码
由于我现在手上的奋斗开发板是将pb.5接到led上,因此需要使用tim3的ch2通道,并且要进行引脚重映像。打开tim3之后,pwm输出,使得led点亮,通过改变pwm_cfg()中的占空比可以调节led的亮度。
#include “stm32f10x_lib.h”
void rcc_cfg();
void gpio_cfg();
void timer_cfg();
void pwm_cfg();
//占空比,取值范围为0-100
int dutyfactor = 50;
int main()
{
int temp;
rcc_cfg();
gpio_cfg();
timer_cfg();
pwm_cfg();
//使能tim3计时器,开始输出pwm
tim_cmd(tim3, enable);
while(1);
}
void rcc_cfg()
{
//定义错误状态变量
errorstatus hsestartupstatus;
//将rcc寄存器重新设置为默认值
rcc_deinit();
//打开外部高速时钟晶振
rcc_hseconfig(rcc_hse_on);
//等待外部高速时钟晶振工作
hsestartupstatus = rcc_waitforhsestartup();
if(hsestartupstatus == success)
{
//设置ahb时钟(hclk)为系统时钟
rcc_hclkconfig(rcc_sysclk_div1);
//设置高速ahb时钟(apb2)为hclk时钟
rcc_pclk2config(rcc_hclk_div1);
//设置低速ahb时钟(apb1)为hclk的2分频
rcc_pclk1config(rcc_hclk_div2);
//设置flash代码延时
flash_setlatency(flash_latency_2);
//使能预取指缓存
flash_prefetchbuffercmd(flash_prefetchbuffer_enable);
//设置pll时钟,为hse的9倍频 8mhz * 9 = 72mhz
rcc_pllconfig(rcc_pllsource_hse_div1, rcc_pllmul_9);
//使能pll
rcc_pllcmd(enable);
//等待pll准备就绪
while(rcc_getflagstatus(rcc_flag_pllrdy) == reset);
//设置pll为系统时钟源
rcc_sysclkconfig(rcc_sysclksource_pllclk);
//判断pll是否是系统时钟
while(rcc_getsysclksource() != 0x08);
}
//开启tim3的时钟
rcc_apb1periphclockcmd(rcc_apb1periph_tim3,enable);
//开启gpiob的时钟和复用功能
rcc_apb2periphclockcmd(rcc_apb2periph_gpiob | rcc_apb2periph_afio,enable);
}
void gpio_cfg()
{
gpio_inittypedef gpio_initstructure;
/******初始化连接led的引脚pb5*************/
//部分映射,将tim3_ch2映射到pb5
//
gpio_pinremapconfig(gpio_fullremap_tim3, enable);
gpio_pinremapconfig(gpio_partialremap_tim3, enable);
//选择引脚5
gpio_initstructure.gpio_pin = gpio_pin_5;
//输出频率最大50mhz
gpio_initstructure.gpio_speed = gpio_speed_50mhz;
//复用推挽输出
gpio_initstructure.gpio_mode = gpio_mode_af_pp;
gpio_init(gpiob,&gpio_initstructure);
}
void timer_cfg()
{
tim_timebaseinittypedef tim_timebasestructure;
//重新将timer设置为缺省值
tim_deinit(tim3);
//采用内部时钟给tim3提供时钟源
tim_internalclockconfig(tim3);
//预分频系数为0,即不进行预分频,此时timer的频率为72mhz
tim_timebasestructure.tim_prescaler = 0;
//设置时钟分割
tim_timebasestructure.tim_clockdivision = tim_ckd_div1;
//设置计数器模式为向上计数模式
tim_timebasestructure.tim_countermode = tim_countermode_up;
//设置计数溢出大小,每计7200个数就产生一个更新事件,即pwm的输出频率为10khz
tim_timebasestructure.tim_period = 7200 - 1;
//将配置应用到tim3中
tim_timebaseinit(tim3,&tim_timebasestructure);
}
void pwm_cfg()
{
tim_ocinittypedef timocinitstructure;
//设置缺省值
tim_ocstructinit(&timocinitstructure);
//pwm模式1输出
timocinitstructure.tim_ocmode = tim_ocmode_pwm1;
//设置占空比,占空比=(ccrx/arr)*100%或(tim_pulse/tim_period)*100%
timocinitstructure.tim_pulse = dutyfactor * 7200 / 100;
//tim输出比较极性高
timocinitstructure.tim_ocpolarity = tim_ocpolarity_high;
//使能输出状态
timocinitstructure.tim_outputstate = tim_outputstate_enable;
//tim3的ch2输出
tim_oc2init(tim3, &timocinitstructure);
//设置tim3的pwm输出为使能
tim_ctrlpwmoutputs(tim3,enable);
}
三相变单相变压器问题探讨
Dialog支持WattUp无线充电技术,与Energous公司达成战略合作和投资关系
【技术篇F01】什么是汽车级电阻,都有哪些标准?
百信与华为携手推出百信AI科研云平台
四方光电:搭建完善的气体传感器技术平台,自主解决核心关键部件
STM32输出PWM
华为P10评测:对比华为P9、华为mate9,华为P10可谓是集万千宠爱于一身啊!
点阵字库的原理及与矢量字库的差别
UPS电池是什么?
电子芯闻早报:ARM推新芯片,骁龙820真来了
可穿戴EMS设备新型的学习形式 能缩小人类和机器人的距离
三极管的基础知识 放大电路的主要性能指标
电路基础知识分享之如何接好CAN的地?
设计模式行为型:中介模式
联通百度携手 混改方向引三大猜想
MODBUS转PROFIBUS网关YT-PB-03将仪表接入PROFIBUS的配制方法
余承东:最快今年秋天,最晚明年春天,华为自己的OS将可能面市
小米手表Color参数曝光内置420mAh电池支持GPS和GLONASS卫星定位
断路器的限流等级
苹果13pro人民币价格和开售时间