单片机各种tim详解_tim 单片机 - CSDN
精华内容
参与话题
  • 单片机mcu—time定时器详解

    千次阅读 2017-08-25 14:47:51
    STM32的定时器分了好几个类别,各个类别针对功能作用都不大相同。 分别有: 1.高级定时器 、2.通用定时器、 3.... 4....其中看门狗定时器和SysTick定时器本篇笔记阐述,这里主要记下对平时使用定时器作用的计时计数器...

    STM32定时器分了好几个类别,各个类别针对功能作用都不大相同。

    分别有: 1.高级定时器 、2.通用定时器、 3.基本定时器、 4.看门狗定时器 、 5.SysTick定时器 

    其中看门狗定时器和SysTick定时器本篇笔记阐述,这里主要记下对平时使用定时器作用的计时计数器的一些自己的理解。 
    按照参考手册中的定义 高级定时器 通用定时器 基本定时器,这三个定时器成上下级的关系,即基本定时器有的功能通用定时器都有,而且还增加了向下、向上/向下计数器、PWM生成、输出比较、输入捕获等等功能;而高级定时器又包含了通用定时器的所有功能,另外还增加了死区互补输出、刹车信号、加入重复计数器等等。(这里等等功能请参考《STM32参考手册》) 
          所以学习STM32 定时器实际就是学习一下高级定时器,然后适当的删减后就是后面的两种定时器了。 
    假若不涉及输出输入,定时器的最基本用法就是计数定时作用了本篇笔记主要针对这部分的理解所写下的。 

    高级定时器中一共有20个寄存器: 

    TIMx_CR1、TIMx_CR2、TIMx_SMCR、TIMx_DIER、TIMx_SR、TIMx_EGR、TIMx_CCMR1、TIMx_CCMR2、 
    TIMx_CCER、TIMx_CNT、TIMx_PSC、TIMx_ARR、TIMx_RCR、TIMx_CCR1、TIMx_CCR2、TIMx_CCR3、 
    TIMx_CCR4、TIMx_BDTR、TIMx_DCR、TIMx_DMAR 
    好吧一堆寄存器光看都看到眼花缭乱了,当然不是所有寄存器都涉及到才能让定时器工作的,例如最基本的定时功能所涉及的只有几个与时基功能相关的寄存器,TIMx_CNT(计数器寄存器)、TIMx_PSC(预分频器寄存器)、TIMx_ARR(自动装载寄存器)、TIMx_RCR(重复次数寄存器)。参考手册中有那么 衣服定时器的框图。这几个寄存器的关系如图所示的: 

    CK_PSC这根时钟线上的时钟源的选择,即给定时器计数计时的时钟源的输入方式,有四种方式,分别是内部时钟,外部时钟模式1,外部时钟模式2,内部触发。这部分日后再说,这里暂且使用最常用的内部时钟方式,既是当内部时钟为72MHz 的内部时钟源。 
    如图所示的,时钟源首先进入预分频器,然后再进入预先装入自动重装载寄存器的计数器中,当计数器溢出时产生一次中断和一次事件更新。除了多了一个PSC,其他的基本和51单片机很相似,初次看参考手册中的功能描述中出现了好多次“更新事件(UEV)”。这究竟是怎么的一样东西呢? 在这里有个新概念叫“影子寄存器”,在上图中,可以看到PSC、ARR、REP(重复计数器中的低八位)这三个寄存器框框下都有个黑影,每次这三个寄存器就是影子寄存器,如果看到参考手册全图中还可以看到另外还有几个框框下也有阴影部分的,这几个寄存器也是影子寄存器。何谓影子寄存器呢,例如PSC寄存器可以理解为有两个,一个是用户可以访问到的寄存器,可读可写,另一部分就是客户访问不到的但其装载值和实际寄存器是密切关联的,当程序在运行中改写PSC 这时候影子寄存器的作用就体现了,因为立刻写入的值可能会大于或小于目前正在运行的寄存器中的数值,而真实在运行时候的正是这个影子寄存器中的值,而程序写入的是可访问的寄存器,只有当产生一个更新事件的时候影子寄存器才会读入访问寄存器中的值,这样就可以防止突然修改而产生的非正常中断或不会中断等异常问题。当然在控制器CR1中控制这个影子寄存器是否起作用,不起作用的话就是立即写入这个数值到寄存器中。

    另外高级定时器中还有RCR重复次数寄存器这个,也是比较简单的事件更新(UEV) 都是在RCR为0的情况下产生计数器溢出而产生的,当RCR中不为0的时候计数器溢出只会使得重复次数寄存器递减而不会产生UEV,这样就可以使得定时器的定时情况得以延长,而相当于有16位的分频器,16位的计数器,再加入16位的重复次数,一共48位的计数定时器。详细看参考手册,这个很好理解。 

        基本的基时单元就是上面提及的这几个,下面看看3.0库是如何实习的基本使用

    1. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 

    2.         
    3.       TIM_DeInit(TIM2);                                           //重新将Timer设置为缺省值 
    4.         
    5.       TIM_InternalClockConfig(TIM2);                              //采用内部时钟给TIM2提供时钟源       
    6.       TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1;            //预分频系数为36000-1,这样计数器时钟为72MHz/36000 = 2kHz        
    7.       TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //设置时钟分割       
    8.       TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置计数器模式为向上计数模式        
    9.       TIM_TimeBaseStructure.TIM_Period = 2000 - 1;           //设置计数溢出大小,每计2000个数就产生一个更新事件 
    10.       TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);         //将配置应用到TIM2中 
    11.       TIM_ClearFlag(TIM2, TIM_FLAG_Update);                  //清除溢出中断标志   
    12.         
    13.       TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);                //开启TIM2的中断 
    14. 以上是一个最基本的定时器配置的代码,载自网上被转载无数次的地方…… 
    15. 中断函数自己按照需求写,这里不多说。 
    16. 在库中的初始化函数和初始化数据类型有3类,TIM_TimeBaseInitTypeDef、TIM_OCInitTypeDef、TIM_ICInitTypeDef 
    17. 与基时参数相关的数据类型是TIM_TimeBaseInitTypeDef 

    18. typedef struct 

    19.   uint16_t TIM_Prescaler;     

    20.   uint16_t TIM_CounterMode;       
    21.   uint16_t TIM_Period;           

    22.   uint16_t TIM_ClockDivision;    
    23.   uint8_t TIM_RepetitionCounter; 
    24. } TIM_TimeBaseInitTypeDef;
    以上是从库stm32f10x_tim.h中 截取的代码,整体的数据结构可以中这段注释中得知,不懂E文的要么翻字典要么翻库函数中文翻译 

    版本(当然这个是2.0的库,有部分会和3.0后的版本很不相同),这部分的数据类型还是很一样的,不多说。  
    接着就是TIM_TimeBaseInit()这个函数了,在stm32f10x_tim.c的224行中 

    1. void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) 

    2.   uint16_t tmpcr1 = 0; 

    3.   /* Check the parameters */ 
    4.   assert_param(IS_TIM_ALL_PERIPH(TIMx));  
    5.   assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode)); 
    6.   assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision)); 

    7.   tmpcr1 = TIMx->CR1;   

    8.   if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)|| 
    9.      (TIMx == TIM4) || (TIMx == TIM5))  
    10.   { 
    11.     /* Select the Counter Mode */ 
    12.     tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS))); 
    13.     tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode; 
    14.   } 
    15.    
    16.   if((TIMx != TIM6) && (TIMx != TIM7)) 
    17.   { 
    18.     /* Set the clock division */ 
    19.     tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD)); 
    20.     tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision; 
    21.   } 

    22.   TIMx->CR1 = tmpcr1; 

    23.   /* Set the Autoreload value */ 
    24.   TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ; 
    25.    
    26.   /* Set the Prescaler value */ 
    27.   TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler; 
    28.       
    29.   if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx == TIM16) || (TIMx == TIM17))   
    30.   { 
    31.     /* Set the Repetition Counter value */ 
    32.     TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter; 
    33.   } 

    34.   /* Generate an update event to reload the Prescaler and the Repetition counter 
    35.      values immediately */ 
    36.   TIMx->EGR = TIM_PSCReloadMode_Immediate;            
    37. }
    可以看3.0后的函数里把所有的TIMx都加入一个函数里面做判断了,不需要和2.0的区分TIM1和TIM 两类函数,比较其基本操作都一样无非就是多了一个两个寄存器而已。
    转自芯片之家

    展开全文
  • 单片机_PWM输出原理详解

    万次阅读 多人点赞 2019-02-27 16:16:46
    单片机_PWM输出原理详解 理论篇   博主自己的经历告诉我,PWM波的理解和应用确实还是挺重要的,这里专门花一期详细介绍一下 什么是PWM?   PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是...

    单片机_PWM输出原理详解

    理论篇
      博主自己的经历告诉我,PWM波的理解和应用确实还是挺重要的,这里专门花一期详细介绍一下

    • 什么是PWM?

      PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码。
      通俗的说,就是控制在一个周期内,控制高电平多长时间,低电平多长时间(前面文章种有说过IO口就只有两种状态,0和1,对应就是0和5V或者0和3.3V)。也就是说通过调节高低电平时间的变化来调节信号、能量等的变化。
    图为周期4毫秒的PWM波形
      图为周期4毫秒的PWM波形

    • 两个重要的概念,频率、占空比

      频率是指每秒钟信号从高电平到低电平再回到高电平的次数,为一个PWM波周期的倒数。上图中频率=1/(0.003+0.001)=250 HZ
      占空比是指高电平持续时间比一个周期持续的时间。上图中占空比=1/(1+3)=25%,所以可以通过控制占空比,来控制输出的等效电压。
      所以对于方波的话,频率和占空比就确定了一个波。

    • 怎么能产生一个PWM波?

      方法1利用芯片内部模块输出PWM信号,STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样, STM32 最多可以同时产生 30 路 PWM 输出! 但是!!!同一个定时器TIM只能产生一个频率的PWM波,你只能改变占空比。 具体例程见一下实战篇STM32部分。
      方法2利用IO口高低电平转变输出PWM信号,比如上图中先把电平置1,维持1ms,然后将电平拉低,维持3ms,再将电平置高,如此循环往复下去,就可以产生一个周期4毫秒占空比为25%的PWM波了。具体方法就是给IO口加一个定时器,用定时器中断来实现及时切换高低电平。 具体历程见以下51单片机部分。

    • 定时器

      要想使用51单片机来产生一路PWM,根据上述的方法2,首先你应该知道什么是定时器?定时器是怎么工作的?

      定时器:和计数器说的是一个东西,因为它既能计时也能计数。定时器的实质是,由机器频率向一个16位寄存器累加,累加满溢出时触发中断。为了产生一个我们想要的时间间隔。比如说1s,所以我们要在这个寄存器里设定一个初值,以至于让它在这个初值上累加可以产生一个1s的倍数。这样我们就得到了稳定的时间间隔。
      这个寄存器分为TH(高八位)和TL(低八位)。所以我们需要把计算好的初值分成两部分分别放入TH和TL。

      过程
      首先,我们通过单片机的晶振频率得知其时钟周期,再尤其乘以12得到机器周期。每一个机器周期在寄存器内+1,直到加满溢出产生中断。

      举例说明
      若单片机频率为12Mhz,其时钟周期就是1/12μs,机器周期为1μs,也就是每1μs寄存器+1。16位的寄存器加到溢出最多需要(2^16)-1=65535μs,溢出也需要一个机器周期,所以总共要65536μs。但这个值太别扭,和我们要的1s没什么关系。我们最好让它记50000μs产生一次中断,所以其初值就设为65536-50000=15536。但我们还要将这个值分别放在高八位和低八位,所以要将这个十进制数,转换为4位十六进制数再分开赋值。十进制计算法:TH = 15536/256; TL = 15536%256;,进制计算问题这里不细讨论。这样的话,每50ms就会产生一次中断。我们只要用程序判断其中断20次就记1s。
      定时器部分摘自:https://www.jianshu.com/p/90ea43a7b4fd

    • PWM的应用

    1 输出模拟电压(通过电压的高低来控制如LED的亮度,直流电机的速度等)
      PWM对模拟信号电平进行数字编码的方法,计算机只能输出0或5V的数字电压值而不能输出模拟电压,而我们如果想获得一个模拟电压值(介于0 - 5V的电压值),则需通过使用高分辨率计数器,改变方波的占空比来对一个模拟信号的电平进行编码。电压是以一种连接(1)或断开(0)的重复脉冲序列被夹到模拟负载上去的,连接即是直流供电输出,断开即是直流供电断开。通过对连接和断开时间的控制,只要带宽足够,可以输出任意不大于最大电压值的模拟电压。

      输出电压=(接通时间/脉冲时间)*最大电压值12

    PWM输出等效电压
       PWM输出等效电压
    解释部分引自 http://www.eeworld.com.cn/mcu/article_2018061939827.html

    2 控制舵机
      大一大二期间做项目经常用到的一个元件就是舵机,而舵机的控制就是通过一个固定周期但是不同占空比来控制舵机摆角的位置的。
      舵机的控制一般需要一个20ms左右的时基脉冲(频率为50HZ),该脉冲的高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分,总间隔为2ms。以180度角度伺服为例,那么对应的控制关系是这样的:
    0.5ms--------------0度;
    1.0ms------------45度;
    1.5ms------------90度;
    2.0ms-----------135度;
    2.5ms-----------180度;
    在这里插入图片描述
    此图可以表现脉冲宽度(也可以转换成占空比)和舵机摆臂的位置图
    3 控制步进电机
      之前在做项目的过程中,一般涉及到精确控制位移的时候,这个时候往复式驱动原件(舵机)就不适合了,所以就会经常用到步进电机。
      步进电机把电脉冲信号变换成角位移以控制转子转动的微特电机。在自动控制装置中作为执行元件。每输入一个脉冲信号,步进电动机前进一步,故又称脉冲电动机。 !!!这里注意一点,直接控制单片机的话是脉冲控制,就是进来一个脉冲信号,步进电机转动一个步进角(一般为1.8°)。所以控制步进电机速度的方式就是通过控制 频率 (占空比一般都是50%)但是!!!现在可以通过接入步进电机驱动板的方式(比如博主之前使用的一款步进电机驱动板Tb6560)细分步进角。比如细分为2,一个脉冲步进电机就转动半个脉冲(0.9°)

    PS:这里由于篇幅原因,舵机、步进电机的控制代码就不上传了,网上一搜一大堆,也可以联系博主私法给你喽!


    实战篇

      这里使用51和STM32实现呼吸灯的功能,同样原理也可以控制直流电机,舵机是频率一定的情况下控制占空比来控制摆臂的方向,而步进电机是通过控制频率的方式来控制速度。

    51部分
      例程使用51单片机将P1.0接一个二极管。运用PWM输出等效模拟电压完成呼吸灯功能。引

    unsigned char PWM_COUNT;  //计数
    unsigned int  HUXI_COUNT;    //占空比更新时间
    unsigned char PWM_VLAUE;    //占空比比对值
    bit direc_flag;             //占空比更新方向
    
    void timer0_init()
    {
        TMOD=0x02;          //模式设置,00010000,定时器0,工作于模式2(M1=1,M0=0)
        TH0=0x47;               //定时器溢出值设置,每隔200us发起一次中断。
        TL0=0X47;
        TR0=1;                  //定时器0开始计时
        ET0=1;                  //开定时器0中断
        EA=1;                       //开总中断
        PWM_COUNT =0;
    }
    
    void time0() interrupt 1
    {   
        PWM_COUNT++;
        HUXI_COUNT++;
        if(PWM_COUNT == PWM_VLAUE)      //判断是否到了点亮LED的时候
            LED = 1;                    //点亮LED
        if(PWM_COUNT == 10)             //当前周期结束
        {
            LED = 0;                    //熄灭LED
            PWM_COUNT = 0;              //重新计时
        }
    
        if((HUXI_COUNT == 600) && (direc_flag == 0))
        {                               //占空比增加10%
            HUXI_COUNT = 0;
            PWM_VLAUE++;
            if(PWM_VLAUE == 9)          //占空比更改方向
                direc_flag = 1; 
        }
    
        if((HUXI_COUNT == 600) && (direc_flag == 1))
        {                               //占空比减少10%
            HUXI_COUNT = 0;
            PWM_VLAUE--;
            if(PWM_VLAUE == 1)          //占空比更改方向
                direc_flag = 0; 
        }   
    }
    void main()
    {
        HUXI_COUNT = 0;
        PWM_COUNT = 0;
        PWM_VLAUE = 5;
        direc_flag = 0;
        LED = 1;            //默认LED熄灭   
        timer0_init();      //定时器0初始化
        while(1);
    }
    

      例程部分引自 http://www.eeworld.com.cn/mcu/article_2018061939827.html 有删改

    32部分
      转自正点原子库函数手册PWM部分教程
      这里用到了 TIM3 的部分重映射功能(重映射:可以理解成把管脚的外设功能映射到另一个管脚,具体哪个引脚可以映射见参考手册), 例程把 TIM3_CH2 直接映射到了 PB5 上。

    //TIM3 PWM 部分初始化
    //PWM 输出初始化
    //arr:自动重装值
    //psc:时钟预分频数
    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); //②重映射 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; //设置预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //③初始化 TIMx
        //初始化 TIM3 Channel2 PWM 模式
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高
        TIM_OC2Init(TIM3, &TIM_OCInitStructure); //④初始化外设 TIM3 OC2
        TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能预装载寄存器
        TIM_Cmd(TIM3, ENABLE); //⑤使能 TIM3
    }
    
    
    int main(void)
    {
        u16 led0pwmval=0;
        u8 dir=1;
        delay_init(); //延时函数初始化
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置 NVIC 中断分组 2
        uart_init(115200); //串口初始化波特率为 115200
        LED_Init(); //LED 端口初始化
        TIM3_PWM_Init(899,0); //不分频,PWM 频率=72000/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);
        }
    }
    //实验现象:我们将看 DS0 不停的由暗变到亮,然后又从亮变到暗。每个过程持续时间大概为 3 秒钟左右。
    

    皮一下,欢迎交流啊! 共同学习,共同进步。
    在这里插入图片描述

    展开全文
  • STM32 TIM定时器 库函数学习笔记

    千次阅读 2019-07-10 10:18:15
    一些库函数的用法手册上讲得不甚详细,网上也几乎没有资料,把我个人搜集到的一些东西... TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period = 10000-1; //设置在下一个更新...

    一些库函数的用法手册上讲得不甚详细,网上也几乎没有资料,把我个人理解的一些东西和大家分享一下,如有错漏请批评指正。

     	TIM_DeInit(TIM2);
    	//注意:按缺省值复位后,时钟源为内部时钟,不必再调用函数设置。如需要更改定时器计时的时钟源,
    	//调用后面的那几个相关函数就行。定时器的时钟不是直接来自APB1/2,而是来自于输入为APB1/2的一个倍频器。
    	//当APB1/2的预分频系数为1时,定时器的时钟频率等于APB1/2的频率;
    	//当APB1/2的预分频系数为其它数值时,定时器的时钟频率等于APB1/2的频率两倍。
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    	
    	TIM_TimeBaseStructure.TIM_Period = 10000-1;
    	//设置在下一个更新事件装入活动的自动重装载寄存器周期的值
    	//由于计数从0开始,所以此处应为理想周期减1,最大值为0xFFFF
    	TIM_TimeBaseStructure.TIM_Prescaler = 0xF;
    	//设置用来作为TIMx时钟频率除数的预分频值,最大值为0xFFFF
    	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    	//设置定时器输入频率fCK_INT与数字滤波器采样频率基准fDTS使用的采样频率之间的分频比例
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    	//中央对齐模式1 计数器交替地向上和向下计数。输出比较中断标志位,只在计数器向下计数时被设置
      //中央对齐模式2 计数器交替地向上和向下计数。输出比较中断标志位,只在计数器向上计数时被设置
      //中央对齐模式3 计数器交替地向上和向下计数。输出比较中断标志位,只在计数器向下和向上计数时均被设置
    	
    	TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);
    	
    	
    	TIM_OCInitTypeDef TIM_OCInitStructure;
    	
    	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//设置输出模式
    	//TIM_OCMode_Timing:  比较成功后不在对应输出管脚上产生输出(输出引脚冻结,可另作他用),但产生中断,用来作软件定时器用。
      //TIM_OCMode_Toggle:  比较成功后翻转对应输出管脚上的电平。
    	//TIM_OCMode_Active:  输出比较主动模式,匹配时设置输出引脚为有效电平,当计数值为比较/捕获寄存器值相同时,强制输出为高电平
    	//TIM_OCMode_Inactive:输出比较非主动模式,匹配时设置输出引脚为无效电平,当计数值为比较/捕获寄存器值相同时,强制输出为低电平
    	//TIM_OCMode_PWM1:    当计时器值小于比较器设定值时则TIMX输出脚此时输出有效高电位。
      //                     当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出低电位。
      //TIM_OCMode_PWM2时:  与TIM_OCMode_PWM1相反
    	
    	TIM_OCInitStructure.TIM_Pulse=0xFFFF;//设置输出脉宽,最大只能取0xFFFF
      TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//使能输出
    	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//设置输出极性
    //	TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_High;
    //	//指定TIM互补输出引脚的在比较有效时的输出电平。仅供高级定时器有效。
    //	TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable;	
    //	//使能或使能TIM的互补输出。仅供高级定时器有效	
    //	TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Set;
    //	TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Reset;
    //	//指定在空闲状态下的TIM输出比较引脚的状态。仅供高级定时器有效。
    	
    	TIM_OC1Init(TIM2, & TIM_OCInitStructure);//使用哪个通道,就把前面的OCxInit改成几
    	
    	TIM_ICInitTypeDef TIM_ICInitStructure;
    
    	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//选择通道。
    	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//选择输入捕获的边沿
    	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    //	TIM_ICSelection_DirectTI   TIM输入1,2,3或4与IC1或IC2或IC3或IC4相连
    //	TIM_ICSelection_IndirectTI TIM输入1,2,3或4与IC2或IC1或IC4或IC3相连
    //	TIM_ICSelection_TRC        TIM输入1,2,3或4与TRC(内部触发)相连。
    	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//设置输入捕获预分频器
    	TIM_ICInitStructure.TIM_ICFilter = 0x0;
    	//选择输入比较滤波器。该参数取值在0x0和0xF
    	//不同的取值代表着不同的采样频率和带宽,详见手册336页表
    	//实际采样频率fSAMPLING不一定等于采样频率基准fDTS
    	TIM_ICInit(TIM2, &TIM_ICInitStructure);
      //TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
      //新版函数库里取消了TIM_ICMode,TIM_ICInit()默认为输入捕获模式ICAP
    	//如果使用PWM输入模式,要用TIM_PWMIConfig()来初始化
    	
    
      TIM_Cmd(TIM2, ENABLE);
    	
    	TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE );
    	//TIM_IT_Update:  更新事件:计数器上溢/下溢,计数器初始化(由软件或内部/外部触发)
    	//TIM_IT_CC1:     通道1输入捕获/输出比较
    	//TIM_IT_CC2:     通道2输入捕获/输出比较
    	//TIM_IT_CC3:     通道3输入捕获/输出比较
    	//TIM_IT_CC4:     通道4输入捕获/输出比较
    	//TIM_IT_COM:     TIM Commutation Interrupt source
    	//TIM_IT_Trigger: 触发事件:计数器开始、停止、初始化或由内部/外部触发计数
    	//TIM_IT_Break:   打断输入
    	
    	TIM_InternalClockConfig(TIM2);
    	//禁止从模式,用内部时钟直接驱动定时器的预分频器
    	
    	TIM_ITRxExternalClockConfig(TIM2, TIM_TS_ITR3);
    	//设置定时器工作于从模式,时钟源为其他定时器的输出分频.此时钟源无滤波
    	//TIM_TS_ITR0 TIM内部触发0 TIM1
    	//TIM_TS_ITR1 TIM内部触发1 TIM2
    	//TIM_TS_ITR2 TIM内部触发2 TIM3
    	//TIM_TS_ITR3 TIM内部触发3 TIM4
    	
    	TIM_TIxExternalClockConfig(TIM2, TIM_TS_TI1FP1,TIM_ICPolarity_Rising, 0);
    	//设置 TIMx 触发为外部时钟(从四个通道引脚引入)
      //触发源选择:
      //TIM_TIxExternalCLK1Source_TI1ED:  未经滤波的Timer Input 1
      //TIM_TIxExternalCLK1Source_TI1:    滤波后的Timer Input 1
      //TIM_TIxExternalCLK1Source_TI2:    滤波后Timer Input 2
      //设置输入捕获的边沿:
      //TIM_ICPolarity_Rising
      //TIM_ICPolarity_Falling
      //设置滤波设置:
      //必须在0x0与0xF之间
    	
    	TIM_ETRClockMode1Config(TIM2, TIM_ExtTRGPSC_DIV2,TIM_ExtTRGPolarity_NonInverted, 0x0);
      //外部时钟模式1.需要设置预分频,以及外部触发极性:
      //TIM_ExtTRGPolarity_Inverted     TIM外部触发极性翻转:  低电平或下降沿有效
      //TIM_ExtTRGPolarity_NonInverted  TIM外部触发极性非翻转:高电平或上升沿有效
    	//最后要设置滤波环节。
    	
    	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_DIV2,TIM_ExtTRGPolarity_NonInverted, 0x0);
    	//外部时钟模式2.
    	
    
    	//通用定时器的计数时钟有三种:
    	//内部时钟(CK_INT)
    	//外部时钟源,包括:
    	//外部时钟模式1 外部输入脚(TIx)  
    	//外部时钟模式2 外部触发输入(ETR) 
    	//内部触发输入(ITRx) 这三种
    	//ETR仅用于外部触发,CHx还可以输出PWM,ETR是不可能输出PWM的。
    	
    	//这个函数后面的一些函数大部分是为实现上述功能而需要调用的底层函数,不需要熟练掌握
    	
    	TIM_ARRPreloadConfig(TIM2, ENABLE);
    	//使能预装载寄存器后其与影子寄存器间将不再是立即写入的关系,而是等更新事件产生后才写入
    	//输入捕获和输出比较相关的预装载寄存器同理
    	
    	
    	TIM_OC1FastConfig(TIM2, TIM_OCFast_Enable);
    	//输出比较快速特征性能用在缩短单脉冲输出模式时的最小输出延迟
    	//失能时,由于从激励进入到打开计数器需要时间,因此最小延迟为5个时钟周期
    	//使能后,一旦有激励进入,将立即输出活动电平,而不管比较结果如何。延迟被缩短为3个时钟周期
    	//必须将通道配置为PWM模式此设置才有作用
    
    展开全文
  • STM32系统学习——TIM(基本定时器)

    万次阅读 多人点赞 2017-12-11 10:22:19
    基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部 IO。通用定时器 TIM2/3/4/5 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个...

    一、定时器分类
    STM32F1 系列中,除了互联型的产品,共有 8 个定时器,分为基本定时器,通用定时器和高级定时器。基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部 IO。通用定时器 TIM2/3/4/5 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部 IO。高级定时器 TIM1/8是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有 8 个外部 IO。
    这里写图片描述

    二、功能框图剖析
    这里写图片描述
    基本定时器的核心是时基,通用计时器和高级定时器也有。
    1、时钟源
    定时器时钟TIMxCLK,即内部时钟CK_INT,经APB1预分频器后分频提供,如果APB1 预分频系数等于 1,则频率不变,否则频率乘以 2,库函数中 APB1 预分频的系数是 2,即 PCLK1=36M,所以定时器时钟 TIMxCLK=36*2=72M 。
    2、计数器时钟
    定时器时钟经过 PSC 预分频器之后,即 CK_CNT,用来驱动计数器计数。PSC 是一个16 位的预分频器,可以对定时器时钟 TIMxCLK 进行 1~65536 之间的任何一个数进行分频。
    具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)。
    3.计数器
    计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。
    4、自动重装载寄存器
    自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。
    5. 定时时间的计算
    定时器的定时时间等于计数器的中断周期乘以中断的次数。计数器在 CK_CNT 的驱动下,计一个数的时间则是 CK_CLK 的倒数,等于:1/(TIMxCLK/(PSC+1)),产生一次中断的时间则等于:1/(CK_CLK * ARR)。如果在中断服务程序里面设置一个变量 time,用来记录中断的次数,那么就可以计算出我们需要的定时时间等于: 1/CK_CLK *(ARR+1)*time。
    三、定时器初始化结构体详解
    在标准库函数头文件stm32f10x_tim.h中对定时器外设建立了四个初始化结构体,基本定时器只用到其中一个即TIM_TimeBaseInitTypeDef,其他三个在高级定时器章节讲解。

     typedef struct {
     uint16_t TIM_Prescaler; // 预分频器
     uint16_t TIM_CounterMode; // 计数模式
     uint32_t TIM_Period; // 定时器周期
     uint16_t TIM_ClockDivision; // 时钟分频
     uint8_t TIM_RepetitionCounter; // 重复计算器
     } TIM_TimeBaseInitTypeDef;

    (1) TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定TIMx_PSC 寄存器的值。可设置范围为 0 至 65535,实现 1至 65536 分频。
    (2) TIM_CounterMode:定时器计数方式,可是在为向上计数、向下计数以及三种中心对齐模式。基本定时器只能是向上计数,即 TIMx_CNT只能从 0开始递增,并且无需初始化。
    (3) TIM_Period:定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为 0至 65535。
    (4) TIM_ClockDivision:时钟分频,设置定时器时钟 CK_INT 频率与数字滤波器采样时钟频率分频比,基本定时器没有此功能,不用设置。
    (5) TIM_RepetitionCounter:重复计数器,属于高级控制寄存器专用寄存器位,利用它可以非常容易控制输出 PWM 的个数。这里不用设置。
    虽然定时器基本初始化结构体有 5 个成员,但对于基本定时器只需设置其中两个就可以。
    四、基本定时器实验
    本实验利用基本定时器 TIM6/7 定时 1s,1s 时间到 LED 翻转一次。基本定时器是单片机内部的资源,没有外部 IO,不需要接外部电路,现只需要一个 LED 即可 。
    软件设计
    编写两个定时器驱动文件,bsp_TiMbase.h 和bsp_TiMbase.h,用来配置定时器中断优先级和和初始化定时器 。

    1、 编程要点
    (1) 开定时器时钟 TIMx_CLK, x[6,7] ;
    (2) 初始化时基初始化结构体 ;
    (3) 使能 TIMx, x[6,7] update 中断;
    (4) 打开定时器;
    (5) 编写中断服务程序
    通用定时器和高级定时器的定时编程要点跟基本定时器差不多,只是还要再选择下计数器的计数模式,是向上还是向下。因为基本定时器只能向上计数,且没有配置计数模式的寄存器,默认是向上。
    2.、软件分析
    基本 定时器宏定义

    1 /********************基本定时器 TIM 参数定义,只限 TIM6、7************/
    2 #define BASIC_TIM6 // 如果使用 TIM7,注释掉这个宏即可
    3 
    4 #ifdef BASIC_TIM6 // 使用基本定时器 TIM6
    5 #define BASIC_TIM TIM6
    6 #define BASIC_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
    7 #define BASIC_TIM_CLK RCC_APB1Periph_TIM6
    8 #define BASIC_TIM_IRQ TIM6_IRQn
    9 #define BASIC_TIM_IRQHandler TIM6_IRQHandler
    10 
    11 #else // 使用基本定时器 TIM7
    12 #define BASIC_TIM TIM7
    13 #define BASIC_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
    14 #define BASIC_TIM_CLK RCC_APB1Periph_TIM7
    15 #define BASIC_TIM_IRQ TIM7_IRQn
    16 #define BASIC_TIM_IRQHandler TIM7_IRQHandler
    17 
    18 #endif

    基本定时器有 TIM6 和 TIM7,我们可以有选择的使用,为了提高代码的可移植性,我们把当需要修改定时器时需要修改的代码定义成宏,默认使用的是定时器 6,如果想修改成定时器 7,只需要把宏 BASIC_TIM6 注释掉即可。

    基本定时器设定

    void BASIC_TIM_Config(void)
    2 {
    3 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    4 
    5 // 开启定时器时钟,即内部时钟 CK_INT=72M
    6 BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE);
    7 
    8 // 自动重装载寄存器周的值(计数值)
    9 TIM_TimeBaseStructure.TIM_Period=1000;
    10 
    11 // 累计 TIM_Period 个频率后产生一个更新或者中断
    12 // 时钟预分频数为 71,则驱动计数器的时钟 CK_CNT = CK_INT / (71+1)=1M
    13 TIM_TimeBaseStructure.TIM_Prescaler= 71;
    14 
    15 // 时钟分频因子 ,基本定时器没有,不用管
    16 //TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    17 
    18 // 计数器计数模式,基本定时器只能向上计数,没有计数模式的设置
    19 //TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
    20 
    21 // 重复计数器的值,基本定时器没有,不用管
    22 //TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
    23 
    24 // 初始化定时器
    25 TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure);
    26 
    27 // 清除计数器中断标志位
    28 TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);
    29 
    30 // 开启计数器中断
    31 TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);
    32 
    33 // 使能计数器
    34 TIM_Cmd(BASIC_TIM, ENABLE);
    35 
    36 // 暂时关闭定时器的时钟,等待使用
    37 BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, DISABLE)
    38 }

    我们把定时器设置自动重装载寄存器 ARR 的值为 1000,设置时钟预分频器为 71,则驱动计数器的时钟:CK_CNT = CK_INT / (71+1)=1M,则计数器计数一次的时间等于:1/CK_CNT=1us,当计数器计数到 ARR 的值 1000 时,产生一次中断,则中断一次的时间为:1/CK_CNT*ARR=1ms。
    在初始化定时器的时候,我们定义了一个结构体:TIM_TimeBaseInitTypeDef,TIM_TimeBaseInitTypeDef 结构体里面有 5 个成员,TIM6 和 TIM7 的寄存器里面只有TIM_Prescaler 和 TIM_Period,另外三个成员基本定时器是没有的,所以使用 TIM6 和TIM7的时候只需初始化这两个成员即可, 另外三个成员是通用定时器和高级定时器才有,具体说明如下:

    1 typedef struct {
    2 TIM_Prescaler // 都有
    3 TIM_CounterMode // TIMx,x[6,7]没有,其他都有
    4 TIM_Period // 都有
    5 TIM_ClockDivision // TIMx,x[6,7]没有,其他都有
    6 TIM_RepetitionCounter // TIMx,x[1,8,15,16,17]才有
    7 } TIM_TimeBaseInitTypeDef;

    定时器中断优先级配置

    1 // 中断优先级配置
    2 void BASIC_TIM_NVIC_Config(void)
    3 {
    4 NVIC_InitTypeDef NVIC_InitStructure;
    5 // 设置中断组为 0
    6 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    7 // 设置中断来源
    8 NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM_IRQ ;
    9 // 设置主优先级为 0
    10 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    11 // 设置抢占优先级为 3
    12 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    13 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    14 NVIC_Init(&NVIC_InitStructure);
    15 }

    定时器中断服务程序

    1 void BASIC_TIM_IRQHandler (void)
    2 {
    3 if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET ) {
    4 time++;
    5 TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update);
    6 }
    7 }

    定时器中断一次的时间是 1ms,我们定义一个全局变量 time,每当进一次中断的时候,让 time 来记录进入中断的次数。如果我们想实现一个 1s 的定时,我们只需要判断time 是否等于 1000 即可,1000 个 1ms 就是 1s。然后把 time 清 0,重新计数,以此循环往复。在中断服务程序的最后,要把相应的中断标志位清除掉,切记。

    主函数

    1 int main(void)
    2 {
    3 /* led 端口配置 */
    4 LED_GPIO_Config();
    5 
    6 /* 基本定时器 TIMx,x[6,7] 定时配置 */
    7 BASIC_TIM_Config();
    8 
    9 /* 配置基本定时器 TIMx,x[6,7]的中断优先级 */
    10 BASIC_TIM_NVIC_Config();
    11 
    12 /* 基本定时器 TIMx,x[6,7] 重新开时钟,开始计时 */
    13 BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE);
    14 
    15 while (1) {
    16 if ( time == 1000 ) { /* 1000 * 1 ms = 1s 时间到 */
    17 time = 0;
    18 /* LED1 取反 */
    19 LED1_TOGGLE;
    20 }
    21 }
    22 }

    函数做一些必须的初始化,然后在一个死循环中不断的判断 time 的值,time 的值在定时器中断改变,每加一次表示定时器过了 1ms,当 time 等于 1000 时,1s 时间到,LED1翻转一次,并把 time 清 0。

    四、思考
    1. 计算基本定时器一次最长定时时间,如果需要使用基本定时器产生 100s 周期事件有什么办法实现?
    2. 修改实验程序,在保使其每 0.5s 翻转一次 LED1的同时在每 10s 翻转 LED2。

    引用《STM32库开发实战指南》

    展开全文
  • 简述单片机

    2016-12-19 16:36:36
    本人毕业三年半,从一个什么都不懂的小白,走到今天,由于性格(按照别人的话来说,就是比较纠结)的原因,浪费很多时间在一些无用的事物上,导致...- 单片机(freescale) - 上位机(MFC/Qt) - Simulink/StateFlo
  • 学习笔记之-51单片机定时计数器

    千次阅读 多人点赞 2017-02-12 16:51:30
    一、单片机的时序 单片机工作时,是在统一的时钟脉冲控制下一拍一拍地进行的。由于指令的字节数不同,取这些指令所需要的时间也就不同,即使是字节数相同的指令,由于执行操作有较大的差别,不同的指令执行时间也不...
  • 在STM32中,基本定时器有TIM6、TIM7等。基本定时器主要包含时基单元,提供16位的计数,能计数0~65535。基本定时器除了计数功能以外,还能输出给DAC模块一个TRGO信号。基本定时器框图如下: 二、时基单元介绍 STM32...
  • 单片机程序构架

    千次阅读 2017-12-05 11:23:27
    似乎软件架构,只有纯上位机软件才有,其实,嵌入式软件也有架构可言,只有好的架构,才能结构清晰,方便开发和让系统稳定的工作。在有嵌入式操作系统的情况下,可以利用多任务和信号量,事件等设计嵌入式软件。...
  • stm32高级定时器PWM互补输出+死区插入使用详解意法半导体开发的stm32系列单片机功能强大,其高级定时器TIM1和TIM8功能强大,配置较繁琐,本文介绍使用标准库进行配置的过程。 标准库例程int main(void) { /*!,
  • STM32之TIM 舵机控制PWM

    万次阅读 多人点赞 2019-07-03 15:07:52
    定时器初始化结构体详解 1. TIM_TimeBaseInitTypeDef 定时器基本初始化结构体 TIM_OCInitTypeDef 定时器比较输出初始化结构体 3. TIM_ICInitTypeDef 4. TIM_BDTRInitTypeDef PWM 互补输出实验 使用STM32控制...
  • 库函数详解 该内核库下面有三个文件夹,三个文件,以下代码都是从KEIL中直接拿出来的源码,所以格式啥的都或多或少发生了变化,注重体验感直接去看KEIL工程里看。 include_main.h 该文件是管理工程头文件包含的,...
  • 前两个是地址,后两个是每个地址里边的具体的情况。比如要初始化了,就这样写 void Ds1302Init() { uchar n; Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能... Ds1302Write(WRITE_RTC_ADDR[n],TIM...
  • STM32F103定时器详解

    万次阅读 2019-04-07 20:50:00
    STM32F103系列的单片机一共有11个定时器,其中: 2个高级定时器 4个普通定时器 2个基本定时器 2个看门狗定时器 1个系统嘀嗒定时器 除去看门狗定时器和系统滴答定时器的八个定时器列表; 8个定时器分成3...
  • Stm32学习笔记三————定时器TIM

    千次阅读 2019-07-15 23:14:35
    STM32F103系列的单片机一共有11个定时器,其中: 2个高级定时器 4个普通定时器 2个基本定时器 2个看门狗定时器 1个系统嘀嗒定时器 除去看门狗定时器和系统滴答定时器的八个定时器又可以分成3个组; ...
  • STM32开发 -- 串口详解

    万次阅读 多人点赞 2019-04-25 21:59:51
    讲完GPIO,接下来看一下串口。 未完待续!!
  • STM32通用定时器使用详解

    万次阅读 多人点赞 2019-06-29 19:12:46
    通用定时器包括TIM2、TIM3、TIM4和TIM5 STM32通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成。 每个定时器都是完全独立的,没有互相共享任何资源。它们可以一起同步操作。 定时器可以进行定时器...
  • 详解51单片机播放音乐、电子琴、快进

    千次阅读 多人点赞 2013-07-15 18:30:04
    这是在学习完51之后做的一个实验,现在再来看有些寄存器都不记得了。不过我还是想要把它记录下来——因为我热爱音乐。 1.效果 先来看看实验的仿真图吧: 从按键就可以看到,这个实验可以实现播放音乐,暂停音乐,...
  • STM32CubeMX和HAL库踩坑记——DMA+TIM输出比较模式1、CubeMX配置1.1 基本设置1.2时钟配置1.3 具体配置2 代码2.1使能2.2调试2.3中断回调函数 目的:让单片机输出一段可调频率的脉冲,用于驱动步进电机。 方案:1、...
  • 1.GPIO初始化函数 用法: voidGPIO_Configuration(void) { GPIO_InitTypeDefGPIO_InitStructure;//GPIO状态恢复默认参数 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_标号|GPIO_Pin_标号; //管脚位置定义,标号可以是NONE...
  • stm32f103的11个定时器详解

    千次阅读 2017-01-23 14:01:29
    STM32F103系列的单片机一共有11个定时器,其中: 2个高级定时器 4个普通定时器 2个基本定时器 2个看门狗定时器 1个系统嘀嗒定时器 除去看门狗定时器和系统滴答定时器的八个定时器列表: 8个定时器分成3个组; ...
1 2 3 4 5 ... 14
收藏数 274
精华内容 109
关键字:

单片机各种tim详解