STM8S timer basic interrupt timing

STM8S timers are divided into three categories.
Advanced Timer TIM1
Universal timers TIM2,TIM3, TIM5
Basic Timer TIM4, TIM6

Except that TIM4 and TIM6 are 8-bit timers, the other timers are 16-bit counted.
Each timer has automatic reloading function
The clock of each timer can be separated by the system clock. The advanced timer TIM1 can choose 65536 kinds of frequency division, and the frequency division coefficient is 1-65536. The universal timer can choose 16 kinds of frequency division, while the basic timer can only choose 8 kinds of frequency division.
In addition to TIM1 can choose the direction of counting, other timers are counted down, and the technical manual said that the upward counting is wrong.

Registers used for basic interrupt timing;

I. Automatic Loading Register High Bit (TIMx_ARRH) and Automatic Loading Register Low Bit (TIMx_ARRL)
Both registers have reset values of 0x00. It should be noted that both advanced timer TIM1 and general timer TIM2, TIM3 and TIM5 are 16-bit counting timers. When operating registers, it is necessary to write 8 bits higher and 8 bits lower. The basic timer TIM4 and TIM6 are 8-bit counting timers, regardless of high 8-bit and low 8-bit, so the name of the register when operating the basic timer is (TIMx_ARR). The updated value is not immediately written to the reload register when the operation reloads the register, but only when the interrupt occurs. Of course, the interrupt can also be generated by software. (The concept of shadow registers is omitted here, and it feels like a trick.)

2. Counter high bit (TIMx_CNTRH) and counter low bit (TIMx_CNTRL)
The high-bit counter and the low-bit reset value of the counter are both 0x00. Only the advanced timer TIM1 and the universal timer TIM2, TIM3 and TIM5 can use the two counters, while the basic timer's counter is (TIMx_CNTR). It's better to zero the counter before starting the timer. Basic timer (bit 5:1 reserved).

Interrupt Enabled Register (TIMx_IER)
This register is universal to all timers with a reset value of 0x00.
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
Retain TIE, Retain CC3IE CC2IE CC1IE UIE
RW RW RW RW RW RW

Position 7 reservation
Bit 6 TIE: Trigger interrupt enablement
0; trigger interrupt disable
1; Trigger interrupt enablement
Bit 5:4 Reservation
Bit 3 CC3IE: Allows capture/comparison of 3 interrupts
0; prohibit capture/comparison 3 interruption
1; Capture/compare 3 interrupts allowed
Note: This bit is reserved in the basic timer
Bit 2 CC2IE: Allow capture/comparison 2 interrupts
0; prohibit capture/comparison 2 interruption
1; Allow capture/comparison 2 interruption
Note: This bit is reserved in the basic timer
Bit 1 CC1IE: Allow capture/comparison 1 interrupt
0; prohibit capture/comparison 1 interruption
1; Capture/compare 1 interrupts allowed
Note: This bit is reserved in the basic timer
Bit 0 UIE: Allow update interruption
0; prohibit update interruption
1; Allow update interruption

State Register 1(TIMx_SR1)
The reset value is 0x00. This register is suitable for advanced timers and general timers, but the state register name of the basic timer is (TIMx_SR). The corresponding function is the same. The basic timer (bit 5:1 reserved).
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
Retain TIF, Retain CC3IF CC2IF CC1IF UIF
Rc_w0 Rc_w0 Rc_w0 Rc_w0 Rc_w0 Rc_w0

Position 7 reservation
Bit 6 TIF: Trigger interrupt flag
When triggering event occurs, the bit is set to 1 by hardware (effective triggering edge is detected on TRGI signal, and both rising and falling edges are valid when gated mode is selected). It is cleared by software.
0; no trigger event occurred
1. Trigger interruption suspension
Note that this bit is retained in TIM2, TIM3
Bit 5:4 Reservation
Bit 3 CC3IF: Capture/compare 3 interrupt flag
Bit 2 CC2IF: capture/compare 2 interrupt flag
Bit 1 CC1IF: Capture/compare 1 interrupt flag
If channel CC1 is configured in output mode;
When the counter value matches the comparison value, the bit is set to 1 by hardware and cleared by software.
0; no matching occurs
1; The value of TIMX_CNT matches the value of TIMX_CCR1
If channel CC1 is configured in input mode;
When the capture event occurs, the bit is set to 1 by hardware, zero by software or zero by reading TIMX_CCR1L.
0; no input capture generation
1; Counter values have been captured (copied) to TIMX_CCR1 (edges with the same polarity as selected have been detected on IC1)
Bit 0 UIF: Update interrupt flag
When an update event occurs, the bit is set to 1 by hardware, and it is cleared by software.
0; no update event occurs
1; Update events await response. When the register is updated, the bit is set to 1 by the hardware.
- If UDIS=0 of TIMX_CR1 register, counter overflow
- If UDIS=0 and URS=0 of TIMX_CR1 register, an update event occurs when UG=1 of TIMX_EGR register (software reinitializes counter CNT)

Control Register 1(TIMx_CR1)
The reset value is 0x00. This register is suitable for all timers.
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
ARPE Reservation Reservation Reservation OPM URS UDIS CEN
rw rw rw rw rw

Bit 7 ARPE: Allowable Bit for Automatic Reloading
0; TIMX_ARR registers do not have pre-loaded registers that can be buffered and manipulated directly.
1; TIMX_ARR registers can be buffered by preloading registers
Bit 6:4 Reservation
Bit 3 OPM: Monopulse Mode
0; when an update event occurs, the counter does not stop
1; When the next update event (clearing CEN bits) occurs, the counter stops
Bit 2 URS: Update request source
0; Update interruption occurs whenever the register is updated when the update request is enabled
1; When the update request is enabled, only the counter overflow will cause the update interrupt.
Bit 1 UDIS: Disable updates
Software allows/prohibits UEV events through this bit
0; Update events occur whenever the counter overflows, software updates are generated, or hardware resets are generated by the clock/trigger mode controller.
1; Shadow registers (ARR,PSC,CCRX) maintain their values without generating update events. If UG is set, the counter and pre-divider are re-initialized.
Bit 0 CEN: Enabling Counter
0; Prohibit counters
1; Enabling Counter

VI. TIMX_PSCR Pre-frequency Division Register
This register has different characteristics and usage methods in different timers. It is introduced in specific applications.

7. Use of TIM1 Interrupt Timing in Advanced Timer
In addition to the above registers, the advanced timer also uses TIM1_PSCRH and TIM1_PSCRL. The advanced timer can choose any frequency division between 1 and 65536 for the system clock, because the two pre-frequency division registers have 16 bits and the maximum count is just 65536. Write 8 digits higher and 8 digits lower.

Example: TIM1 interrupt timing, 1ms in an interrupt, 1s flip of LED lamp, downward counting mode

/*  This project template is someone else's, but this header file does not affect the use, in their own project need to be changed to their own header file. */

#include<iostm8s105k6.h>


unsigned int ms_count=0;//Millisecond count


/************************************

Various function declarations

************************************/
void InitLED();
void InitTIM1();

int main(void)
{
  CLK_CKDIVR = 0x00;  //CPUDIV = 1 HSIDIV = 1 internal clock = 16 Mhz 


  asm("sim");         //First close the total interrupt

  InitLED();          //Various initializations
  InitTIM1();

  asm("rim");         //Open total interrupt
  while(1);           //Enter the dead cycle and wait for the timer cycle to interrupt
}


/*********************************************************

Timer 1 updates interrupt processing function
 Interrupt vectors can also be replaced by decimal system, which is used here for convenience.
Because the macro definition of the header file is in hexadecimal.
Function names can be written freely, just be happy.

*****************************************************/
#pragma vector = 0x0D    //This is the interrupt format, just call it directly.
__interrupt void TIM1_OVR_UIF(void)
{
  TIM1_SR1 &= ~(1<<0);//Clear interruption mark
  ms_count++;
  if(ms_count>1000)//1ms*1000=1s
  {
    ms_count=0;
    PE_ODR ^= 1<<5;//LED lamp flipped once in 1s
  }
}


/*********************************************

Timer 1 initialization
tim1 Downward counting mode,

************************************************/
void InitTIM1()
{
  TIM1_PSCRH=0;//Be sure to write high eight first
  TIM1_PSCRL=0;//1 frequency division, timer clock equals system clock = 16m

  TIM1_ARRH=0X3e;//We must first install eight high positions and then eight low positions.
  TIM1_ARRL=0X80;//1ms reload value 16000,

  TIM1_CNTRH=0;
  TIM1_CNTRL=0;//It is necessary to clear down the counter

  TIM1_IER |= 1<<0;//Enable tim1 update interrupt
  TIM1_SR1 |= 1<<0;//Clear tim1 update interrupt flag

  TIM1_CR1 |= 1<<7;//Allow reassembly to enable timer
  TIM1_CR1 |= 1<<4;//Select Downward Counting Mode
  TIM1_CR1 |= 1<<0;//Enabling counter
}


/******************************************

LED Initialization

********************************************/
void InitLED()
{
    PE_DDR |= 1<<5;//PE5 directional output
    PE_CR1 |= 1<<5;//PE5 is push-pull output
    PE_CR2 |= 1<<5;//Maximum output speed is 10M
    PE_ODR |= 1<<5;//PE5 output 1
}

Example: TIM1 interrupt timing, 1ms into an interrupt, LED lights 1s flip once, up counting mode, as if the program can not be used, can not enter the interrupt.

/*  This project template is someone else's, but this header file does not affect the use, in their own project need to be changed to their own header file. */

#include<iostm8s105k6.h>


unsigned int ms_count=0;//Millisecond count


/************************************

Various function declarations

************************************/
void InitLED();
void InitTIM1();

int main(void)
{
  CLK_CKDIVR = 0x00;  //CPUDIV = 1 HSIDIV = 1 internal clock = 16 Mhz 


  asm("sim");         //First close the total interrupt

  InitLED();          //Various initializations
  InitTIM1();

  asm("rim");         //Open total interrupt
  while(1);           //Enter the dead cycle and wait for the timer cycle to interrupt
}


/*********************************************************

Timer 1 updates interrupt processing function
 Function names can be written freely, just be happy.

*****************************************************/
#pragma vector = 0X0D    //This is the interrupt format, just call it directly.
__interrupt void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void)
{
  TIM1_SR1 = 0;//Clear interruption mark
  ms_count++;
  if(ms_count>1000)//1ms*1000=1s
  {
    ms_count=0;
    PE_ODR ^= 1<<5;//LED lamp flipped once in 1s
  }
}


/*********************************************

Timer 1 initialization
tim1 Counting up mode,
The system clock has a frequency divider = timer clock = 16m, so each clock is 1/16us
 Timing 1ms requires 16,000 clocks, so the initial value is 65536-16000=49536=0xc180
 Why don't you count up? No interruption at all

************************************************/
void InitTIM1()
{
  TIM1_PSCRH=0;//Be sure to write high eight first
  TIM1_PSCRL=0;//1 frequency division, timer clock equals system clock = 16m

  TIM1_ARRH=0XC1;//We must first install eight high positions and then eight low positions.
  TIM1_ARRL=0X80;//1ms reload value 0xc180

  TIM1_CNTRH=0;
  TIM1_CNTRL=0;//It is necessary to clear down the counter

  TIM1_IER |= 1<<0;//Enable tim1 update interrupt
  TIM1_SR1 |= 1<<0;//Clear tim1 update interrupt flag

  TIM1_CR1 |= 1<<7;//Allow reassembly to enable timer
  //....................................
  TIM1_CR1 |= ~(1<<5);
  TIM1_CR1 |= ~(1<<6);
  TIM1_CR1 |= ~(1<<4);//Select Downward Counting Mode
  //.....................................
  TIM1_CR1 |= 1<<0;//Enabling tim1 counter
}


/******************************************

LED Initialization

********************************************/
void InitLED()
{
    PE_DDR |= 1<<5;//PE5 directional output
    PE_CR1 |= 1<<5;//PE5 is push-pull output
    PE_CR2 |= 1<<5;//Maximum output speed is 10M
    PE_ODR |= 1<<5;//PE5 output 1
}

8. Use of Universal Timers TIM2, TIM3 and TIM5
The clock pre-divider (TIMx_PSCR) of the universal timer is somewhat different from that of the advanced timer. The pre-divider of the universal timer has only 8 bits and 4 bits are reserved, only 4 bits are used. A total of 16 kinds of frequency dividers can be selected, i.e. 1-16 power divider of 2, 1 frequency divider, 2 frequency divider, 4 frequency divider, 8 frequency divider.... 32768.
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
Preserve PSC[3:0]
RW RW RW RW

PSC[3:0] Frequency Division Coefficient
0000 1
0001 2
0010 4
0011 8
.................... .................................
1111 32768

Example: When determined by TIM2, 1ms enters an interruption and 1s reverses the LED lamp.

/*  This project template is somebody else's, but this header file does not affect usage.  */
#include<iostm8s105k6.h>


unsigned int ms_count=0;//Millisecond count


//***********************************
//Various function declarations
void InitLED();
void InitTIM2();

int main(void)
{
  CLK_CKDIVR = 0x00;  //CPUDIV = 1 HSIDIV = 1 internal clock = 16 Mhz 


  asm("sim");         //First close the total interrupt

  InitLED();          //Various initializations
  InitTIM2();

  asm("rim");         //Open total interrupt
  while(1);           //Enter the dead cycle and wait for the timer cycle to interrupt
}


//*********************************************************
//Timer 2 updates interrupt handler
#pragma vector = 15     //Set the interrupt vector number of timer 2 overload = 15, which is the interrupt format. Just call it directly.
__interrupt void TIM2_UPDATE_IRQHandler(void)
{
  TIM2_SR1=0;//Clear interruption mark
  ms_count++;
  if(ms_count>1000)//1ms*1000=1s
  {
    ms_count=0;
    PE_ODR^=1<<5;//LED lamp flipped once in 1s
  }
}


//*********************************************
//Timer 2 initialization
void InitTIM2()
{
  TIM2_PSCR=0;//1 frequency division, timer clock equals system clock = 16m

  TIM2_ARRH=0X3e;//We must first install eight high positions and then eight low positions.
  TIM2_ARRL=0X80;//1ms reload value 16000, this is a pit, the technical manual says tim2 is up counting, actually down counting.

  TIM2_CNTRH=0;
  TIM2_CNTRL=0;//It is necessary to clear down the counter

  TIM2_IER=0X01;//Enable tim2 update interrupt
  TIM2_SR1=0X01;//Clear tim2 update interrupt flag
  TIM2_CR1=0X81;//Allow reassembly to enable timer
}


//******************************************
//LED initialization
void InitLED()
{
    PE_DDR |= 1<<5;//PE5 directional output
    PE_CR1 |= 1<<5;//PE5 is push-pull output
    PE_CR2 |= 1<<5;//Maximum output speed is 10M
    PE_ODR |= 1<<5;//PE5 output 1
}

Example: When TIM3 is used to determine, 1ms enters an interruption and 1s flips the LED lamp.

/*  This project template is someone else's, but this header file does not affect the use, in their own project need to be changed to their own header file. */

#include<iostm8s105k6.h>


unsigned int ms_count=0;//Millisecond count


/************************************

Various function declarations

************************************/
void InitLED();
void InitTIM3();

int main(void)
{
  CLK_CKDIVR = 0x00;  //CPUDIV = 1 HSIDIV = 1 internal clock = 16 Mhz 


  asm("sim");         //First close the total interrupt

  InitLED();          //Various initializations
  InitTIM3();

  asm("rim");         //Open total interrupt
  while(1);           //Enter the dead cycle and wait for the timer cycle to interrupt
}


/*********************************************************

Timer 3 updates interrupt processing function
 Interrupt vectors can also be replaced by decimal system, which is used here for convenience.
Because the macro definition of the header file is in hexadecimal.
Function names can be written freely, just be happy.

*****************************************************/
#pragma vector = 0x11    //This is the interrupt format, just call it directly.
__interrupt void TIM3_OVR_UIF(void)
{
  TIM3_SR1 = 0;//Clear interruption mark
  ms_count++;
  if(ms_count>1000)//1ms*1000=1s
  {
    ms_count=0;
    PE_ODR ^= 1<<5;//LED lamp flipped once in 1s
  }
}


