cancel
Showing results for 
Search instead for 
Did you mean: 

STM8 Frequency Counter

SBrow.1
Associate II

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?

1 ACCEPTED SOLUTION

Accepted Solutions
SBrow.1
Associate II

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
}

View solution in original post

1 REPLY 1
SBrow.1
Associate II

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
}