AnsweredAssumed Answered

STM8 startup bug Timer 2 input capture

Question asked by van_de_sande.mitchel on Apr 28, 2015
Hi,

I wanna make a frequency pulse counter with an STM8. The counter is based on the input capture of the STM timer 2.
The frequency is a frequency with a range of 1 Hz - 20 kHz.
With the following code this is possible:


001.#include <iostm8s003k3.h>
002.#include <intrinsics.h>
003.#include <stdio.h>
004.#include "stm8s.h"
005. 
006.unsigned int CaptureLow;
007.unsigned int CaptureHigh;
008.unsigned int CaptureValue;
009.unsigned int Freq;
010.unsigned char flag;
011.char string[20];
012.float Frequency;
013. 
014.//
015.//  Setup the system clock to run at 16MHz using the internal oscillator.
016.//
017.void InitialiseSystemClock()
018.{
019.    CLK_ICKR = 0;                       //  Reset the Internal Clock Register.
020.    CLK_ICKR_HSIEN = 1;                 //  Enable the HSI.
021.    CLK_ECKR = 0;                       //  Disable the external clock.
022.    while (CLK_ICKR_HSIRDY == 0);       //  Wait for the HSI to be ready for use.
023.    CLK_CKDIVR = 0;                     //  Ensure the clocks are running at full speed.
024.    CLK_PCKENR1 = 0xff;                 //  Enable all peripheral clocks.
025.    CLK_PCKENR2 = 0xff;                 //  Ditto.
026.    CLK_CCOR = 0;                       //  Turn off CCO.
027.    CLK_HSITRIMR = 0;                   //  Turn off any HSIU trimming.
028.    CLK_SWIMCCR = 0;                    //  Set SWIM to run at clock / 2.
029.    CLK_SWR = 0xe1;                     //  Use HSI as the clock source.
030.    CLK_SWCR = 0;                       //  Reset the clock switch control register.
031.    CLK_SWCR_SWEN = 1;                  //  Enable switching.
032.    while (CLK_SWCR_SWBSY != 0);        //  Pause while the clock switch is busy.
033.}
034. 
035.void InitMCU(void)
036.{
037.  PB_DDR     = 0x0F;
038.  PB_CR1     = 0x0F;
039.  PB_ODR     = 0x00;
040.  
041.  PC_DDR_DDR1 = 1;
042.  PC_CR1_C11  = 1;
043.  PC_ODR_ODR1 = 0;
044.  
045.  PC_DDR_DDR2 = 1;
046.  PC_CR1_C12  = 1;
047.  PC_ODR_ODR2 = 0;
048.}
049. 
050.void InitCaptureTIM2(void)
051.{
052.  TIM2_PSCR  = 3;
053.  TIM2_CCMR1 = 0x01;            //CAPTURE / VERGELIJK moderegister 1
054.  TIM2_CCER1_CC1P = 0;
055.  TIM2_CCER1_CC1E = 1;
056.  TIM2_SR1_CC1IF  = 0;
057.  TIM2_SR2_CC1OF  = 0;
058.  TIM2_IER_CC1IE  = 1;
059.}
060.   
061.void __delay(void)
062.{
063.  unsigned long int j=200000;
064.  while(j--);
065.}
066.  
067.//
068.//  Setup the UART to run at 115200 baud, no parity, one stop bit, 8 data bits.
069.//
070.//  Important: This relies upon the systemk clock being set to run at 16 MHz.
071.//
072.void InitialiseUART()
073.{
074.    //
075.    //  Clear the Idle Line Detected bit in the status rerister by a read
076.    //  to the UART1_SR register followed by a Read to the UART1_DR register.
077.    //
078.    unsigned char tmp = UART1_SR;
079.    tmp = UART1_DR;
080.    //
081.    //  Reset the UART registers to the reset values.
082.    //
083.    UART1_CR1 = 0;
084.    UART1_CR2 = 0;
085.    UART1_CR4 = 0;
086.    UART1_CR3 = 0;
087.    UART1_CR5 = 0;
088.    UART1_GTR = 0;
089.    UART1_PSCR = 0;
090.    //
091.    //  Now setup the port to 115200,n,8,1.
092.    //
093.    UART1_CR1_M = 0;        //  8 Data bits.
094.    UART1_CR1_PCEN = 0;     //  Disable parity.
095.    UART1_CR3_STOP = 0;     //  1 stop bit.
096.    UART1_BRR2 = 0x0a;      //  Set the baud rate registers to 115200 baud
097.    UART1_BRR1 = 0x08;      //  based upon a 16 MHz system clock.
098.    //
099.    //  Disable the transmitter and receiver.
100.    //
101.    UART1_CR2_TEN = 0;      //  Disable transmit.
102.    UART1_CR2_REN = 0;      //  Disable receive.
103.    //
104.    //  Set the clock polarity, lock phase and last bit clock pulse.
105.    //
106.    UART1_CR3_CPOL = 1;
107.    UART1_CR3_CPHA = 1;
108.    UART1_CR3_LBCL = 1;
109.    //
110.    //  Turn on the UART transmit, receive and the UART clock.
111.    //
112.    UART1_CR2_TEN = 1;
113.    UART1_CR2_REN = 1;
114.    UART1_CR3_CKEN = 1;
115.}
116. 
117.//
118.//  Send the message in the string to UART1.
119.//
120.void UARTPrintF(char *message)
121.{
122.    char *ch = message;
123.    while (*ch)
124.    {
125.        UART1_DR = (unsigned char) *ch;     //  Put the next character into the data transmission register.
126.        while (UART1_SR_TXE == 0);          //  Wait for transmission to complete.
127.        ch++;                               //  Grab the next character.
128.    }
129.}
130. 
131.int main( void )
132.{
133.   
134.  //Setup of program, initializing
135.    __disable_interrupt();
136.    InitMCU();
137.    InitCaptureTIM2();
138.    InitialiseSystemClock();
139.    InitialiseUART();
140.    __enable_interrupt();
141.      
142.    TIM2_CR1_CEN = 1; 
143.     
144.   for(;;)
145.   {
146.      Frequency = (float)Freq/100.0;
147.       
148.      sprintf(string,"%.2f \n\r",Frequency);
149.      UARTPrintF(string);
150.    }
151.}
152. 
153.#pragma vector = TIM2_CAPCOM_CC1IF_vector
154.__interrupt void Timer2_CAPTURE_INT(void)
155.{
156.  if(!flag)
157.  {
158.    TIM2_CNTRH = 0;
159.    TIM2_CNTRL = 0;
160.    flag ^= 1;
161.  }
162.  else
163.  {
164.    CaptureHigh = TIM2_CCR1H;
165.    CaptureLow  = TIM2_CCR1L;
166.    CaptureValue = ((CaptureHigh << 8) | CaptureLow);
167.    flag ^= 1;
168.    Freq = 200000000/CaptureValue;
169.  }
170.}

My problem is that there is a bug in the code. The timer UART output start always with a wrong frequency (1150 Hz), maybe a reset or an initialisation is wrong but I can't find the mistake?

When the frequency drops down, below 50 Hz, the system is working until a new system startup. With a new system startup there is the same start up problem.

What is wrong in my code??

Thankyou!!

Outcomes