zoukankan      html  css  js  c++  java
  • [原创] STM32 定时器TIMx 编码器应用 函数 TIM_EncoderInterfaceConfig 分析

    今天把STM32 定时器输入作为 编码器接口相关的 函数   TIM_EncoderInterfaceConfig ,好好分析了一遍

    因为网上不少人对这个函数有问题

      1 void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
      2                                 uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
      3 {
      4   uint16_t tmpsmcr = 0;
      5   uint16_t tmpccmr1 = 0;
      6   uint16_t tmpccer = 0;
      7   
      8   /* Get the TIMx SMCR register value */
      9   tmpsmcr = TIMx->SMCR;
     10   
     11   /* Get the TIMx CCMR1 register value */
     12   tmpccmr1 = TIMx->CCMR1;
     13   
     14   /* Get the TIMx CCER register value */
     15   tmpccer = TIMx->CCER;
     16   
     17   /* Set the encoder Mode */
     18   tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS));  //0x0007    //关闭从模式
     19   
     20     //#define  TIM_SMCR_SMS                        ((uint16_t)0x0007)            /*!< SMS[2:0] bits (Slave mode selection) */
     21     //#define  TIM_SMCR_SMS_0                      ((uint16_t)0x0001)            /*!< Bit 0 */
     22     //#define  TIM_SMCR_SMS_1                      ((uint16_t)0x0002)            /*!< Bit 1 */
     23     //#define  TIM_SMCR_SMS_2                      ((uint16_t)0x0004)            /*!< Bit 2 */
     24     //0x0007 -> 0b0000 0000 0000 0111 -> 位取反 -> 0b1111 1111 1111 1000 ->再与,也就是把 tmpsmcr[2:0]置0
     25     //tmpsmcr[2:0]置0 , 就是TIMx->SMCR[2:0] =000 , 
     26     /*
     27         SMCR[2:0]  SMS:从模式选择
     28         当选择了外部信号,触发信号(TRGI)的有效边沿与选中的外部输入极性相关(见输入控制寄存器
     29         和控制寄存器的说明)
     30         000:关闭从模式 – 如果CEN=1,则预分频器直接由内部时钟驱动。
     31         001:编码器模式1 – 根据TI1FP1的电平,计数器在TI2FP2的边沿向上/下计数。
     32         010:编码器模式2 – 根据TI2FP2的电平,计数器在TI1FP1的边沿向上/下计数。
     33         011:编码器模式3 – 根据另一个输入的电平,计数器在TI1FP1和TI2FP2的边沿向上/下计数。
     34         100:复位模式 – 选中的触发输入(TRGI)的上升沿重新初始化计数器,并且产生一个更新寄存
     35         器的信号。
     36         101:门控模式 – 当触发输入(TRGI)为高时,计数器的时钟开启。一旦触发输入变为低,则计
     37         数器停止(但不复位)。计数器的启动和停止都是受控的。
     38         110:触发模式 – 计数器在触发输入TRGI的上升沿启动(但不复位),只有计数器的启动是受控
     39         的。
     40         111:外部时钟模式1 – 选中的触发输入(TRGI)的上升沿驱动计数器。
     41         注:如果TI1F_EN被选为触发输入(TS=100)时,不要使用门控模式。这是因为, TI1F_ED在每
     42         次TI1F变化时输出一个脉冲,然而门控模式是要检查触发输入的电平。
     43     */
     44   
     45     //#define TIM_EncoderMode_TI1                ((uint16_t)0x0001)
     46     //#define TIM_EncoderMode_TI2                ((uint16_t)0x0002)
     47     //#define TIM_EncoderMode_TI12               ((uint16_t)0x0003)   
     48     
     49   tmpsmcr |= TIM_EncoderMode; //0x0003 
     50     //SMCR[2:0]  SMS:从模式选择  
     51     //011:编码器模式3 – 根据另一个输入的电平,计数器在TI1FP1和TI2FP2的边沿向上/下计数。
     52   
     53 
     54   
     55   /* Select the Capture Compare 1 and the Capture Compare 2 as input */
     56      //#define  TIM_CCMR1_CC1S   ((uint16_t)0x0003)            /*!< CC1S[1:0] bits (Capture/Compare 1 Selection) */
     57     //#define  TIM_CCMR1_CC2S   ((uint16_t)0x0300)            /*!< CC2S[1:0] bits (Capture/Compare 2 Selection) */ 
     58   tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC1S)) & (uint16_t)(~((uint16_t)TIM_CCMR1_CC2S)));
     59   //简化一下   
     60   //tmpccmr1 &= (    (~(TIM_CCMR1_CC1S))       &       (~(TIM_CCMR1_CC2S))          );
     61   //(~(TIM_CCMR1_CC1S)) = ~0x0003 = 0b1111 1111 1111 1100
     62   //(~(TIM_CCMR1_CC2S)) = ~0x0300 = 0b1111 1100 1111 1111
     63   //上面两个先位与 , 得到 ---------0b1111 1100 1111 1100
     64   //tmpccmr1 =tmpccmr1 & 0b1111 1100 1111 1100   -->  CCMR1[9:8]=00 ; CCMR1[1:0] = 00 
     65   /*
     66     CCMR1[9:8] --> CC2S[1:0]:捕获/比较2选择。
     67     该位定义通道的方向(输入/输出),及输入脚的选择:
     68     00: CC2通道被配置为输出;
     69     01: CC2通道被配置为输入, IC2映射在TI2上;
     70     10: CC2通道被配置为输入, IC2映射在TI1上;
     71     11: CC2通道被配置为输入, IC2映射在TRC上。此模式仅工作在内部触发器输入被选中时(由
     72     TIMx_SMCR寄存器的TS位选择)。
     73     注: CC2S仅在通道关闭时(TIMx_CCER寄存器的CC2E=0)才是可写的。
     74 
     75     CCMR1[1:0] --> CC1S[1:0]:捕获/比较1 选择。
     76     这2位定义通道的方向(输入/输出),及输入脚的选择:
     77     00: CC1通道被配置为输出;
     78     01: CC1通道被配置为输入, IC1映射在TI1上;
     79     10: CC1通道被配置为输入, IC1映射在TI2上;
     80     11: CC1通道被配置为输入, IC1映射在TRC上。此模式仅工作在内部触
     81     TIMx_SMCR寄存器的TS位选择)。
     82     注: CC1S仅在通道关闭时(TIMx_CCER寄存器的CC1E=0)才是可写的。
     83   */
     84   
     85   
     86   
     87     //#define  TIM_CCMR1_CC1S_0     ((uint16_t)0x0001)            /*!< Bit 0 */
     88     //#define  TIM_CCMR1_CC2S_0     ((uint16_t)0x0100)            /*!< Bit 0 */  
     89   tmpccmr1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
     90   // tmpccmr1 = tmpccmr1 | TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
     91   // TIM_CCMR1_CC1S_0 = 0b0000 0000 0000 0001
     92   // TIM_CCMR1_CC2S_0 = 0b0000 0001 0000 0000
     93   
     94   // tmpccmr1 -> CCMR1[9:8]=01 ; CCMR1[1:0] = 01 
     95   // CCMR1[9:8]        01: CC2通道被配置为输入, IC2映射在TI2上;
     96   // CCMR1[1:0]       01: CC1通道被配置为输入, IC1映射在TI1上;
     97   
     98   
     99   /* Set the TI1 and the TI2 Polarities */
    100 
    101     //#define  TIM_CCER_CC1P    ((uint16_t)0x0002)            /*!< Capture/Compare 1 output Polarity */
    102     //#define  TIM_CCER_CC2P    ((uint16_t)0x0020)            /*!< Capture/Compare 2 output Polarity */  
    103   tmpccer &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCER_CC1P)) & ((uint16_t)~((uint16_t)TIM_CCER_CC2P)));
    104     //简化一下
    105     //tmpccer &= (      (~(TIM_CCER_CC1P))        &       (~(TIM_CCER_CC2P))      );
    106     //(~(TIM_CCER_CC1P)) = ~0x0002  = 0b1111 1111 1111 1101
    107     //(~(TIM_CCER_CC2P)) = ~0x0020  = 0b1111 1111 1101 1111
    108     //上面两个先位与 ---------------->0b1111 1111 1101 1101
    109     // CCER[5]=0   CCER[1]=0
    110     
    111     /*
    112     CCER位5 CC2P:输入/捕获2输出极性。参考CC1P的描述。    
    113     CCER位1 CC1P:输入/捕获1输出极性
    114                     CC1通道配置为输出:
    115                     0: OC1高电平有效
    116                     1: OC1低电平有效
    117                     CC1通道配置为输入:(******上面已经将CC1/CC2 配置位输入了 !!!!!)
    118                     该位选择是IC1还是IC1的反相信号作为触发或捕获信号。
    119                     0:不反相:捕获发生在IC1的上升沿;当用作外部触发器时, IC1不反
    120                     1:反相:捕获发生在IC1的下降沿;当用作外部触发器时, IC1反相    
    121     */
    122     
    123     
    124     
    125   
    126     //#define  TIM_ICPolarity_Rising             ((uint16_t)0x0000)
    127     //#define  TIM_ICPolarity_Falling            ((uint16_t)0x0002)
    128     //#define  TIM_ICPolarity_BothEdge           ((uint16_t)0x000A)    //0b1010
    129   tmpccer |= (uint16_t)(TIM_IC1Polarity | (uint16_t)(TIM_IC2Polarity << (uint16_t)4));
    130    //1. 如果参数为 TIM_ICPolarity_Rising  -> 0x0000 
    131    // tmpccer |= 0;  
    132    // CCER没有改变,其实就是上面注释中的 --> 0 不反相:捕获发生在IC1/IC2的上升沿;当用作外部触发器时,IC1/IC2不反
    133    
    134    //2. 如果参数为 TIM_ICPolarity_Falling -> 0x0002
    135    // tmpccer |= 0x0002 | (0x0002<<4) = 0b0000 0010  | 0b0010 0000 = 0b0010 0010;
    136    // CCER[5]=1   CCER[1]=1
    137    // CCER没有改变,其实就是上面注释中的 --> 1:反相:捕获发生在IC1/IC2的下降沿;当用作外部触发器时, IC1/IC2反相
    138    
    139    //3. 如果参数为 TIM_ICPolarity_BothEdge  -> 0x000A -> 0b1010
    140    // ( 0b0000 0000 0000 1010 <<4 ) 结果是:0b0000 0000 1010 0000
    141    // 好吧  我都不想说了,真不知道为啥要做这个参数 !!!!!!!!
    142   
    143   
    144   /* Write to TIMx SMCR */
    145   TIMx->SMCR = tmpsmcr;
    146     //跟函数的参数有关系
    147     //tmpsmcr -> SMCR[2:0]  SMS:从模式选择  
    148     //011:编码器模式3 – 根据另一个输入的电平,计数器在TI1FP1和TI2FP2的边沿向上/下计数。
    149   
    150   
    151   /* Write to TIMx CCMR1 */
    152   TIMx->CCMR1 = tmpccmr1;
    153     // 函数内部处理,已经固定好了
    154     // tmpccmr1 -> CCMR1[9:8]=01 ; CCMR1[1:0] = 01 
    155     // CCMR1[9:8]        01: CC2通道被配置为输入, IC2映射在TI2上;
    156     // CCMR1[1:0]       01: CC1通道被配置为输入, IC1映射在TI1上;
    157   
    158   
    159   /* Write to TIMx CCER */
    160   TIMx->CCER = tmpccer;
    161     //跟函数的参数有关系
    162   
    163 }

    请看上面的注释

    谢谢留言分享

  • 相关阅读:
    git常用命令(转载)
    坑爹的跨域iframe高度
    Linux命令-cat
    redis之内存分配malloc底层实现(转)
    redis之jedis客户端使用shardjedis config
    多线程--生产者消费者以及死锁
    约瑟夫环问题--递推解法
    应用层协议小结之HTTP协议
    Colidity-- MaxDoubleSliceSum
    操作系统--用户空间和内核空间,用户态和内核态
  • 原文地址:https://www.cnblogs.com/caohenry999/p/12622362.html
Copyright © 2011-2022 走看看