[原創] 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 }

請看上面的注釋

謝謝留言分享


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM