嵌入式学习笔记——PWM与输入捕获(上)
输出比较与输入捕获前言输出比较PWMPWM简介输出比较详细框图1. 定时器部分2. 比较器控制部分3.输出控制部分寄存器简介输出比较代码伪代码实际代码实际效果总结M4系列目录前言上一篇中主要介绍了有关通用定时器的一些概述性内容本文主要是具体介绍一下输出比较与输入捕获的使用过程包括其详细结构以及寄存器其中输出捕获以常用的PWM为例输入捕获以捕获按下按键的时间为例。输出比较PWM首先来看看输出比较部分前面提到了通用定时器的通道具有输入捕获、输出比较、PWM模式、单脉冲输出模式本质上除了输入捕获以外其他三个都是属于输出比较都是通过编程控制输出高低电平的具体时间、周期循环或者单次只是具体配置的输出方式不一样其中PWM是最常用的控制方式在电机控制、调节LED、屏幕亮度、电源电压控制等等邻域都有应用。那么什么是PWM呢PWM简介PWM名称叫做脉冲宽度调制技术是一种常用于电子电路和控制系统中的信号调制技术。在实际应用中PWM广泛运用于电机驱动、灯光控制、电源电压控制等领域。因为PWM技术能够提供精准的控制使得输出信号的质量更加高效和稳定同时也减少了系统能耗和噪声干扰。其实通俗点说PWM就是一个一直循环的方波信号只是这个方波信号的周期以及高低电平的时间都是可以调节的也正是由于其周期性所以需要借助定时器来实现使用定时器去操作PWM控制的本质是操作高低电平的时间。输出比较详细框图在编程手册的15.3.4 捕获/比较通道有关于输入输出的详细电路图如下所示是通道1的主电路图其中左侧是输入捕获部分的右侧是输出比较部分的这里先看输出比较部分的。仔细观察会发现在这个框图的内容应该不全上一篇的中的输出部分还有一个输出控制器在这个图中找不到实际上不是少了只是为了方便排版官方分为了几个图找到“图 146. 捕获/比较通道的输出阶段通道 1”它所对应的电路就是输出的剩下部分这里笔者直接将两者做个拼接拼接后如下图所示这个电路图才是输出比较的实际框图还是老规矩为了好理解进行分块介绍。1. 定时器部分首先还是来看定时器的部分其实定时器部分的配置和框图和之前的基本定时一样的这里只是更详细了对照下图再捋一下定时器的配置流程1.开启对应的时钟使能2.进行时基配置包括计数器、预分频和重装载的配置关于计数器的配置其实很简单没有什么多说的这里要补充一点计数器和比较器的工作方式。如上图所示计数器的计数器会和比较器的CCR1进行比较假设我们编程控制要求当计数器的CNT大于CCR1的时候输出高电平当CNTCCR1时输出低电平这在对应通道的IO口我们就可以看见右侧IO逻辑的输出波形。同样的我们也可以编程为当CNT小于CCR1时输出高电平当CNT大于等于CCR1时输出低电平此时IO的输出波形如下图所示也就是说GPIO在啥时候输出啥电平是可以由我们进行编程控制的。2. 比较器控制部分关于比较器的控制部分其实和基本定时器的流程差不多这里我们先看下图中的红框位置他的输出是指向比较预装载寄存器和比较影子寄存器之间的这就说明由他来控制是否将预装在寄存器里面的值写入影子寄存器进而是参数对计数器产生效果。要让这个与门输出为真才可以让预装载值写入影子寄存器那么要让与门输出为真就要求后面的三个输入都是真才行接下来看与门后面的三个输入首先是1号位置它的输出在进入与门之前会有一个非对它进行取反也就说如果1号位置是非0的时候 第一个输入红框与门的信号就是0这样是无法写入数据的那么1号位置代表的是什么呢查询对应的寄存器就可以知道了如下图所示可以发现这个寄存器就是写入预装载值的在写入CCR1数据的时候1号位置会输出1使得红框的与门被卡住避免将错误数据写入影子寄存器而写入完成后1号位置会输出0此时1号输入红框与门的为真可以写入对于编程人员来说只需要对CCR1进行赋值就可以了写入完成这些不需要我们判断。然后是2号位置这里是一个或非门它的逻辑是输入全为假则为真输入有真则为真也就是说此路想要让红框的与门输出为真的话就必须保证CC1S这个寄存器的值为0才可以那么这个寄存器的值为0代表了什么呢还是在编程手册中对应搜索即可。可以发现这个寄存器是用来选择配置为输入模式还是输出模式的由于PWM是输出比较所以得配置为“00”这样也就使得或非门输出为真进而使得与门的第二个数为真。4 .最后就是红框与门的第三个输入了也就是图中的3号位置可以看出它是一个或门有两个输入且上面的输入也是带有非门标志的那么这个或门要输出真的话就要求上面的输入事件为假或者下面的输入为真那么这两个输入的事件对应的是什么呢还是看编程手册如下图所示首先是OCIPE这一位就是使能预装载的也就是说编程时可以通过控制这一位来实现预装载要不要开启。然后是下面这个事件我们先不看猜一下既然上个事件是使能或者禁止预装载那么这个预装载配套的还有个东西——就是我们前面使用基本定时器的时候提到过的更新事件如果开启了预装载寄存器那么我们要想真正的将数据写入计数器的话就必须手动产生一次更新时间才可以所以最后一个肯定是和更新事件有关的UEV更新事件。这里的配置一般都会开启预装载寄存器的。3.输出控制部分经过计数器和比较比较后的输出结果会来到下图所示的输出模式控制器这部分的电路主要就是控制输出的模式是高有效还是低有效这些那么具体怎么控制的呢。首先需要看的就是1号框内有一个数据选择器这里要注意原本的编程手册这个地方有点小问题就是选择器的选择寄存器原图中标的寄存器找不到实际是笔者图中改的TIMx_CCMR1的OC1CK,描述如下ETRF前面提到过叫做外部触发输入 (ETRF)由于PWM输出过程中不需要由外部触发的作用所以默认配置为0然后是2号框对应的OC1M这位对应位置也在CCMR1上可以发现这个寄存器分为了两部分功能其中上面第一列是控制输出功能的中间第二列是控制输入模式的他们是共用一个寄存器的。关于OC1M的作用如下图所示此三位是用来选择模式的由于我们要使用PWM模式所以就需要配置为110或者111关于PWM的模式1和PWM的模式2其实就是上面提到的有效电平的不同罢了当计数器为向上计数时PWM模式1 CNTCCR的时候为有效电平PWM模式2 CNTCCR的时候为有效电平也就是说这两个模式在其他配置都一样的情况下会生成互补的输出波形。然后就是3号红框的位置这里又是一个数据选择器但是输入信号是同一个只是其中一个进行了取反操作猜一下这个位是用来控制输出极性的具体描述如下图所示此位就是用来控制输出博信是高有效还是低有效的那么需要注意的是上面的PWM模式最终也是控制高低电平的这个也是用来控制高低电平在配置的过程中要小心。最后就是4号框所在的控制器使能位置一才可以开启对应的输出。输出比较需要配置的流程输出通道需要配置的①选择输出模式②比较寄存器的影子寄存器③选择PWM模式④选择有效电平⑤输出使能寄存器简介上面的框图讲解已经引出了大部分寄存器了这里再来做个总结将所需要用的寄存器挑出来。通用定时和高级定时器的寄存器数量还是蛮多的通用定时器就有了20个寄存器当然不是每次都需要20个寄存器只需要根据对应功能去配置对应位即可。 PWM需要使用的寄存器如下所示1.TIMx 控制寄存器 1 (TIMx_CR1)写法 TIMx-CR1位 0 CEN计数器使能位 1 UDIS更新禁止 (Update disable)位 2 URS更新请求源 (Update request source)位 3 OPM单脉冲模式 (One-pulse mode)位 4 DIR方向 (Direction)位 7 ARPE自动重载预装载使能 (Auto-reload preload enable)位 9:8 CKD时钟分频 (Clock division)输入捕获的时候涉及到采样频率2.TIMx 状态寄存器 (TIMx_SR)写法TIMx-SR位 0 UIF更新中断标志 (Update interrupt flag)位 1 CC1IF捕获/比较 1 中断标志 (Capture/compare 1 interrupt flag)3.TIMx 事件生成寄存器 (TIMx_EGR)写法TIMx-EGR位 0 UG更新生成 (Update generation)4.TIMx 捕获/比较模式寄存器 1 (TIMx_CCMR1)写法TIMx-CCMR1用于配置通道1 通道2位 1:0 CC1S捕获/比较 1 选择 (Capture/Compare 1 selection)选择输入还是输出位 3 OC1PE输出比较 1 预装载使能 (Output compare 1 preload enable)比较影子寄存器使能位 6:4 OC1M输出比较 1 模式 (Output compare 1 mode)选择对应输出模式 PWM15.TIMx 捕获/比较模式寄存器 2 (TIMx_CCMR2)写法TIMx-CCMR2功能和CCMR1完全一致 操作的是通道3 和 通道46.TIMx 捕获/比较使能寄存器 (TIMx_CCER)写法TIMx-CCER位 0 CC1E捕获/比较 1 输出使能 (Capture/Compare 1 output enable)。通道使能置1使能位 1 CC1P捕获/比较 1 输出极性 (Capture/Compare 1 output Polarity)。配置对应有效电平7.TIMx 捕获/比较寄存器 1 (TIMx_CCR1)写法TIMx-CCR1用法直接赋值不难发现整个配置过程中时基配置部分和前面的基本定时器一样的就是修改了一下定时的名字。通用定时的PWM功能只是在其基础上怎加了部分寄存器。输出比较代码根据上面的框图讲解以及寄存器的介绍总结一下使用定时器输出PWM的配置流程:伪代码PWM初始化配置{//开始对应时钟 IO口 定时器GPIO的控制器//模式寄存器//复用功能寄存器 查映射表配置定时器的时基单元部分//更新禁制//更新请求源//单脉冲//方向//重装载值影子寄存器//预分频配置//重装载值配置//人为产生更新事件配置输出通道//通道配置成输出模式//比较寄存器的影子寄存器//配置PWM模式//配置输出的有效电平//通道使能//计数器使能}//具体修改PWM输出的占空比就是通过控制比较寄存器的值CCR来实现的TIMx-CCR1****;实际代码首先找到对应需要PWM驱动的外设引脚这里笔者用的是PA6、PA7在原理图上即可查看然后再引脚映射表查找对应的映射号和对应的定时器通道分别是AF2、TIM3-CH1、TIM3-CH2;然后就是代码了如下所示/******************************************* *函数名 :Time3_PWM_Init *函数功能 :定时器三的PWM初始化配置 *函数参数 :u16 arr u16 psc *函数返回值:无 *函数描述 : PA6---------CH1 PA7---------CH2 *********************************************/voidTime3_PWM_Init(u16 psc,u16 arr){RCC-AHB1ENR|(10);//打开PA的时钟RCC-APB1ENR|(11);//打开Time3的时钟//GPIO的配置GPIOA-MODER~(0xf12);//清零GPIOA-MODER|(0xa12);//复用模式GPIOA-AFR[0]~(0xf24);//清零GPIOA-AFR[0]|(0x224);//将PA6映射到Time3的通道1//GPIOA-AFR[0] ~(0xf28);//清零GPIOA-AFR[0]~(0XF28);//清零GPIOA-AFR[0]|(228);//将PA7复用到TIM3_CH1/*-----------时基配置-----------------------------------------------------------------*/TIM3-CR1~(0Xf1);//更新禁止更新请求源关闭单脉冲向上计数TIM3-CR1|(17);//重装载影子寄存器TIM3-SMCR~(70);//配置内部时钟TIM3-PSCpsc-1;TIM3-ARRarr-1;TIM3-EGR|(10);//更新事件写入预分频和重装载值/*--------------通道部分-------------------------------------------------------------*///通道一TIM3-CCMR1~(30);//配置为输出模式TIM3-CCMR1|(13);//比较寄存器的影子寄存器TIM3-CCMR1~(0X74);TIM3-CCMR1|(0X64);//PWM模式1TIM3-CCER|(11);//低电平有效TIM3-CCER|(10);//输出通道使能//通道二TIM3-CCMR1~(38);//配置为输出模式TIM3-CCMR1|(111);//比较寄存器的影子寄存器TIM3-CCMR1~(0X712);TIM3-CCMR1|(0X612);//PWM模式1TIM3-CCER|(15);//低电平有效TIM3-CCER|(14);//输出通道使能TIM3-CR1|(10);//计数器使能}#ifndef _PWM_H #define _PWM_H #includestm32f4xx.h#define Time_PWM_Duty1TIM3-CCR1#define Time_PWM_Duty2TIM3-CCR2voidTime3_PWM_Init(u16 psc,u16 arr);#endif实际效果实现板子上两个灯PA6和PA7的呼吸灯效果占空比控制函数/******************************* 函数名TIM7_IRQHandler 函数功能定时器7中断服务函数函数 函数形参无 函数返回值void 备注1ms中断 ********************************/voidTIM7_IRQHandler(void){staticu8 LED_Flag0;staticu16 Time7_Cnt[10];if(TIM7-SR(10)){TIM7-SR~(10);Time7_Cnt[0];Time7_Cnt[1];if(Time7_Cnt[0]500){Time7_Cnt[0]0;}if(Time7_Cnt[1]2){Time7_Cnt[1]0;if(LED_Flag0)//逐渐亮{Time_PWM_Duty1;Time_PWM_Duty2;if(Time_PWM_Duty1900){LED_Flag1;Time_PWM_Duty1990;Time_PWM_Duty2990;}}if(LED_Flag1)//逐渐暗{Time_PWM_Duty1--;Time_PWM_Duty2--;if(Time_PWM_Duty150){LED_Flag0;Time_PWM_Duty110;Time_PWM_Duty210;}}}}}呼吸灯总结关于输出比较模式的PWM输出就介绍这么多由于篇幅太长影响看的体验输入捕获再单开一篇下篇进行介绍。M4系列目录1.嵌入式学习笔记——概述2.嵌入式学习笔记——基于Cortex-M的单片机介绍3.嵌入式学习笔记——STM32单片机开发前的准备4.嵌入式学习笔记——STM32硬件基础知识5.嵌入式学习笔记——认识STM32的 GPIO口6.嵌入式学习笔记——使用寄存器编程操作GPIO7.嵌入式学习笔记——寄存器实现控制LED小灯8.嵌入式学习笔记——使用寄存器编程实现按键输入功能9.嵌入式学习笔记——STM32的USART通信概述10.嵌入式学习笔记——STM32的USART相关寄存器介绍及其配置11.嵌入式学习笔记——STM32的USART收发字符串及串口中断12.嵌入式学习笔记——STM32的中断控制体系13.嵌入式学习笔记——STM32寄存器编程实现外部中断14.嵌入式学习笔记——STM32的时钟树15.嵌入式学习笔记——SysTick(系统滴答)16.嵌入式学习笔记——M4的基本定时器17.嵌入式学习笔记——通用定时器18.嵌入式学习笔记——PWM与输入捕获上19.嵌入式学习笔记——PWM与输入捕获下20.嵌入式学习笔记——ADC模数转换器21.嵌入式学习笔记——DMA22.嵌入式学习笔记——SPI通信23.嵌入式学习笔记——SPI通信的应用24嵌入式学习笔记——IIC通信