今天把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 }
請看上面的注釋
謝謝留言分享