STM32 定时器TIM

[复制链接]
发表于 2025-9-22 03:01:20 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目次
定时器基础知识
根本定时器
通用定时器
定时器克制应用 
超声波模块
 通用定时输出PWM



定时器基础知识

定时器就是用来定时的呆板,是存在于STM32单片机中的一个外设。STM32统共有8个定时器,分别是2个高级定时器(TIM1、TIM8),4个通用定时器(TIM2、TIM3、TIM4、TIM5)和2个根本定时器(TIM6、TIM7),如下图所示:
STM32F10X系列统共最多有八个定时器
三种STM32定时器的区别:

向上是指1234逐个递增计数,向下是指逐个递减计数,向上/向下是指中央对齐模式(根本定时器只能向上,上图写错了) ,捕获指的是输入捕获,比力指的是输出比力

根本定时器

1. 时钟源 2. 控制器 3. 时基单元
时钟源
时钟源来自RCC的TIMx_CLK(属于内部的CK_INIT)
外设挂载在总线下的APB1对应的是时钟2~时钟7(以是我们的根本定时器TIM6 TIM7在APB1下的)
根据时钟树
因为AHB 72M,(AHB默认分频是2)以是APB1是 36M,(APB1默认分频是2)以是根据(如果APB1预分频系数=1则频率稳定,否则频率x2.)可知定时器的频率 = 72M

时基(定时器的心脏)
        定时器最紧张的就是时基部分:包罗预分频器、计数器、自动重装载寄存器  
        预分频器:1-16位预分频器PSC对内部时钟CK_PSC举行分频之后,得到计数器时钟CK_INT=CK_PSC/(PSC+1)
        CNT在计数器时钟的驱动下开始计数,计数一次的时间为1/CK_INT
        计数器、重装在寄存器:定时器使能(CEN置1)后,计数器CNT在CK_CNT驱动 下计数,当CNT值与ARR的设定值相称时就自动天生变乱并CNT自动清零,然后 自动重新开始计数,云云重复以上过程。
   影子寄存器
  1.PSC和ARR都有影子寄存器,功能框图上有个影子
  2.影子寄存器的存在起到一个缓冲的作用,用户值->寄存器->影子寄存器->起作用, 如果不使用影子寄存器则用户值在写到寄存器之后则内里起作用,ARR影子, TIMx_CR1:APRE位控制。
   定时时间的盘算
定时器时间=(PSC+1)*(ARR+1)/72M
因为我们的计数器是从0开始计数的,以是要加1
根本定时器的功能
1.计数器16bit,只能向上计数,只有TIM6和TIM7
2.没有外部的GPIO,是内部资源,只能用来定时
3.时钟来自PCKL1,为72M,可实现1~65536分频

通用定时器

