博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(五)转载:通用定时器PWM输出
阅读量:6808 次
发布时间:2019-06-26

本文共 6348 字,大约阅读时间需要 21 分钟。

1.     TIMER输出PWM基本概念

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

STM32的定时器除了TIM6和TIM7之外,其他的定时器都可以用来产生PWM输出,其中高级定时器TIM1和TIM8可以同时产生7路的PWM输出,而通用定时器也能同时产生4路的PWM输出。

1.1   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模式”一节,在此就不详细赘述了。

1.2   PWM输出管脚

  PWM的输出管脚是确定好的,具体的引脚功能可以查看《STM32参考手册》的“8.3.7 定时器复用功能重映射”一节。在此需要强调的是,不同的TIMx有分配不同的引脚,但是考虑到管脚复用功能,STM32提出了一个重映像的概念,就是说通过设置某一些相关的寄存器,来使得在其他非原始指定的管脚上也能输出PWM。但是这些重映像的管脚也是由参考手册给出的。比如说TIM3的第2个通道,在没有重映像的时候,指定的管脚是PA.7,如果设置部分重映像之后,TIM3_CH2的输出就被映射到PB.5上了,如果设置了完全重映像的话,TIM3_CH2的输出就被映射到PC.7上了。

 

1.3   PWM输出信号

  PWM输出的是一个方波信号,信号的频率是由TIMx的时钟频率和TIMx_ARR预分频器所决定的,具体设置方法在前面一个学习笔记中有详细的交代。而输出信号的占空比则是由TIMx_CRRx寄存器确定的。其公式为“占空比=(TIMx_CRRx/TIMx_ARR)*100%”,因此,可以通过向CRR中填入适当的数来输出自己所需的频率和占空比的方波信号。

 

2.     TIMER输出PWM实现步骤

  1.设置RCC时钟;

  2.设置GPIO时钟;

  3.设置TIMx定时器的相关寄存器;

  4.设置TIMx定时器的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输出了。

 

3.     TIMER输出PWM源代码

由于我现在手上的奋斗开发板是将PB.5接到LED上,因此需要使用TIM3的CH2通道,并且要进行引脚重映像。打开TIM3之后,PWM输出,使得LED点亮,通过改变PWM_cfg()中的占空比可以调节LED的亮度。

 