/*********************************************

timer initiated
 It's also a pit. According to the technical manual, tim3 is counted up. In fact, timer 3 is counted down.
The system clock has a frequency divider = timer clock = 16m, so each clock is 1/16us
 Timing 1ms requires 16,000 clocks, so the initial value is 16,000 = 0X3E80

************************************************/
void InitTIM3()
{
  TIM3_PSCR=0;//1 frequency division, timer clock equals system clock = 16m

  TIM3_ARRH=0X3e;//We must first install eight high positions and then eight low positions.
  TIM3_ARRL=0X80;//1ms reload value 0X3E80

  TIM3_CNTRH=0;
  TIM3_CNTRL=0;//It is necessary to clear down the counter

  TIM3_IER |= 1<<0;//Enable tim3 update interrupt
  TIM3_SR1 |= 1<<0;//Clear tim3 update interrupt flag

  TIM3_CR1 |= 1<<7;//Allow reassembly to enable timer
  TIM3_CR1 |= 1<<0;//Enabling tim3 counter
}


/******************************************

LED Initialization

********************************************/
void InitLED()
{
    PE_DDR |= 1<<5;//PE5 directional output
    PE_CR1 |= 1<<5;//PE5 is push-pull output
    PE_CR2 |= 1<<5;//Maximum output speed is 10M
    PE_ODR |= 1<<5;//PE5 output 1
}

Example: TIM5 interrupt timing, 1ms in an interrupt, 1s LED lamp flip once.
It seems that my STM8SK4T6 minimal system does not have TIM5.................................... ..

9. Use of Basic Timers TIM4 and TIM6
The clock pre-divider (TIMx_PSCR) of the basic timer is different from the advanced timer and the universal timer. The pre-divider of the basic timer has only 8 bits and 5 bits are reserved, only 3 bits are used. A total of 8 kinds of frequency dividers can be selected, i.e. 1-8 power divider, 1 divider, 2 divider, 4 divider, 8 divider.... 256 minutes.
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
Preserve PSC[3:0]
RW RW RW

PSC[3:0] Frequency Division Coefficient
000 1
001 2
010 4
011 8
.................... .................................
111 256

Example: When TIM4 is used, 1ms is interrupted once and the LED lamp is flipped once.

/*  This project template is someone else's, but this header file does not affect the use, in their own project need to be changed to their own header file. */

#include<iostm8s105k6.h>


unsigned int ms_count=0;//Millisecond count


/************************************

Various function declarations

************************************/
void InitLED();
void InitTIM4();

int main(void)
{
  CLK_CKDIVR = 0x00;  //CPUDIV = 1 HSIDIV = 1 internal clock = 16 Mhz 


  asm("sim");         //First close the total interrupt

  InitLED();          //Various initializations
  InitTIM4();

  asm("rim");         //Open total interrupt
  while(1);           //Enter the dead cycle and wait for the timer cycle to interrupt
}


/*********************************************************

Timer 4 updates interrupt handler
 Function names can be written freely, just be happy.

*****************************************************/
#pragma vector = 0x19    //This is the interrupt format, just call it directly.
__interrupt void TIM4_OVR_UIF(void)
{
  TIM4_SR  = 0;//Clear interruption mark
  ms_count++;
  if(ms_count>50000)//10US*50000=500MS
  {
    ms_count=0;
    PE_ODR ^= 1<<5;//LED lamp 500MS flip once
  }
}


/*********************************************

timer initiated
 It's also a pit. According to the technical manual, tim4 is counted up, but in fact timer 4 is counted down.
The system clock has a frequency divider = timer clock = 16m, so each clock is 1/16us
 Timing 10US requires 160 clocks, so the initial value is 160=0XA0

************************************************/
void InitTIM4()
{
  TIM4_PSCR=0;//1 frequency division, timer clock equals system clock = 16m

  TIM4_ARR=0XA0;//1ms reload value 0XA0

  TIM4_CNTR=0;//It is necessary to clear down the counter

  TIM4_IER |= 1<<0;//Enable tim4 update interrupt
  TIM4_SR  |= 1<<0;//Clear tim4 update interrupt flag

  TIM4_CR1 |= 1<<7;//Allow reassembly to enable timer
  TIM4_CR1 |= 1<<0;//Enabling tim4 counter
}


/******************************************

LED Initialization

********************************************/
void InitLED()
{
    PE_DDR |= 1<<5;//PE5 directional output
    PE_CR1 |= 1<<5;//PE5 is push-pull output
    PE_CR2 |= 1<<5;//Maximum output speed is 10M
    PE_ODR |= 1<<5;//PE5 output 1
}

My STM8SK4T6 is not TIM6, so I can only regret it here, but the usage should be the same as TIM4.

Posted by eon201 on Tue, 21 May 2019 14:13:36 -0700