STM32 的通用定时器功能:
位于低速的APB1总线上(APB1)
16 位/32 位(仅 TIM2 和 TIM5)向上、向下、向上/向下自动装载计数器 (TIMx_CNT),注意:TIM9~TIM14 只支持向上(递增)计数方式
16 位可编程(可以及时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~ 65535 之间的任意数值
4 个独立通道(TIMx_CH1~4,TIM9~TIM14 最多 2 个通道),这些通道可以用来作为:
                输入捕获
                输出比力
                PWM 天生(边沿或中心对齐模式) ,注意:TIM9~TIM14 不支持中心对齐模式
                单脉冲模式输出
可使用外部信号(TIMx_ETR)控订定时器和定时器互连(可以用 1 个定时器控制别的 一个定时器)的同步电路。
        如下变乱发生时产生克制/DMA(TIM9~TIM14 不支持 DMA):
                更新:计数器向上溢出/向下溢出,计数器初始化(通过软件大概内部/外部触发)
                触发变乱(计数器启动、克制、初始化大概由内部/外部触发计数)
                输入捕获
                输出比力
                支持针对定位的增量(正交)编码器和霍尔传感器电路(TIM9~TIM14 不支持)
                触发输入作为外部时钟大概按周期的电流管理(TIM9~TIM14 不支持) 
STM32的通用定时器可以被用于:丈量输入信号的脉冲长度(输入捕获)大概产生输出波形(输出比力和PWM)等
使用定时器分频器和RCC时钟控制分频器,脉冲长度和波型周期可以在几个玄妙到几个毫秒间调解,STM32的每个通用定时器都是完全独立的,没有相互共享的任何资源        
计数器模式  
        向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且 产生一个计数器溢出变乱
        向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装 入的值重新开始,并产生一个计数器向下溢出变乱
        中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个 计数器溢出变乱,然后向下计数到1并且产生一个计数器溢出变乱;然后再从0开始重新计数

通用定时器框图

框图可以分为四个大部分,分别是:
时钟产生部分
时基单元部分
输入捕获部分
输出捕获部分
时钟产生部分 
内部时钟(CKINT)
外部时钟模式:外部触发输入(ETR)
内部触发输入(TRX):使用一个定时器作为另一个定时器的预分频器,如可以设置一个定时器Timer1而作为另一个定时器Iimer2的预分频器。
外部时钟模式:外部输入脚(TIx)
时机单元
时基单元就是定时器框图的第二部分,它包罗三个寄存器,分别是:计教器寄存器(TIMXCND、预分频器寄存器(TIMXPSC)和自动装载寄存器(TIMX ARR)。对这三个寄存器的先容如下:
计数器寄存器(TIMx_CNT)
        向上计数、向下计数大概中心对齐计数;
预分频器寄存器(TIMx_PSC)
       可将时钟频率按1到65535之间的任意值举行分频,可在运行时改变其设置值;
自动装载寄存器(TIMX ARR)
        如果TIMx_CR1寄存器中的ARPE位为0,ARR寄存器的内容将直接写入影子寄存器;如果ARPE为1,ARR寄存器的那日同将在每次的更新时间UEV发生时,传送到影子寄存器;
输入捕获通道
1.IC1、2和IC3、4可以分别通过软件设置将其映射到T11、TI2和TI3、TI4;
2.4个16位捕获比力寄存器可以编程用于存放检测到对应的每一次输入捕获时计数器的值,
3.当产生一次捕获,相应的CCxIF标记位被置1;同时如果克制或DMA哀求使能,则产生克制或DMA哀求。
4.如果当CCxIF标记位已经为1,当又产生一个捕获,则捕获溢出标记位CCxOF将被置1。
输出比力通道
PWM模式运行产生:
        定时器2、3和4可以产生独立的信号:频率和占空比可以举行如下设定一个自动重载寄存器用于设定PWM的周期;每个PWM通道有一个
捕获比力寄存器用于设定占空时间。
两种可设置PWM模式:
        边沿对齐模式
        中心对齐模式
常用库函数
定时器参数初始化函数(第一个参数定时器几,第二个参数布局体指针)
  1.  void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
复制代码
布局体内部成员
  1. typedef struct
  2. {
  3.     uint16_t TIM_ClockDivision;     //外部输入时钟分频因子,基本定时器没有
  4.    uint16_t TIM_CounterMode;       //计数模式,基本定时器只能向上计数
  5.     uint16_t TIM_Period;           //自动重装载值 //注意重装载值和分频因子的数配置不能超过65535
  6.    uint16_t TIM_Prescaler;    //分频因子      
  7.     uint8_t TIM_RepetitionCounter;  //重复计数值,基本定时器没有,高级定时器专用
  8. } TIM_TimeBaseInitTypeDef;  
  9. 65535
复制代码
 定时器控制LED灯软件流程设计
初始化体系
        初始化定时器和LED的IO时钟、初始化LED的引脚IO
        使能定时器时钟、初始化定时器、开启克制设置、使能定时器、
编写定时器克制函数
定时器时间= (ARR+1)*(PSC+1)/TCLK(72M=72 000 000)
如果定时1秒 1= 72 00*10000/72M

 这里预分频是对72M举行7200分频,得到的是10K的计数频率,在10k的频率下计10000个数,那就是1s的时间
  1. #include "stm32f10x.h"
  2. #include "tim.h"
  3. void Base_Tim_Init()
  4. {
  5.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  6.         TIM_TimeBaseInitTypeDef TIM_TimeIinitStruct;
  7.         NVIC_InitTypeDef NVIC_InitStruct;
  8.        
  9.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  10.         TIM_TimeIinitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
  11.         TIM_TimeIinitStruct.TIM_CounterMode = TIM_CounterMode_Up;
  12.         TIM_TimeIinitStruct.TIM_Period = 7200 - 1;
  13.         TIM_TimeIinitStruct.TIM_Prescaler = 10000 - 1;
  14.         TIM_TimeIinitStruct.TIM_RepetitionCounter = 0;
  15.        
  16.         TIM_TimeBaseInit(TIM2,&TIM_TimeIinitStruct);
  17.        
  18.   TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);
  19.         TIM_Cmd(TIM2, ENABLE);
  20.         NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
  21.         NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  22.         NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
  23.         NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
  24.        
  25.         NVIC_Init(&NVIC_InitStruct);
  26. }
  27.        
复制代码
  1.   TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);
  2. 第二个参数
  3. 输入捕获输出比较所用到的通道
  4. 如果我们只是想产生定时器的更新源中断用第一个参数
