0

I am using stm8l - discovery and i have created a code for toggling a led for every 1 second using timer (TIM1) but this is not working properly. I am missing something here in my configuration

I could enter the interrupt function for the first time but after that it does not enter the interrupt function. Someone please look into and help me out

enter code here
#include <iostm8l.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "defs.h"

unsigned int count = 0;

@svlreg @interrupt void TIM1(void)
{
count += 1;
TIM1_SR1 &= ~(0x01);
}

main()
{
CLK_DIVR = 0x00; // Set the frequency to 16Mhz
CLK_PCKENR2 = 0x02; // clock for timer1
PC_DDR = 0x80; // direction output for led
PC_CR1 = 0x80; // fast push pull mode
PE_DDR = 0x80; // direction output for led
PE_CR1 = 0x80; // fast push pull mode
TIM1_PSCRH = 0x3e; //to create a frequency for 1000 hz
TIM1_PSCRL = 0x80; // so prescalar is 16000
TIM1_CR1 = 0x01;
TIM1_IER = 0x01;
_asm("rim\n");
while(1)
{

    if (count == 1000)
    {
        PE_ODR ^= 0x80;
        count = 0;
    }
}
}

The interrupt enters only one time but after that it does not enter. So variable "count" remains at value 1

glts
  • 21,808
  • 12
  • 73
  • 94
Viswa5095
  • 1
  • 2

1 Answers1

1
  • You are using magic numbers for the bit masks instead of defined constants, so the code is pretty damn hard to read for you and me both. Change this so that the code ends up like for example

    TIM1_SR1 &= ~TIM1_SR1_UIF;

  • Since this is a 8 bit MCU it is also absolutely essential that you u suffix all integer contants, or they will be of type signed int, which you don't want.

    For example this code TIM1_SR1 &= ~(0x01); is equivalent to TIM1_SR1 &= -2. Very easy to write accidental subtle bugs this way. I recommend studying Implicit type promotion rules.

    It is highly recommended to disassemble every ISR you write to see what machine code you actually end up with, and single step it through the debugger while watching the register as well. This particular register seems to ignore having 1 written to it, so you could probably just do TIM1_SR = TIM1_SR1_UIF;. Incorrectly cleared timer flags inside ISRs is one of the most common bugs in embedded systems.

  • Quoting the manual:

    UIF: Update interrupt flag
    – At overflow or underflow if UDIS = 0 in the TIM1_CR1 register
    – When CNT is re-initialized by software using the UG bit in TIM1_EGR register, if URS = 0 and UDIS = 0 in the TIM1_CR1 register.
    – When CNT is re-initialized by a trigger event (refer to the TIM1_SMCR register description), if URS = 0 and UDIS = 0 in the TIM1_CR1 register

    Your code doesn't appear to do any of this, so it is pretty safe to assume the timer counter isn't reset.

  • Another problem is that count must be declared as volatile or otherwise the compiler might optimize out this code completely:

    if (count == 1000)
    {
        PE_ODR ^= 0x80;
        count = 0;
    }
    
Lundin
  • 195,001
  • 40
  • 254
  • 396