0
\$\begingroup\$

I want to use Sm8s003f3p6 as a frequency counter , My program is as described in stm8s reference manual 17.4.3 External clock source mode 1 and pulse counting is done in pin PC7 using HSI 16 Mhz , but the speed of counting is very low , for example for a 10 mhz pulse in 1 ms TIM1_CNTRL counts to 60 .

I want to know is this speed of counting correct ?

Is it possible to have faster counting ?

what is the maximum counting frequency of stm8s003f3p6?

I want to make a frequency counter and need to have more speed to count high frequency wave . As I said for 10 mhz pulse , counter is 60 so each increment of counter is equal to 10Mhz/60 = 167 khz that is not a good resolution . .

my code for timer counter is as follows

#include <iostm8S003f3.h>
#include <intrinsics.h>
unsigned long int fr=0,f=0;  // fr increment in timer1 overflow , f is number of final pulse counting 
unsigned char h; //dummy variable 
int main(void)
{
  __disable_interrupt();  
  InitialiseSystemClock();
  InitialisePorts();
  config_counter();
  TIM1_IER_UIE = 1;  // enable timer 1 interrupt     
  __enable_interrupt();
  while (1)
  {
    fr=0;
    TIM1_CNTRH = 0; //reset counter 
    TIM1_CNTRL = 0;
    TIM1_CR1_CEN=1; // start counter 
    delayms(1);
    TIM1_CR1_CEN=0; // stop counting 
    // calculate counter as a number = TIM1_CNTRH*256 + TIM1_CNTRL + fr*65536 
    // fr will increment whenever tim1 counter overflows 
    h=TIM1_CNTRH ;  
    f=h*256;
    h=TIM1_CNTRL;
    f=f+h;
    f=fr*65536+f;
  }
}

void delayms(int t)
{
 int d;
 while(t--)
 for (d = 0; d < 2020; ++d) ; //approximately 1 ms delay with 16 mhz clock
}

#pragma vector = TIM1_OVR_UIF_vector
__interrupt void TIM1_UPD_OVF_IRQHandler(void)
{
 fr++;
 TIM1_SR1_UIF = 0; 
}

void InitialisePorts()
{
  PC_DDR_DDR7=0;  // pc7 as input 
  PC_CR1_C17 = 0; // no pullup 
  PC_CR2_C27 = 0; // no interrupt
}

void InitialiseSystemClock()
{
  CLK_ICKR = 0;            // Reset the Internal Clock Register.
  CLK_ICKR_HSIEN = 1;         // Enable the HSI.
  CLK_ECKR = 0;            // Disable the external clock.
  while (CLK_ICKR_HSIRDY == 0);    // Wait for the HSI to be ready for use.
  CLK_CKDIVR = 0;           // Ensure the clocks are running at full speed.
  CLK_PCKENR1 = 0xff;         // Enable all peripheral clocks.
  CLK_PCKENR2 = 0xff;        
  CLK_CCOR = 0;            // Turn off CCO.
  CLK_HSITRIMR = 0;          // Turn off any HSIU trimming.
  CLK_SWIMCCR = 0;          // Set SWIM to run at clock / 2.
  CLK_SWR = 0xe1;           // Use HSI as the clock source.
  CLK_SWCR = 0;            // Reset the clock switch control register.
  CLK_SWCR_SWEN = 1;         // Enable switching.
  while (CLK_SWCR_SWBSY != 0);    // Pause while the clock switch is busy.
}

void config_counter()
{
 TIM1_CNTRH = 0;
 TIM1_CNTRL = 0; //Reset counter
 TIM1_IER = 0; //Interrupt disabled
 TIM1_SR1 = 0; //Clear Interrupt
 TIM1_CCMR2 |= 1<<0; //External pulse source T1C2
 TIM1_CCER1 &= ~(1<<5); //Rising edge
 TIM1_SMCR |= (7<<0); //External Clock Source
 TIM1_SMCR |= (6<<4); //T1C2 Input Source
 TIM1_CR1 &= ~(1<<0); //Counter disabled
 return;
}
\$\endgroup\$
1
  • \$\begingroup\$ Please fix your code formatting. Select the text and then press the {} button. Make sure that the indenting is correct and remove unnecessary blank lines. Use proper capitalisation for part numbers and SI units such as 'Hz'. Preview the question before posting it. Welcome to EE.SE. \$\endgroup\$
    – Transistor
    Commented May 6, 2021 at 19:35

1 Answer 1

0
\$\begingroup\$

Since your result (f) is a 32-bit number, your resolution could theoretically be one part in 4,294,967,296. Your present design counts for only one millisecond, so your answer will be in kilohertz with a resolution of one kHz. TIM1_CNTRL is only the low byte of your answer; the result is the variable "f". You can get more resolution by increasing the value of delayms(). I don't see in your code where you output the answer. If you increased to delayms(1000), and inserted a printf command to report the value of f after "f=fr*65536+f;" you would get an answer in Hz once per second.

The timer can probably handle 10 MHz if it's a clean digital signal, but not much higher.

Also the accuracy will be determined by the accuracy of your delayms() function.

Good luck!

\$\endgroup\$
1
  • \$\begingroup\$ Thanks Jhon , yes if I increase the delay , resolution becomes better . One thing I forgot was that I used a prescaler divide by 128 so 10 mhz divide by 128 is 78.125 khz and counter for 1 ms should be arround 78 and my circuit that counts to 60 in 1 ms seems works correctly and differnce of 60 to 78 is not much . \$\endgroup\$
    – Ali
    Commented May 8, 2021 at 20:26

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.