复制代码

  1. #include "stm32f10x.h"
  2. #include "main.h"
  3. #include "led.h"
  4. #include "bear.h"
  5. #include "key.h"
  6. #include "relay.h"
  7. #include "shake.h"
  8. #include "usart.h"
  9. #include "stdio.h"
  10. #include "tim.h"
  11. void delay(uint16_t time) {
  12.     uint16_t i = 0;
  13.     while (time--) {
  14.         i = 12000;
  15.         while (i--);
  16.     }
  17. }
  18. int main()
  19. {
  20.                
  21.                 Led_Init();
  22.     Base_Tim_Init();
  23.     while (1)
  24.                 {                              
  25.                        
  26.         }
  27. }
  28. void TIM2_IRQHandler(void)
  29. {
  30.         if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
  31.         {
  32.                
  33.                 GPIO_ResetBits(GPIOA, GPIO_Pin_1);
  34.                 delay(1000);
  35.                 GPIO_SetBits(GPIOA, GPIO_Pin_1);
  36.                 delay(1000);
  37.                
  38.         }
  39.                 TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  40.        
  41. }
复制代码
定时器克制应用 

超声波模块

                         

 1.工作原理
起首单片机给Trig引脚,给至少10us(10微秒)的高电平信号。
模块自动发送8个40KHz的方波,自动检测是否有信号返回。
有信号返回,通过Echo引脚输出高电平,高电平连续时间就是超声波从发射到返回的时间
HC-SR04超声波测距模块提供2cm-400cm的测距功能,精度达3mm。
2.硬件接线
四根杜邦线,VCC毗连单片机3.3-5V(保举5V供电),GND接到板子的GND,Trig为外部触发信号输入,输入一个10us的高电平即可触发模块测距,Echo(吸收引脚)即为 反响信号输出,测距竣事时此管引脚输出一个低电平,电平宽度反映超声波往返时间之和。
3.控制超声波测距步调
初始化定时器时钟和定时器克制
初始化超声波时钟和超声波引脚模式
编写定时器克制函数测距
先发送10us的高电平信号,发送了之后我的定时器就开始捕获Echo的高电平的时间,什么时间低电平就什么时间关闭定时器,就开始算好比说我们产生了多少次定时器的克制,好比是一次定时器克制是1秒,多少个定时器克制就是多少个秒,通过一系列公式就能知道间隔是多少
   1. 发送 10μs 的高电平信号(触发信号)
  

  • 目标:启动一次测距使用。
    这里的 “发送高电平” 通常是通过单片机的 IO 口输出一个连续 10 微秒(μs) 的高电平脉冲(如 HC-SR04 模块必要如许的触发信号)。
  • 为什么是 10μs?
    这是目标装备(如超声波传感器)的协议规定,用于告知传感器 “开始发射信号”(比方超声波传感器会在吸收到 10μs 高电平后,发射一束超声波)。
  2. 定时器开始捕获 Echo 信号的高电平常间
  

  • Echo 信号是什么?
    Echo 是 “回波信号”,即目标装备吸收到反射回来的信号后,输出的电信号。比方:

    • 发送端发射超声波后,Echo 信号保持低电平;
    • 当超声波遇到停滞物反射回来被吸收端检测到,Echo 信号变为高电平;
    • 直到信号吸收完毕,Echo 信号重新变为低电平。

  • 定时器的作用:
    从触发信号发送完成的时间起,定时器开始记录 Echo 信号 高电平的连续时间(即从 “收到回波” 到 “回波竣事” 的时间)。
  3. 检测到低电平常关闭定时器
  

  • 何时关闭定时器?
    当 Echo 信号从高电平跳转为低电平常(即回波吸收完毕),立即克制定时器计数。
  • 本质:
    定时器记录的是 “回波信号高电平的连续时间 T”,这个时间 T 即是信号从发射到吸收的 往返时间(即信号从发射端→停滞物→吸收端的总时间)。
  4. 通过定时器克制次数盘算时间 T
  

  • 定时器克制机制:
    定时器通常设置为按固定周期产生克制(比方每 1μs、1ms 产生一次克制),每次克制时计数器加 1。

    • 假设定时器克制周期为 1μs(即每 1 微秒产生一次克制),克制次数为 N 次,则总时间 T = N × 1μs。
    • (原句中 “一次克制是 1 秒” 是简化举例,现实应用中克制周期远小于 1 秒,通常为微秒或毫秒级,否则精度不敷。)

  • 怎样盘算克制次数?
    定时器启动后,每当 Echo 为高电平常,克制计数器连续累加,直到 Echo 变低时克制计数,此时计数器的值即为高电平期间的克制次数。
  5. 通过公式盘算间隔
  

  • 核心公式(以超声波测距为例):
    间隔 = (信号速率 × 时间 T) / 2

    • 除以 2 的缘故起因:信号往返一次(发射→停滞物→吸收),现实间隔是单程间隔。
    • 信号速率:超声波在氛围中约为 340m/s(即 0.034cm/μs),光速约为 3×10⁸m/s(用于激光测距)。

  • 举例盘算:
    若 T = 1000μs(1 毫秒),则间隔 = (0.034cm/μs × 1000μs) / 2 = 17cm。
  
   超声波代码框架

