Skip to main content
Visitor II
January 14, 2018
Solved

How to use TIMER 2 as simple counter in STM8S103F3?

  • January 14, 2018
  • 2 replies
  • 5886 views
Posted on January 14, 2018 at 09:04

Hi All,

I am new to STM8S and not yet that good at microcontroller programming in general. I am trying to learn about timers/counters in microcontrollers.

I wrote following code to toggle an LED connected at PB5 pin in each second.

#include 'stm8s.h'
int main() {
 // Default clock is HSI/8 = 2MHz
 PB_DDR |= (1 << PB5); // PB5 is now output
 PB_CR1 |= (1 << PB5); // PB5 is now pushpull
 TIM2_PSCR = 0b00000111; // Prescaler = 128
 TIM2_CR1 |= (1 << TIM2_CR1_CEN); // Enable TIM2
 while (1) {
 if ( ( ((uint16_t)TIM2_CNTRH << 8) + (uint16_t)TIM2_CNTRL ) >= 15625 ) {
 // Reset counter back to 0
 TIM2_CNTRH = 0;
 TIM2_CNTRL = 0;
 // Toggle LED.
 PB_ODR ^= (1 << PB5);
 }
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

My microcontroller is not connected with any external clock and using internal clock to operate.

After I reading datasheet, I see MCU clock will be HSI/8 = 2MHz by default. I set 128 as prescaler for TIM2. So, TIM2 counter will increment in each 64us. So, when it reach at 15625 it will be 1 second (64 * 15625 = 1000000us = 1s).

So, I assumed the LED to toggle in each second.

The problem is the LED stays ON all time.

Could somebody help me to identify the problem with my code?

Thanks in advance. #counter #timer #stm8s #stm8s103f3
    This topic has been closed for replies.
    Best answer by Junaid PV
    Posted on January 15, 2018 at 10:33

    After reading reference manual, I found that we need to set UG bit of TIM2_EGR register to tell MCU to take prescaler value set.

    TIM2_PSCR = 0b00000111; // Prescaler = 128
    // Generate an update event so prescaler value will be taken into account.
    TIM2_EGR |= (1 << TIM2_EGR_UG);
    TIM2_CR1 |= (1 << TIM2_CR1_CEN); // Enable TIM2�?�?�?�?

    2 replies

    Junaid PVAuthorAnswer
    Visitor II
    January 15, 2018
    Posted on January 15, 2018 at 10:33

    After reading reference manual, I found that we need to set UG bit of TIM2_EGR register to tell MCU to take prescaler value set.

    TIM2_PSCR = 0b00000111; // Prescaler = 128
    // Generate an update event so prescaler value will be taken into account.
    TIM2_EGR |= (1 << TIM2_EGR_UG);
    TIM2_CR1 |= (1 << TIM2_CR1_CEN); // Enable TIM2�?�?�?�?

    Visitor II
    July 16, 2020

    Hai Junaid PV,

    I was following your Timer operation and configured the same for TIM1.And able to get the 1sec work.Now I want set timer for 32sec or more.Can you help me on how to set the prescalar and time period value please.

    Regrads

    Srikanth.

    Junaid PVAuthor
    Visitor II
    July 16, 2020

    I think you can set 4096 as prescaler value.

    Default clock is 2MHz.

    So,

    (1/2000000) * 4096 * 15625 = 32

    Please note, Timer 1 has 16 bit prescaler capability and we need to set two registers TIM1_PSCRL and TIM1_PSCRH.

    Regards,

    Junaid

    Visitor II
    July 16, 2020

    the code gets you going but can be further improved: 1) it is not very modular and hard to reuse the code; 2) it doesn't ensure atomicity in reading the timer counter.

    rewriting the counter isn't a good way to ensure long-term accuracy. instead I use something like this:

    //return 1 if sufficient ticks have passed
    //return 0 otherwise
    uint8_t tim2_cnt(uint16_t cnt) {
     static uint16_t _cnt=0; //temp tick counter
      
     if (tim2_get() - _cnt > cnt) {_cnt+=cnt; return 1;}
      return 0;
     }

    so in your case, something like this would work:

     if (tim2_cnt(TICK_DLY) flip_led(); //flip the led if sufficient tim2 ticks have passed.

    tim2_get() returns a read of the tim2 counter, often via a double read to ensure atomicity.