历史上的今天
返回首页

历史上的今天

今天是:2025年06月17日(星期二)

正在发生

2020年06月17日 | STM32F103 实验 PWM输出

2020-06-17 来源:eefocus

正文


实验目的

使用TIM3的通道2,把通道2重映射到PB5,产生PWM来控制DS0的亮度


实验内容

脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用 微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽 度的控制。


STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定 时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4 路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出!


要使 STM32 的通用定时器 TIMx 产生 PWM 输出,除了上一章介绍的寄存器外,我们还会 用到 另外3 个寄存器。


寄存器

捕获/比较模式寄存器(TIMx_CCMR1/2)

TIMx_CCMR1 控制 CH1 和 2,而 TIMx_CCMR2 控制 CH3 和 4。

在这里插入图片描述

上面一层对应输出而下面的则对应输入。。这里我们需要说明的是模式设置位 OCxM,此部分由 3 位组成。 总共可以配置成 7 种模式,我们使用的是 PWM 模式,所以这 3 位必须设置为 110/111。这两种 PWM 模式的区别就是输出电平的极性相反。


捕获/比较使能寄存器(TIMx_CCER)


该寄存器比较简单,我们这里只用到了 CC2E 位,该位是输入/捕获 2 输出使能位,要想 PWM 从 IO 口输出,这个位必须设置为 1,所以我们需要设置该位为 1。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

捕获/比较寄存器(TIMx_CCR1~4)

在这里插入图片描述

该寄存器总共有 4 个,对应 4 个 输通道 CH1~4。下面以CCR1为例

在这里插入图片描述

在输出模式下,该寄存器的值与 CNT 的值比较,根据比较结果产生相应动作。利用这点, 我们通过修改这个寄存器的值,就可以控制 PWM 的输出脉宽了。

在这里插入图片描述

我们要利用 TIM3 的 CH2 输出 PWM 来控制 DS0 的亮度,但是 TIM3_CH2 默认是接在 PA7 上面的,而我们的 DS0 接在 PB5 上面,如果普通 MCU,可能就只能用飞线把 PA7 飞到 PB5 上来实现了,不过,我们用的是 STM32,它比较高级,可以通过重映射功能,把 TIM3_CH2 映射到 PB5 上。


复用重映射和调试 IO 配置寄存器(AFIO_MAPR)


我们这里用到的是 TIM3 的重映射,从上图可以看出,TIM3_REMAP 是由[11:10]这 2 个位 控制的。

在这里插入图片描述

默认条件下,TIM3_REMAP[1:0]为 00,是没有重映射的,所以 TIM3_CH1~TIM3_CH4 分 别是接在 PA6、PA7、PB0 和 PB1 上的,而我们想让 TIM3_CH2 映射到 PB5 上,则需要设置 TIM3_REMAP[1:0]=10,即部分重映射,这里需要注意,此时 TIM3_CH1 也被映射到 PB4 上了。


相关步骤

1) 开启TIM3时钟以及复用功能时钟,配置PB5为复用输出


RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器 3 时钟 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  //复用时钟使能

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输


2) 设置TIM3_CH2重映射到PB5上


GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //第一个 入口参数可以理解为设置重映射的类型

//TIM3 部分重映射入口参数为 GPIO_PartialRemap_TIM3


3) 初始化 TIM3,设置 TIM3 的 ARR 和 PSC


在开启了 TIM3 的时钟之后,我们要设置 ARR 和 PSC 两个寄存器的值来控制输出 PWM 的 周期。


TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载

TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 

TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim 

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式 

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的 


4) 设置 TIM3_CH2 的 PWM 模式,使能 TIM3 的 CH2 输出


通过配置 TIM3_CCMR1 的相关位来控制 TIM3_CH2 的模式。在库函数中,PWM 通道设 置是通过函数 TIM_OC1Init()~TIM_OC4Init()来设置的,不同的通道的设置函数不一样,这里我 们使用的是通道 2,所以使用的函数是 TIM_OC2Init()。


void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); 