只有收到反响信号的时间,我们的trigr,在信号发出的时间我的echo引脚输入给我们的单片机,然后如果我们的单片机之前是低电平,检测高电平的刹时才开始打开定时器(怎么打开和关闭定时器呢)之前设置定时器的时间布局体设置和克制的设置TIM_Cmd(TIM2, DISABLE);函数,先关闭
当收到信号的时间再打开,怎么盘算高电平常间?起重要先判断echo引脚什么时间酿成高电平
用GPIO_ReadInputDataBit函数然后这里再打开定时器这时就开始我们的克制函数,克制函数去计数定时器进入的次数,因为我们用定时器的开启的时间用定时器的克制盘算进入定时器的时间,注意  这里定时器的设置TIM_Initstruct.TIM_Period = 1000 -1;  TIM_Initstruct.TIM_Prescaler = 72 -1;
以是定时器的定时周期的1毫秒,计数器每计1次代表1微秒 ,克制1次是1毫秒,因为我们对应的时间是高电平的时间即是克制次数加上不敷一个克制的次数(不敷一个克制的次数是说不到1毫秒但有多少个微秒呢)打开定时器,就会跳到定时器克制函数void TIM2_IRQHandler()让mscount++;这里必要界说一个新变量,然后关闭定时器,盘算总电平常间,界说一个变量uint16_t t=0;界说一个函数专门用来封装总的高电平常间int Get_Echon_Time()(这里返回值是int)然后将总时间换算成间隔以种种方式将t换算间隔然后返回值length
 
  1. #include "stm32f10x.h"
  2. #include "tim.h"
  3.   uint16_t mscount = 0;//定义一个变量专门用来记录中断的次数
  4. void delay_us(uint32_t us)
  5. {
  6.                 us*= 8;
  7.                 while(us--);
  8.         //延时微秒函数
  9.        
  10. }       
  11. void delay_ms(uint32_t ms)
  12. {
  13.                 while(ms--)
  14.                 {
  15.                         delay_us(1000);
  16.                        
  17.                 }       
  18.         //延时毫秒函数
  19.        
  20.        
  21. }
  22. void Base_Tim_Init()
  23. {
  24.         TIM_TimeBaseInitTypeDef TIM_Initstruct;
  25.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  26.         NVIC_InitTypeDef NVIC_TIM_Initstruct;
  27.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  28.        
  29.        
  30.         TIM_Initstruct.TIM_ClockDivision =TIM_CKD_DIV1;
  31.         TIM_Initstruct.TIM_CounterMode = TIM_CounterMode_Up;
  32.         TIM_Initstruct.TIM_Period = 1000 -1;
  33.         TIM_Initstruct.TIM_Prescaler = 72 -1;
  34.         TIM_Initstruct.TIM_RepetitionCounter = 0;
  35.        
  36.         TIM_TimeBaseInit(TIM2, &TIM_Initstruct);
  37.         TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);
  38.         TIM_Cmd(TIM2, DISABLE);
  39.         NVIC_TIM_Initstruct.NVIC_IRQChannel =  TIM2_IRQn;
  40.         NVIC_TIM_Initstruct.NVIC_IRQChannelCmd = ENABLE;
  41.         NVIC_TIM_Initstruct.NVIC_IRQChannelPreemptionPriority = 0;
  42.         NVIC_TIM_Initstruct.NVIC_IRQChannelSubPriority = 0;
  43.        
  44.         NVIC_Init(&NVIC_TIM_Initstruct);
  45.        
  46. }
  47. void HC04_Iint()
  48. {
  49.        
  50.         GPIO_InitTypeDef GPIO_Initstruction;
  51.        
  52.         RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
  53.        
  54.         //Tring B11
  55.         GPIO_Initstruction.GPIO_Mode = GPIO_Mode_Out_PP;
  56.         GPIO_Initstruction.GPIO_Pin = GPIO_Pin_11;
  57.         GPIO_Initstruction.GPIO_Speed = GPIO_Speed_10MHz;
  58.        
  59.         GPIO_Init(GPIOB, &GPIO_Initstruction);
  60.     //Echo B10
  61.         GPIO_Initstruction.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  62.         GPIO_Initstruction.GPIO_Pin = GPIO_Pin_10;
  63.        
  64.         GPIO_Init(GPIOB, &GPIO_Initstruction);
  65.        
  66.        
  67. }
  68. void Open_Tim()
  69. {
  70.        
  71.         TIM_SetCounter(TIM2, 0);
  72.         mscount = 0;
  73.        
  74.         TIM_Cmd(TIM2, ENABLE);
  75.        
  76.        
  77.        
  78. }
  79. void Close_Tim()
  80. {
  81.        
  82.         TIM_Cmd(TIM2, DISABLE);
  83.        
  84.        
  85. }
  86. //获取定时器中断的次数
  87. void TIM2_IRQHandler()
  88. {
  89. if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
  90.         {
  91.                         mscount++;
  92.                
  93.                 TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  94.         }
  95.        
  96.        
  97. }
  98. //获取总的高电平时间
  99. int Get_Echon_Time()
  100. {
  101.        
  102.         uint16_t t = 0;
  103.        
  104.         t = mscount * 1000;
  105.         t = t +TIM_GetCounter(TIM2);
  106.         delay_ms(50);
  107.        
  108.         TIM_SetCounter(TIM2, 0);
  109.         return t;
  110.                                
  111. }
  112. float Get_Length()
  113. {
  114.         float sum = 0;
  115.         uint16_t t=0;
  116.         float length = 0;
  117.     int i = 0;
  118.     while(i != 5)
  119.   {
  120.        
  121.         //1.hc04开始工作 Tring引脚输出高电平20us
  122.         GPIO_SetBits(GPIOB,  GPIO_Pin_11)
  123.        
  124.         delay_us(20);//延时20微秒
  125.        
  126.         GPIO_ResetBits(GPIOB,  GPIO_Pin_11);//然后关闭
  127.         //2.定时器计算高电平时间
  128.         while(GPIO_ReadInputDataBit(GPIOB,  GPIO_Pin_10) == 0);//当GPIO 10引脚高电平时 会卡在这
  129.         Open_Tim();//打开定时器
  130.         while(GPIO_ReadInputDataBit(GPIOB,  GPIO_Pin_10) == 1);//当高电平跳成低电平时
  131.         Close_Tim();//关闭定时器
  132.         t = Get_Echon_Time();
  133.     //3.将时间换算成距离
  134.        
  135.         length = ((float)t/58.0);
  136.                
  137.         sum = sum+length;
  138.        
  139.   }
  140.         length = sum/5.0;
  141.        
  142.         return length;
  143.        
  144.        
  145.        
  146. }
