2020-10-13 09:07 AM
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?
Solved! Go to Solution.
2020-10-13 12:17 PM
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
}
2020-10-13 12:17 PM
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
}