Skip to main content
Hicss.2033
Associate III
July 8, 2020
Solved

is there a sample code showing how to count external events on a STM32F429I discovery (using timer 3)? Thanks, Piero

  • July 8, 2020
  • 4 replies
  • 1104 views

..

This topic has been closed for replies.
Best answer by Tesla DeLorean
// STM32F429I-DISCO TIM3 (CH1 PA6) External Count Demo - sourcer32@gmail.com
 
#include "stm32f429i_discovery.h"
 
//****************************************************************************
 
void GPIO_Configuration(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;
 
 /* GPIOA clock enable */
 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
 
 /* pin configuration */
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
 GPIO_Init(GPIOA, &GPIO_InitStructure);
 
 GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3); // PA6 TIM3_CH1
}
 
//****************************************************************************
 
void TIM3_Configuration(void)
{
 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
 int i;
 
 /* Enable TIM3 Peripheral clock */
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
 
 TIM_TimeBaseStructure.TIM_Prescaler = 0;
 TIM_TimeBaseStructure.TIM_Period = 100 - 1; // 100 (16-bit counter)
 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
 
 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
 
 TIM_TIxExternalClockConfig(TIM3, TIM_TIxExternalCLK1Source_TI1, TIM_ICPolarity_Rising, 0);
 
 TIM_Cmd(TIM3, ENABLE);
 
 // Likely will interrupt initially unless we clear it
 
 for(i=0; i<3; i++)
 if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
 TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
 
 TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
 
 // Could also use compare mode, set the counter maximal and advance CCRx 100 ticks at a time
}
 
//****************************************************************************
 
void TIM3_IRQHandler(void)
{
 if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
 {
 TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
 
 /* Toggle LED3 */
 STM_EVAL_LEDToggle(LED3);
 }
}
 
//****************************************************************************
 
void NVIC_Configuration(void)
{
 NVIC_InitTypeDef NVIC_InitStructure;
 
 /* Enable the TIM3 global Interrupt */
 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);
}
 
//****************************************************************************
 
int main(void)
{
 /* Initialize Leds mounted on STM32F429I-DISCO board */
 STM_EVAL_LEDInit(LED3);
 
 /* Turn on LED3 */
 STM_EVAL_LEDOn(LED3);
 
 NVIC_Configuration();
 
 GPIO_Configuration();
 
 TIM3_Configuration();
 
 while(1); // Do not exit
}
 
//******************************************************************************
 
#ifdef USE_FULL_ASSERT
/**
 * @brief Reports the name of the source file and the source line number
 * where the assert_param error has occurred.
 * @param file: pointer to the source file name
 * @param line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t* file, uint32_t line)
{
 /* User can add his own implementation to report the file name and line number,
 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 
 /* Infinite loop */
 while (1)
 {
 }
}
#endif
 
//******************************************************************************

4 replies

S.Ma
Principal
July 8, 2020

You should look at the corresponding Nucleo board examples, for timer and say input capture or external clock mode whichever closer to your needs.

Tesla DeLorean
Tesla DeLoreanBest answer
Guru
July 8, 2020
// STM32F429I-DISCO TIM3 (CH1 PA6) External Count Demo - sourcer32@gmail.com
 
#include "stm32f429i_discovery.h"
 
//****************************************************************************
 
void GPIO_Configuration(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;
 
 /* GPIOA clock enable */
 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
 
 /* pin configuration */
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
 GPIO_Init(GPIOA, &GPIO_InitStructure);
 
 GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3); // PA6 TIM3_CH1
}
 
//****************************************************************************
 
void TIM3_Configuration(void)
{
 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
 int i;
 
 /* Enable TIM3 Peripheral clock */
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
 
 TIM_TimeBaseStructure.TIM_Prescaler = 0;
 TIM_TimeBaseStructure.TIM_Period = 100 - 1; // 100 (16-bit counter)
 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
 
 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
 
 TIM_TIxExternalClockConfig(TIM3, TIM_TIxExternalCLK1Source_TI1, TIM_ICPolarity_Rising, 0);
 
 TIM_Cmd(TIM3, ENABLE);
 
 // Likely will interrupt initially unless we clear it
 
 for(i=0; i<3; i++)
 if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
 TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
 
 TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
 
 // Could also use compare mode, set the counter maximal and advance CCRx 100 ticks at a time
}
 
