1
\$\begingroup\$

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 in each second which is connected at PB5 pin.

#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 to 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 the time.

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

Thanks in advance.

\$\endgroup\$
2
  • \$\begingroup\$ Can you debug this and monitor the LED Pin? If it doesn't work in the debugger then at least you have eliminated that the problem is not from your hardware. \$\endgroup\$
    – rrz0
    Jan 14, 2018 at 21:37
  • \$\begingroup\$ Unfortunately I am yet to learn about debugging :) However, LED blinks fine if I run program using simple for loop to create the delay. \$\endgroup\$
    – Junaid
    Jan 14, 2018 at 21:42

2 Answers 2

2
\$\begingroup\$

After reading Reference Manual more I found we need to set UG bit TIM2_EGR to generate and update event so MCU will take the prescaler value for TIMER 4.

TIM2_EGR |= (1 << TIM2_EGR_UG);

So, updated code will be:

#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_EGR |= (1 << TIM2_EGR_UG); // Generate an update event so prescaler value will be taken into account.
  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);
    }
  }
}

Now the LED started to toggle in each second!!

\$\endgroup\$
0
\$\begingroup\$

Make small tweaks to the code : Included Timer 2 overflow interrupt.

NOTE :

  • The program was compiled using SDCC compiler and microcontroller was flashed using ST Visual Programmer ( STVP ).

  • Make sure to download the custom header file from here : https://github.com/ElectronicCircuitDesignTools/STM8S103F3P6/blob/303d53aded5b4b91b23d1356df89df0c97968d30/stm8s103f3p6_register_map.h

      #define using_io_ports 1
      #define using_tim2 1
      #define TIM2_OVF 13
    
      #include "stm8s103f3p6_register_map.h"
    
      unsigned int prescaler = 4;
      unsigned char led_state = 0x00;
    
      void isr_timer_2_overflow() __interrupt(TIM2_OVF)
      {
          PD_ODR ^= ( 1 << ODR4 );
          TIM2_CNTRH = (unsigned char)(3035 >> 8);        //  Load starting value of timer 2 ( high byte ).
          TIM2_CNTRL = (unsigned char)(3035 & 0xFF);      //  Load starting value of timer 2 ( low byte ).
          TIM2_SR1 = 0x00;                    //  Clear the update interrupt flag.
      }
    
      void main( void )
      {
          PD_DDR = ( 1 << ODR4 );
          PD_CR1 = ( 1 << C14 );
    
          __asm__("sim");             //  Disable all interrupts.
    
          TIM2_CNTRL = 0;             //  Clear Timer 2 counter register ( high byte ).
          TIM2_CNTRH = 0;             //  Clear Timer 2 counter register ( low byte ).
    
          TIM2_PSCR = 0x04;           //  Set Timer 2 clock speed = f_master / 4.
          TIM2_EGR = 0x01;            //  Enable update event.
          TIM2_IER = 0x01;            //  Enable update interrupt.
          TIM2_SR1 = 0x00;            //  Clear the update interrupt flag.
          TIM2_CR1 = 0x01;            //  Enable Timer 2 operation as counter.
    
          __asm__("rim");
    
          while(1)
          {
    
          }
      }
    
\$\endgroup\$
1
  • \$\begingroup\$ PATRICK A JOSEPH - Hi, That looks like your GitHub repo which you have linked to - is that correct? If so, we need to add a suitable disclosure to your answer, to comply with site rules. Since you are a new user, please reply in a comment below and I'll help you to do that. Thanks. \$\endgroup\$
    – SamGibson
    May 4, 2021 at 11:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.