typedef struct {   

uint16_t TIM_OCMode; //设置模式是 PWM 还是输出比较,这里我们是 PWM 模式,TIM_OCMode_PWM2

uint16_t TIM_OutputState; //比较输出使能,也就是使能 PWM 输出到端口。 TIM_OutputState_Enable

uint16_t TIM_OutputNState; */   

uint16_t TIM_Pulse;            

uint16_t TIM_OCPolarity;       //设置极性是高还是低,TIM_OCPolarity_High

uint16_t TIM_OCNPolarity;      

uint16_t TIM_OCIdleState;     

uint16_t TIM_OCNIdleState;   //其他参数是高级定时器TIM1和TIM8才会用到

} TIM_OCInitTypeDef; 


5) 使能 TIM3


TIM_Cmd(TIM3, ENABLE);  //使能 TIM3 


6) 修改 TIM3_CCR2 来控制占空比


最后,在经过以上设置之后,PWM 其实已经开始输出了,只是其占空比和频率都是固定 的,而我们通过修改 TIM3_CCR2 则可以控制 CH2 的输出占空比。继而控制 DS0 的亮度。

修改 TIM3_CCR2 占空比的函数是:


void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);

在这里插入图片描述

相关代码

#include "led.h"

#include "delay.h"

#include "key.h"

#include "sys.h"

#include "usart.h"

#include "timer.h"

 

int main(void)

{

u16 led0pwmval=0;

u8 dir=1;

delay_init();     //延时函数初始化   

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级

uart_init(115200); //串口初始化为115200

LED_Init();      //LED端口初始化

TIM3_PWM_Init(899,0); //不分频。PWM频率=72000000/900=80Khz,周期的倒数

while(1)

{

delay_ms(10);  

if(dir)led0pwmval++;

else led0pwmval--;


if(led0pwmval>300)dir=0;

if(led0pwmval==0)dir=1;  

TIM_SetCompare2(TIM3,led0pwmval);    

}  

}

void TIM3_PWM_Init(u16 arr,u16 psc)

{  

GPIO_InitTypeDef GPIO_InitStructure;

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

TIM_OCInitTypeDef  TIM_OCInitStructure;


RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟

GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5    

 

   //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOB.5

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO

 

   //初始化TIM3

TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值

TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 

TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

//初始化TIM3 Channel2 PWM模式  

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高

TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2


TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器

 

TIM_Cmd(TIM3, ENABLE);  //使能TIM3

}


总结

下一篇是关于输入捕获,我个人觉得学的越多,越会发现自己的不足;下次更新本文,加点自己的想法上去。

推荐阅读

史海拾趣

AC Photonics Inc公司的发展小趣事

AC Photonics Inc深知品质是企业生存和发展的关键。因此,公司始终将品质管理放在首位,从原材料采购到生产流程控制,再到产品出厂检验,都严格遵循国际标准和行业规范。同时,公司还注重品牌建设,通过参加行业展会、举办技术研讨会等方式,不断提升品牌知名度和美誉度。这些努力使得AC Photonics Inc的产品在市场上获得了广泛的认可和好评。

Gravitech公司的发展小趣事

AC Photonics Inc公司自成立以来,一直致力于光电技术的研发与应用。在公司成立初期,研发团队在光子集成技术上取得了重大突破,成功开发出一种高效、稳定的光电转换器。这一技术的问世,不仅提升了数据传输的速度和稳定性,还大大降低了能耗,为公司的业务发展奠定了坚实的基础。随着这一技术的逐步推广和应用,AC Photonics Inc在电子行业中逐渐崭露头角。

Global Specialties公司的发展小趣事

为了进一步扩大市场份额,Global Specialties积极实施全球化战略。公司通过与国际分销商和代理商的合作,将产品销往全球各地。同时,公司还参加了多个国际性的电子展会和论坛,与来自世界各地的客户和合作伙伴进行交流和合作。这些举措不仅提升了Global Specialties的品牌知名度,还为公司带来了更多的国际合作机会和客户资源。通过这些努力,Global Specialties逐渐发展成为一家具有全球影响力的电子测试与测量公司。

ALLEN BRADLEY公司的发展小趣事

