AnsweredAssumed Answered

ARM M4 - Timer 2&5 as Encoder Inputs

Question asked by DuaneB on Jan 8, 2015
Latest reply on Jan 8, 2015 by Clive One
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/DM00119316.pdf, 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

Outcomes