复制代码
  1. int main()
  2. {
  3.        
  4.         float length = 0;
  5.        
  6.        
  7.                 my_usart_init();
  8.                 Ch04_Init();
  9.                 Led_Init();
  10.                 Base_Tim_Init();
  11.     while (1)
  12.                 {
  13.       
  14.                        
  15.                         length = Get_Length();
  16.                         printf("%f\r\n",length);
  17.                                                
  18.                        
  19.         }
  20. }
复制代码
 通用定时输出PWM

第一步内部时钟的选择,第二步是预分频器,计数器,去设置输出 捕获和比力

定时器3的通道2 

以TIM3为例,STM32的通用定时器氛围TIM2,TIM3,TIM4,TIM5,每个定时器都有独立的四个通道可以用来作为: 输入捕获,输出比力,PWM输出,单脉冲模式输出等。

STM32的定时器除了TIM6和TIM7(根本定时器)之外,其他的定时器都可以产生PWM波输出,高级定时器TIM1,TIM8可以同时产生7路PWM输出,而通用定时器可以同时产生4路PWM输出,如许STM32可以最多同时输出30路PWM输出。

 PWM的工作原理

以向上计数为例,报告PWM原理:

①在PWM输出模式下除了CNT(计数器当前值),ARR(自动重装载值),CCRx(捕获/比力寄存器值)。

