Skip to main content
Visitor II
October 13, 2020
Solved

STM8 Frequency Counter

  • October 13, 2020
  • 1 reply
  • 1375 views

Hello, I'm trying to implement a simple frequency counter. The idea is I have some external signal sitting at 6MHz, and I want to measure it by simply starting the TIM1 counter, waiting 1ms (delay), then reading the count, which I'd expect to be about 6,000. I also have an AND gate which i use to control when the 6MHZ is present on pin C6 (TIM1 chan 1); by writing high to the end gate the signal is present and by writing low, there is no signal. This is the only job for the microcontroller, and the signal in question isn't fast changing so taking a 1ms sample every 200ms should be more than enough.

Here's my main routine

main(){
	clock_setup();
	GPIO_setup();
	UART1_setup();
	TIM1_setup();
	TIM4_setup();
		
	SerialPutString("Starting STM8 \r\n");
	while(1){
		GPIO_WriteReverse(GPIOD, GPIO_PIN_2); //LED
 
	 delay_ms(200); //slow down the blinking		
		TIM1_setup();
		//TIM1_SetCounter(0); //Clear the count
		GPIO_WriteHigh(GPIOC, GPIO_PIN_4); //AND Gate
		delay_us(1000);
		GPIO_WriteLow(GPIOC, GPIO_PIN_4); //AND Gate
		//count = TIM1_GetCapture3();
		count = TIM1_GetCounter();
		
		clearprintBuffer(printBuffer);
		SerialPutString(printBuffer); //For some this needs to be called first
 sprintf(printBuffer, "count = %u \r\n", count);
 SerialPutString(printBuffer);
	}
}

I've confirmed that the AND gate is being set correctly, and I've confirmed that the delay_us() function is working correctly. The issue is that I am getting 0 as the output of TIM1_GetCounter(). If I comment out the line:

	TIM1_TIxExternalClockConfig(TIM1_TIXEXTERNALCLK1SOURCE_TI1, TIM1_ICPOLARITY_RISING, 0);

then I get 16000, which appears to be my 16MHZ clock, rather than the signal on pin C3. So it seems to me that the issue is that I need to use TIM1 chan1 (pin C6) as my clock rather than the 16MHz clock; but when I try to do this with the above line, I simply get 0.

Below is my Timer1 setup:

void TIM1_setup(void){	
//http://embedded-lab.com/blog/continuing-stm8-microcontroller-expedition/4/
	TIM1_DeInit();
	
 TIM1_TimeBaseInit(0, TIM1_COUNTERMODE_UP, 65535, 1);
	TIM1_SelectInputTrigger(TIM1_TS_TI1F_ED);
	TIM1_CCxCmd(TIM1_CHANNEL_1, ENABLE);
 TIM1_ICInit(TIM1_CHANNEL_1, TIM1_ICPOLARITY_RISING, TIM1_ICSELECTION_DIRECTTI, 1, 1);
	TIM1_TIxExternalClockConfig(TIM1_TIXEXTERNALCLK1SOURCE_TI1, TIM1_ICPOLARITY_RISING, 0);
	TIM1_Cmd(ENABLE);
}

and here is my clock setup:

void clock_setup(void){
	CLK_DeInit();
 
 CLK_HSECmd(ENABLE);
 CLK_LSICmd(DISABLE);
 CLK_HSICmd(DISABLE);
 while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);
 
 CLK_ClockSwitchCmd(ENABLE);
 CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
 CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
 
 CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, 
 DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);
			
 CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
 CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);
 CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
 CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, DISABLE);
 CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, ENABLE);
 CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, ENABLE);
 CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, ENABLE);
 CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, ENABLE); 
}

Can anyone advise me on how I should configure TIM1 for it to count the number of pulses on channel 1 (pin C6)? Also, I've noticed I'm getting the same value from both TIM1_GetCounter(), and TIM1_GetCapture1(), can anyone advise me on the differences between these two signals?

    This topic has been closed for replies.
    Best answer by SBrow.1

    Ok, I managed to resolve this one. I am using the STM8S003F3, which only maps TIM1_CH1 to C6 as an alternate function (see datasheet). In order to use that alternate function, the option bytes need to be set. In this case this is the zero bit of option byte 2 (See the option byte section of the datasheet).

    Setting the Option bytes does not appear to be something one can configure in software (I could be wrong), and instead ought to be done with the STVP program. Once the option byte is correctly set, I am now able to count pulses from TIM1_Ch1!

    Some other observations I made in the course of this debug. While TIM1_Ch3 seems to be broken out to pin C3 without the need for an option byte. I can't seem to count off it. Also, be sure to correctly configure the GPIOs. Somthing like this:

    void GPIO_setup(void){
    	GPIO_DeInit(GPIOD); //deinitialize port D
    	GPIO_DeInit(GPIOC); //deinitialize port C
    	GPIO_Init(GPIOC, GPIO_PIN_3, GPIO_MODE_IN_FL_NO_IT); //C3 is FreqInput
    	GPIO_Init(GPIOC, GPIO_PIN_6, GPIO_MODE_IN_FL_NO_IT); //timer1 chan1
    	GPIO_Init(GPIOC, GPIO_PIN_7, GPIO_MODE_IN_FL_NO_IT); //timer1 chan2
    	GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_LOW_SLOW); //LED
    	GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_SLOW); //RS485 control
    	GPIO_Init(GPIOC, GPIO_PIN_4, GPIO_MODE_OUT_PP_LOW_SLOW); //C4 is the AND gate control
    	GPIO_WriteLow(GPIOC, GPIO_PIN_4); //AND Gate
    }

    1 reply

    SBrow.1AuthorAnswer
    Visitor II
    October 13, 2020

    Ok, I managed to resolve this one. I am using the STM8S003F3, which only maps TIM1_CH1 to C6 as an alternate function (see datasheet). In order to use that alternate function, the option bytes need to be set. In this case this is the zero bit of option byte 2 (See the option byte section of the datasheet).

    Setting the Option bytes does not appear to be something one can configure in software (I could be wrong), and instead ought to be done with the STVP program. Once the option byte is correctly set, I am now able to count pulses from TIM1_Ch1!

    Some other observations I made in the course of this debug. While TIM1_Ch3 seems to be broken out to pin C3 without the need for an option byte. I can't seem to count off it. Also, be sure to correctly configure the GPIOs. Somthing like this:

    void GPIO_setup(void){
    	GPIO_DeInit(GPIOD); //deinitialize port D
    	GPIO_DeInit(GPIOC); //deinitialize port C
    	GPIO_Init(GPIOC, GPIO_PIN_3, GPIO_MODE_IN_FL_NO_IT); //C3 is FreqInput
    	GPIO_Init(GPIOC, GPIO_PIN_6, GPIO_MODE_IN_FL_NO_IT); //timer1 chan1
    	GPIO_Init(GPIOC, GPIO_PIN_7, GPIO_MODE_IN_FL_NO_IT); //timer1 chan2
    	GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_LOW_SLOW); //LED
    	GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_SLOW); //RS485 control
    	GPIO_Init(GPIOC, GPIO_PIN_4, GPIO_MODE_OUT_PP_LOW_SLOW); //C4 is the AND gate control
    	GPIO_WriteLow(GPIOC, GPIO_PIN_4); //AND Gate
    }