//****************************************************************************
 
void TIM3_IRQHandler(void)
{
 if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
 {
 TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
 
 /* Toggle LED3 */
 STM_EVAL_LEDToggle(LED3);
 }
}
 
//****************************************************************************
 
void NVIC_Configuration(void)
{
 NVIC_InitTypeDef NVIC_InitStructure;
 
 /* Enable the TIM3 global Interrupt */
 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);
}
 
//****************************************************************************
 
int main(void)
{
 /* Initialize Leds mounted on STM32F429I-DISCO board */
 STM_EVAL_LEDInit(LED3);
 
 /* Turn on LED3 */
 STM_EVAL_LEDOn(LED3);
 
 NVIC_Configuration();
 
 GPIO_Configuration();
 
 TIM3_Configuration();
 
 while(1); // Do not exit
}
 
//******************************************************************************
 
#ifdef USE_FULL_ASSERT
/**
 * @brief Reports the name of the source file and the source line number
 * where the assert_param error has occurred.
 * @param file: pointer to the source file name
 * @param line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t* file, uint32_t line)
{
 /* User can add his own implementation to report the file name and line number,
 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 
 /* Infinite loop */
 while (1)
 {
 }
}
#endif
 
//******************************************************************************

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Hicss.2033
Associate III
September 8, 2020

I thanks for your reply, but I'm using the HAL library on system workbench (I don't know which is the reference library of your example)

Hicss.2033
Associate III
July 20, 2020

thanks for yor reply

waclawek.jan
Super User
September 8, 2020

My take. No library.

// https://community.st.com/s/question/0D53W00000COHcsSAH/is-there-a-sample-code-showing-how-to-count-external-events-on-a-stm32f429i-discovery-using-timer-3-thanks-piero
// wek at efton dot sk
 
#include "stm32f4xx.h"
 
// 'F429 DISCO
// GREEN_LED PG13
// RED_LED PG14
#define GREEN_LED_PORT GPIOG
#define GREEN_LED_PIN 13
 
#define RED_LED_PORT GPIOG
#define RED_LED_PIN 14
 
 
 
// ------- defines missing from the device header -- normally I have the complete collection in a separate header, this is just to keep things in one file
 
 // GPIOx_MODER - 2 bits per pin
#define GPIO_Mode_In 0x00 // GPIO Input Mode
#define GPIO_Mode_Out 0x01 // GPIO Output Mode
#define GPIO_Mode_AlternateFunction 0x02 // GPIO Alternate function Mode
#define GPIO_Mode_AF GPIO_Mode_AlternateFunction
#define GPIO_Mode_Analog 0x03 // GPIO Analog Mode
 
#define GPIO_PullNone 0x00
#define GPIO_PullUp 0x01
#define GPIO_PullDown 0x02
 
#define GPIO_AlternateFunction_TIM3 2
 
#define SHL <<
#define AND &
#define PIN_SET(pin) pin##_PORT->BSRR = (1 SHL (pin##_PIN + 0))
#define PIN_CLR(pin) pin##_PORT->BSRR = (1 SHL (pin##_PIN + 16))
#define PIN_GET(pin) ((pin##_PORT->IDR AND (1 SHL pin##_PIN)) ? 1 : 0)
 
 
#define TIM_CCMR_CCS__INPUT_TI1 1 // CC unit in capture mode, input from "own" pin (i.e. TI1 for CC1, TI2 for CC2, TI3 for CC3, TI4 for CC4)
 
#define TIM_SMCR_TS__TI1FP1 5 // TI1FP1 with the same polarity as if CH1 used for capturing in CC1
 
#define TIM_SMCR_SMS__EXT_CLK_1 7
 