②当CNT小于CCRx时,TIMx_CHx通道输出低电平

③当CNT即是或大于CCRx时,TIMx_CHx通道输出高电平

假设ARR设置是100CRRX是80,在0加到80过程中都属于低电平,在80加到100都属于高电平,这就是一个周期,以是占空比为百分之二十,

          所谓脉宽调制信号(PWM波),就是一个TIMx_ARR自动重装载寄存器确定频率=周期的导数(由它决定PWM周期),TIM_CCRx寄存器确定占空比信号。
占空比=高电平占低电平的时间
 PWM的内部运作机制

CCR1:设置捕获比力寄存器,设置比力值。      

CCMR1寄存区:设置PWM模式1 大概PWM模式2。

CCER:  P位:输出/捕获   :设置极性: 0 高电平有用,1 低电平有用

             E位:输出/捕获   : 使能端口

PWM的模式 

模式一    边沿对齐模式

向上计数时: 当TIMx_CNT<TIMx_CCRx时通道1为有用电平,否则为无效电平;(计数值小于有用值是有用电平)

向下计数时:   一旦TIMx_CNT>TIMx_CCRx,CCR1通道1为无效电平,否则为有用电平。(计数值大于比力值为无效电平)

但是这里的有用电平是高电平还是低电平有极性( 0 高电平有用,1 低电平有用)去选择


模式二    中央对齐模式

向上计数时: 当TIMx_CNT<TIMx_CCRx时通道1为无效电平,否则为无效电平;

向下计数时:   一旦TIMx_CNT>TIMx_CCRx,CCR1通道1为有用电平,否则为无效电平。

和模式一相反

 但是这里的有用电平是高电平还是低电平有极性( 0 高电平有用,1 低电平有用)去选择
 自动加载的预加载寄存器

 

简朴的说:

APER =1 ,ARR立即见效

APER =0,ARR下个周期见效

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

 定时器输出PWM 布局体
  1. typedef struct
  2. {
  3.   uint16_t TIM_OCMode;            //配置PWM模式1还是模式2
  4.   uint16_t TIM_OutputState;       //配置输出使能/ OR失能
  5.   uint16_t TIM_OutputNState;     
  6.   uint16_t TIM_Pulse;                  //配置比较值,CCRx
  7.   uint16_t TIM_OCPolarity;         //比较输出极性
  8.   uint16_t TIM_OCNPolarity;   
  9.   uint16_t TIM_OCIdleState;  
  10.   uint16_t TIM_OCNIdleState;  
  11. } TIM_OCInitTypeDef;