1 #include "stm32f10x_lib.h"  2   3    4   5 void RCC_cfg();  6   7 void GPIO_cfg();  8   9 void TIMER_cfg(); 10  11 void PWM_cfg(); 12  13 //占空比,取值范围为0-100 14  15 int dutyfactor = 50; 16  17   18  19 int main() 20  21 { 22  23      int Temp; 24  25        RCC_cfg(); 26  27        GPIO_cfg(); 28  29        TIMER_cfg(); 30  31        PWM_cfg(); 32  33   34  35        //使能TIM3计时器,开始输出PWM 36  37        TIM_Cmd(TIM3, ENABLE); 38  39   40  41        while(1); 42  43 } 44  45   46  47 void RCC_cfg() 48  49 { 50  51        //定义错误状态变量 52  53        ErrorStatus HSEStartUpStatus; 54  55        56  57        //将RCC寄存器重新设置为默认值 58  59        RCC_DeInit(); 60  61   62  63        //打开外部高速时钟晶振 64  65        RCC_HSEConfig(RCC_HSE_ON); 66  67   68  69        //等待外部高速时钟晶振工作 70  71        HSEStartUpStatus = RCC_WaitForHSEStartUp(); 72  73        if(HSEStartUpStatus == SUCCESS) 74  75        { 76  77               //设置AHB时钟(HCLK)为系统时钟 78  79               RCC_HCLKConfig(RCC_SYSCLK_Div1); 80  81   82  83               //设置高速AHB时钟(APB2)为HCLK时钟 84  85               RCC_PCLK2Config(RCC_HCLK_Div1); 86  87   88  89               //设置低速AHB时钟(APB1)为HCLK的2分频 90  91               RCC_PCLK1Config(RCC_HCLK_Div2); 92  93               94  95               //设置FLASH代码延时 96  97               FLASH_SetLatency(FLASH_Latency_2); 98  99  100 101               //使能预取指缓存102 103               FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);104 105  106 107               //设置PLL时钟,为HSE的9倍频 8MHz * 9 = 72MHz108 109               RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);110 111  112 113               //使能PLL114 115               RCC_PLLCmd(ENABLE);116 117  118 119               //等待PLL准备就绪120 121               while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);122 123  124 125               //设置PLL为系统时钟源126 127               RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);128 129  130 131               //判断PLL是否是系统时钟132 133               while(RCC_GetSYSCLKSource() != 0x08);134 135        }136 137  138 139        //开启TIM3的时钟140 141        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);142 143        //开启GPIOB的时钟和复用功能144 145        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);146 147  148 149 }150 151  152 153 void GPIO_cfg()154 155 {156 157        GPIO_InitTypeDef GPIO_InitStructure;158 159  160 161       162 163        //部分映射,将TIM3_CH2映射到PB5164 165 //     GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);166 167        GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);168 169  170 171        //选择引脚5172 173        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;174 175        //输出频率最大50MHz                                                        176 177        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;178 179        //复用推挽输出                                              180 181       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 182 183  184 185        GPIO_Init(GPIOB,&GPIO_InitStructure);186 187 }188 189  190 191 void TIMER_cfg()192 193 {194 195        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;196 197  198 199        //重新将Timer设置为缺省值200 201        TIM_DeInit(TIM3);202 203        //采用内部时钟给TIM3提供时钟源204 205        TIM_InternalClockConfig(TIM3);206 207        //预分频系数为0,即不进行预分频,此时TIMER的频率为72MHz208 209        TIM_TimeBaseStructure.TIM_Prescaler = 0;210 211        //设置时钟分割212 213        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;214 215        //设置计数器模式为向上计数模式216 217        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;218 219        //设置计数溢出大小,每计7200个数就产生一个更新事件,即PWM的输出频率为10kHz220 221        TIM_TimeBaseStructure.TIM_Period = 7200 - 1;222 223        //将配置应用到TIM3中224 225        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);226 227 }228 229  230 231 void PWM_cfg()232 233 {234 235        TIM_OCInitTypeDef TimOCInitStructure;236 237        //设置缺省值238 239        TIM_OCStructInit(&TimOCInitStructure);240 241        //PWM模式1输出242 243        TimOCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;244 245        //设置占空比,占空比=(CCRx/ARR)*100%或(TIM_Pulse/TIM_Period)*100%246 247        TimOCInitStructure.TIM_Pulse = dutyfactor * 7200 / 100;248 249        //TIM输出比较极性高250 251        TimOCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;252 253        //使能输出状态254 255        TimOCInitStructure.TIM_OutputState = TIM_OutputState_Enable;256 257        //TIM3的CH2输出258 259        TIM_OC2Init(TIM3, &TimOCInitStructure);260 261        //设置TIM3的PWM输出为使能262 263        TIM_CtrlPWMOutputs(TIM3,ENABLE);264 265 }

 

 

转载地址:http://mytwl.baihongyu.com/

你可能感兴趣的文章
苹果iCloud大调整:干掉1TB版本,2TB降价
查看>>
中拉光伏产业合作蓬勃发展前景远大
查看>>
定位到文件目录并选定文件
查看>>
瑞典驻华参赞:智慧城市建设提升为国家战略
查看>>
跨界合作成潮流 智能家居竞争升级
查看>>
思科:企业数据中心技术产品采购放缓
查看>>
StatX 获250万美元融资,随时随地通知公司业务变化
查看>>
《软件定义网络:基于OpenFlow的SDN》一一3.4 本章总结
查看>>
智能家居形态逐步演进 机会与挑战并存
查看>>
《Linux指令从入门到精通》——4.4 Linux下的文本编辑指令
查看>>
淘富成真,硬件智能—— 硬件创新一站赋能平台
查看>>
网友神总结:我们继续用 XP 的十大理由
查看>>
2014年8月份国内主浏览器市场份额排行榜
查看>>
《Storm实时数据处理》一导读
查看>>
《UNIX网络编程 卷1:套接字联网API(第3版)》——8.2 recvfrom和sendto函数
查看>>
《数据结构与抽象:Java语言描述(原书第4版)》一第2章
查看>>
初学者指南:为开源做贡献
查看>>
OVM 免费虚拟化软件迭代时间调整,提高产品稳定性!
查看>>
《Windows Server 2012 Hyper-V虚拟化管理实践》——2.3 Hyper-V角色安装后的状态
查看>>
《电子元器件的可靠性》——3.7节电子元器件失效率鉴定试验
查看>>