#define TIM_CCMR_ICF__32_8S 15 // input filter - 8 samples, sampled by fDTS/32
 
 
// -------- utils/frameworks
// trivial loopdelay
static void LoopDelay(volatile uint32_t n) {
	while(n > 0) n--;
}
 
#define DELAY_CONSTANT 1000000
 
 
 
// ---------------------------- MAIN ------------------------------
int main(void) {
 
 RCC->AHB1ENR |= 0
 | RCC_AHB1ENR_GPIOAEN // let's enable all GPIOs, we are going to use them all anyway, and don't plan to spare power significantly, so what
 | RCC_AHB1ENR_GPIOBEN
 | RCC_AHB1ENR_GPIOCEN
 | RCC_AHB1ENR_GPIODEN
 | RCC_AHB1ENR_GPIOEEN
 | RCC_AHB1ENR_GPIOFEN
 | RCC_AHB1ENR_GPIOGEN
 | RCC_AHB1ENR_GPIOHEN
 ;
 RCC->APB1ENR |= 0
 | RCC_APB1ENR_TIM3EN
 ;
 
 
 
 GPIOA->MODER = (GPIOA->MODER // assuming reset value
 ) | (0
 | (GPIO_Mode_AF * GPIO_MODER_MODER6_0) // PA6 - TIM3_CH1
 );
 GPIOA->AFR[0] = 0 // AFRL
 | (GPIO_AlternateFunction_TIM3 * GPIO_AFRL_AFRL6_0) // PA6 - TIM3_CH1
 ;
 GPIOA->PUPDR = GPIOA->PUPDR
 | (GPIO_PullUp * GPIO_PUPDR_PUPDR6_0) // pulled up, so can wiggle it by pulling it to GND
 ;
 // PA6 is input so no need for OSPEEDR setting
 
 GPIOG->MODER = (GPIOG->MODER
 ) | (0
 | (GPIO_Mode_Out * GPIO_MODER_MODER13_0) // GREEN_LED
 | (GPIO_Mode_Out * GPIO_MODER_MODER14_0) // RED_LED
 );
 // LEDs don't need to change OSPEEDR nor any other GPIO register
 
 
 // now setup TIM3 for the external counter
 // leave PSC and ARR at their defaults
 TIM3->CCMR1 = 0
 | (TIM_CCMR_CCS__INPUT_TI1 * TIM_CCMR1_CC1S_0) // input capture from "its own" pin
 | (TIM_CCMR_ICF__32_8S * TIM_CCMR1_IC1F_0) // set the heaviest filtering here, as we are going to wiggle the pin using a loose wire
 ;
 TIM3->CCER = 0
 | (1 * TIM_CCER_CC1E) // enable TIM1_CH1
 ;
 TIM3->SMCR = 0
 | (TIM_SMCR_TS__TI1FP1 * TIM_SMCR_TS_0) // select TI1FP1 (filtered CH1) as TRGI source
 | (TIM_SMCR_SMS__EXT_CLK_1 * TIM_SMCR_SMS_0) // and set external clock mode for slave controller
 ;
 TIM3->CR1 = 0
 | (1 * TIM_CR1_CEN) // enable counter
 ;
 
 // for the laughs, enable interrupt from the capture
 TIM3->DIER = 0
 | (1 * TIM_DIER_CC1IE) // enable interrupt from CC1
 ;
 NVIC_EnableIRQ(TIM3_IRQn);
 
 
 
 while(1) {
 PIN_SET(RED_LED);
 LoopDelay(DELAY_CONSTANT);
 PIN_CLR(RED_LED);
 LoopDelay(DELAY_CONSTANT);
 __asm("nop");
 }
}
 
 
// interrupt handler
 
void TIM3_IRQHandler(void) {
 uint32_t sr;
 
 sr = TIM3->SR;
 TIM3->SR = ~sr; // clear flags
 
 if (sr & TIM_SR_CC1IF) {
 if (PIN_GET(GREEN_LED)) {
 PIN_CLR(GREEN_LED);
 } else {
 PIN_SET(GREEN_LED);
 }
 }
}

JW