复制代码
定时器输出PWM 库函数

  1. void TIM_OCxInit                      //结构体初始化
  2. (TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
  3. void TIM_SetCompare1            //设置比较值函数
  4. (TIM_TypeDef* TIMx, uint16_t Compare1);
  5. void TIM_OC1PreloadConfig     //使能输入比较预装载
  6. (TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
  7. void TIM_Cmd                            //开启定时器
  8. (TIM_TypeDef* TIMx, FunctionalState NewState)
  9. void TIM_ARRPreloadConfig     //使能自动重装载的预装载寄存器允许位
  10. (TIM_TypeDef* TIMx, FunctionalState NewState);
  11. void TIM_OC1PolarityConfig      //配置修改极性
  12. (TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
复制代码
定时器输出PWM 库函数


TIM3 PWM输出  驱动SG90电机    设置过程:

1.GPIO布局体

2.设置通用定时器布局体

3.设置定时去输出PWM布局体

4.打开时钟  ---> GPIO时钟,TIM定时器时钟,部分重映射时钟

5.设置PWM比力值

  1. void motor_config(void)
  2. {
  3.        
  4.        
  5.         GPIO_InitTypeDef GPIO_MotorInitStruct;
  6.         TIM_TimeBaseInitTypeDef TIM_MotorInit;
  7.         TIM_OCInitTypeDef TIMPWM_MotorInit;
  8.        
  9.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);
  10.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
  11.         GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);//部分重映射配置
  12.        
  13.         GPIO_MotorInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
  14.         GPIO_MotorInitStruct.GPIO_Pin = GPIO_Pin_5;
  15.         GPIO_MotorInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  16.        
  17.         GPIO_Init(GPIOB, &GPIO_MotorInitStruct);
  18.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  19.         TIM_MotorInit.TIM_ClockDivision = TIM_CKD_DIV1;       //设置时钟分割
  20.         TIM_MotorInit.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上计数模式
  21.         TIM_MotorInit.TIM_Period = 200-1;//设置下一个更新事件装入活动的自动重装载值
  22.         TIM_MotorInit.TIM_Prescaler = 7200 -1;        //分频周期
  23.         TIM_TimeBaseInit(TIM3, &TIM_MotorInit);
  24.         TIMPWM_MotorInit.TIM_OCMode = TIM_OCMode_PWM1;//选择定时器模式1
  25.         TIMPWM_MotorInit.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
  26.         TIMPWM_MotorInit.TIM_OCNPolarity = TIM_OCPolarity_Low;//选择有效输出极性
  27.        
  28.         TIM_OC2Init(TIM3, &TIMPWM_MotorInit);//因为选择的是定时器3的通道2 所以选OC2
  29.         TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
  30.         TIM_Cmd(TIM3, ENABLE);
  31.        
  32. }
复制代码
  1. void delay(uint16_t time)
  2. {
  3.    uint16_t  i=0;
  4.         while(time--)
  5.         {
  6.           i=12000;
  7.                 while(i--);
  8.        
  9.         }
  10. }
  11. int main()
  12. {
  13.        
  14.         uint16_t pwmval = 155;
  15.          motor_config();
  16.        
  17.        
  18.         while(1)
  19.                 {
  20.                         for(pwmval = 195;pwmval >= 175;pwmval-=5)
  21.                         {
  22.                                 TIM_SetCompare2(TIM3,  pwmval);
  23.                                 delay(500);
  24.                        
  25.                         }
  26.                                                
  27.                 }
  28.                        
  29. }
复制代码
  垃圾桶项目 
                                 

SG9O电机

硬件接线:

红线 : 3.3v/ 5v

黑线 : GND

黄线 : 信号线
  1. int main()
  2. {
  3.        
  4.         int  pwmval =195;
  5.         float Length =0;
  6.         Ch04_Init();       
  7.         my_usart_init();
  8.         motor_config();
  9.         while(1)
  10.         {
  11.                 pwmval =155;
  12.     Length= Get_Length();
  13.                 printf("%.3f\r\n",Length);
  14.        
  15.                
  16.                 if(Length<5)
  17.                 {
  18.                    for(pwmval=195;pwmval>=155;pwmval-=15)
  19.                         {
  20.                           TIM_SetCompare2(TIM3, pwmval);
  21.                                 delay(500);       
  22.                         }
  23.                 }
  24.                                         else if(Length>5)
  25.                         {
  26.                           TIM_SetCompare2(TIM3, pwmval-20);
  27.                        
  28.                         }
  29.         }
  30.                        
  31. }
复制代码

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表