为了进一步扩大市场份额,Global Specialties积极实施全球化战略。公司通过与国际分销商和代理商的合作,将产品销往全球各地。同时,公司还参加了多个国际性的电子展会和论坛,与来自世界各地的客户和合作伙伴进行交流和合作。这些举措不仅提升了Global Specialties的品牌知名度,还为公司带来了更多的国际合作机会和客户资源。通过这些努力,Global Specialties逐渐发展成为一家具有全球影响力的电子测试与测量公司。

Holtek(合泰)公司的发展小趣事

Global Specialties的创立源于对高质量测试与测量产品的追求。在公司成立初期,创始人便明确了公司的核心定位:为工程师、学生和业余爱好者提供可靠的测试与测量工具。他们首先推出了一系列电源、十进位箱和电子培训仪,这些产品迅速在行业内获得认可。凭借对产品质量的不懈追求,Global Specialties逐渐在竞争激烈的市场中站稳了脚跟。

3M公司的发展小趣事

近年来,创客文化在全球范围内兴起,Global Specialties迅速抓住了这一趋势。公司推出了一系列创客/DIY产品,包括各种模块化的电子元件和工具,旨在帮助创客们实现他们的创意和想法。通过举办线上线下的创客活动,Global Specialties不仅促进了创客之间的交流与合作,还进一步扩大了自己的品牌影响力。

问答坊 | AI 解惑

常用晶体管,3极管资料大全

常用晶体管,3极管资料大全…

查看全部问答>

RFIC是分布参数还是集总参数?

与各位探讨: RFIC的整体电路结构和集总参数射频电路区别不大,差异是因为在芯片里有些元件需要用工艺可以实现的方式设计。 集成电路有它的特点,例如在IC中,线间距离和线的尺寸都很小,由此在分立电路中不会出现或影响不显著的一些物理效应( ...…

查看全部问答>

无法打开包括文件:“ca_merge30.h”

在编译时出现无法打开包括文件:“ca_merge30.h”,寻求大侠们帮忙。。。。谢谢…

查看全部问答>

新手请教GPRS发手机短信中的PDU模式

我用GPRS调试发短信,但是不知道怎么把文本的转换成PDU模式的,也可以是怎么把超级终端中收到的一堆16进制的转换成中文?…

查看全部问答>

关于传感器采样液体微量变化的问题?

关于传感器采样液体微量变化的问题?     想用传感器采样液体的微量变化,然后试了试挂吊瓶,用传感器采样滴液的变化情况,感觉液体在滴啊,但是采样值却是一会大一会小,完全没有规律,一点也没呈现出线性变小的趋势。这是怎么回事? ...…

查看全部问答>

基于arm9的开发板运行一个wince系统,读写总线问题

基于arm9(EP9302)的开发板运行一个wince系统,读写总线问题: 在wince上写了一个小的测试程序, while循环读取一个虚拟地址(DI)的值, 再把这个值写到另一个虚拟地址(DO)上. 结果是:用示波器测得总线上的写信号正常, 读信号间隔时间有时要几秒钟才 ...…

查看全部问答>

据闻WINCE下能够定制触摸屏校准,具体如何定制呢?有大侠指教吗?

据闻WINCE下能够定制触摸屏校准,具体如何定制呢?有大侠指教吗?…

查看全部问答>

OLEDB 方法中的IID_IRowsetIndex 中的seek相关问题

请问一下各位大侠,我在一个数据表中建了三列(即3个字段)都是WCHAR类型,我想根据第二或第三列的值查询某一行的数据,请问要怎么实现啊?急急………

查看全部问答>

问个wince5.0的中断问题

就以SD卡为例子 注册表 [HKEY_LOCAL_MACHINE\\Drivers\\BuiltIn\\SDHC_SMDK2440]     \"Order\"=dword:21     \"Dll\"=\"sdhc_sc2440.dll\"     \"Prefix\"=\"SDH\"         \"DMAChann ...…

查看全部问答>

硬盘分区与文件恢复

我的电脑原来D盘有50G,用了好几年,删了存存了删,剩了不到3G的文件。2个月前我的朋友把我的电脑重新分区,格式化,重装了系统,我现在想起来原来在D盘(一年前)存过三十多个课件录音文件,当时就删了。我想问一下,这些文件现在在不恢复原有分 ...…

查看全部问答>