cancel
Showing results for 
Search instead for 
Did you mean: 

ARM M4 - Timer 2&5 as Encoder Inputs

duane
Associate II
Posted on January 08, 2015 at 17:14

Hello everyone,

Working on a Differentially Steered robot, nothing new (except to me). I found some code on the web that sets up Timer2 in mode3 (Encoder mode) using PA0 & PA1. I have the contents of the TIM2->CNT register being displayed to an I2C LCD. All is good. Looking at the Datasheet (for the STM32F411RE), PA0 & PA1 can be used by either TIM2 or TIM5. TIM5 can ONLY use PA0 & PA1, whereas TIM2 can use an alternate set of pins/inputs. Looking at the Reference Manual,

http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00119pdf

, it looks like the only thing I need to do is change the value of the RCC_APB1ENR (peripheral clock enable register) from a value of 0x00000001 to 0x00000008 to start using TIM5. But when I make the change, it appears like the I2C stuff quits working as nothings appears on the screen. Could someone point me in the right direction? Working Timer2 code:

// configure TIM2 as Encoder input
RCC->APB1ENR |= 0x00000001; // Enable clock for TIM2
 TIM2->CR1 = 0x0001; // CEN(Counter ENable)='1' < 
TIM
control register 1
TIM2->SMCR = 0x0003; // SMS='011' (Encoder mode 3) < 
TIM
slave mode control register
TIM2->CCMR1 = 0xF1F1; // CC1S='01' CC2S='01' < 
TIM
capture/compare mode register 1
TIM2->CCMR2 = 0x0000; // < 
TIM
capture/compare mode register 2
TIM2->CCER = 0x0011; // CC1P CC2P < 
TIM
capture/compare enable register
TIM2->PSC = 0x0000; // Prescaler = (0+1) < 
TIM
prescaler
TIM2->ARR = 0xffffffff; // reload at 0xfffffff < 
TIM
auto-reload register
TIM2->CNT = 0x0000; //reset the counter before we use it

NOT working Timer 5 code:

// configure TIM5 as Encoder input
RCC->APB1ENR |= 0x00000008; // Enable clock for TIM5
TIM5->CR1 = 0x0001; // CEN(Counter ENable)='1' < 
TIM
control register 1
TIM5->SMCR = 0x0003; // SMS='011' (Encoder mode 3) < 
TIM
slave mode control register
TIM5->CCMR1 = 0xF1F1; // CC1S='01' CC2S='01' < 
TIM
capture/compare mode register 1
TIM5->CCMR2 = 0x0000; // < 
TIM
capture/compare mode register 2
TIM5->CCER = 0x0011; // CC1P CC2P < 
TIM
capture/compare enable register
TIM5->PSC = 0x0000; // Prescaler = (0+1) < 
TIM
prescaler
TIM5->ARR = 0xffffffff; // reload at 0xfffffff < 
TIM
auto-reload register
TIM5->CNT = 0x0000; //reset the counter before we use it

GPIOA code:

// configure GPIO PA0 & PA1 as inputs for Encoder
RCC->AHB1ENR |= 0x00000001; // Enable clock for GPIOA
GPIOA->MODER |= GPIO_MODER_MODER0_1 | GPIO_MODER_MODER1_1 ; //PA0 & PA1 as Alternate Function /*!< 
GPIO
port mode register, Address offset: 0x00 */
GPIOA->OTYPER |= GPIO_OTYPER_OT_0 | GPIO_OTYPER_OT_1 ; //PA0 & PA1 as Inputs /*!< 
GPIO
port output type register, Address offset: 0x04 */
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR0 | GPIO_OSPEEDER_OSPEEDR1 ; // Low speed /*!< 
GPIO
port output speed register, Address offset: 0x08 */
GPIOA->PUPDR |= GPIO_PUPDR_PUPDR0_1 | GPIO_PUPDR_PUPDR1_1 ; // Pull Down /*!< 
GPIO
port pull-up/pull-down register, Address offset: 0x0C */
GPIOA->AFR[0] |= 0x00000011 ; // AF01 for PA0 & PA1 /*!< 
GPIO
alternate function registers, Address offset: 0x20-0x24 */
GPIOA->AFR[1] |= 0x00000000 ; // /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */

Bulk of Main:

int main() 
{
EncoderInitialise() ;
unsigned int pCount;
float x;
lcd.cls();
lcd.locate(0,0); // Move cursor to start of the first display line
lcd.printf(''Pulse cnt: '');
lcd.locate(0,1); // Move cursor to start of the second display line 
lcd.printf(''Dist Traveled:''); 
lcd.locate(0,2); // Move cursor to start of the third display line 
lcd.printf(''Inches: ''); 
lcd.locate(0,3); // Move cursor to start of the third display line 
lcd.printf(''Feet: ''); 
while (true) 
{
pCount = TIM2->CNT ; // Get current position from Encoder
x = (pCount/4); // Get real count number
lcd.locate(11,0); // Move cursor to start of the first display line
lcd.printf(''%i'', pCount);
lcd.locate(8,2); // Move cursor to start of the third display line 
lcd.printf(''%5.2f'', (x *(1/PPI)));
lcd.locate(6,3); // Move cursor to start of the third display line
lcd.printf(''%4.2f'', (x *(1/PPF))); 
wait(1.0);
} 
}

When trying to use TIM5, this get changed to: pCount = TIM5->CNT ; // Get current position from Encoder This is using the mbed online compiler, as I have yet to get the Keil MDK ARM compiler to work yet, though I think all I need to do is load the Legacy drivers. WIll do this when I get home. Thanks, Duane #discovery #timers #stm32f4
3 REPLIES 3
Tuttle.Darrell
Associate II
Posted on January 08, 2015 at 17:32

TIM5 uses AF02 (alternate function)

duane
Associate II
Posted on January 08, 2015 at 18:57

Thanks for the 'Heads up''.  There is a LOT to take in  when reading through the Reference Manual!!

Posted on January 08, 2015 at 19:15

The Data Sheet is the best place to find the pin associations.

http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00115249.pdf

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..