This article records the capture function of the timer
1. Can capture square waves of any length, test millisecond and second level capture is no problem
2. A 10s timeout (TIMER_CAP_TIMEOUT) is added to get_period and get_freq in the code to only capture square waves with a period of less than 10s.
3. Select one of the channels for the capture function through macro definition TIMER1_CH0_GPIO_A0, TIMER1_CH1_GPIO_A1, TIMER1_CH2_GPIO_B10, TIMER1_CH3_GPIO_B11
4. Call timer_capture_config() first, then call timer_start_capture(), then get_freq() or get_period()
The source code is as follows:
#include "timer.h"
#include "gd32l23x_timer.h"
#include "systick.h"
//#define TIMER1_CH0_GPIO_A0
//#define TIMER1_CH1_GPIO_A1
//#define TIMER1_CH2_GPIO_B10
#define TIMER1_CH3_GPIO_B11
/*
capture timeout, 10s , unit: ms
The capture period is within TIMER_CAP_TIMEOUT
*/
#define TIMER_CAP_TIMEOUT 10000U
#if defined TIMER1_CH0_GPIO_A0
#define CAPTURE_TIMER_RCU RCU_TIMER1
#define CAPTURE_TIMER TIMER1
#define CAPTURE_CHN TIMER_CH_0
#define CAPTURE_INT_CHN TIMER_INT_CH0
#define CAPTURE_TIMER_IRQ TIMER1_IRQn
#define CAPTURE_GPIO_RCU RCU_GPIOA
#define CAPTURE_GPIO GPIOA
#define CAPTURE_GPIO_PIN GPIO_PIN_0
#define CAPTURE_GPIO_AF GPIO_AF_1
#elif defined TIMER1_CH1_GPIO_A1
#define CAPTURE_TIMER_RCU RCU_TIMER1
#define CAPTURE_TIMER TIMER1
#define CAPTURE_CHN TIMER_CH_1
#define CAPTURE_INT_CHN TIMER_INT_CH1
#define CAPTURE_TIMER_IRQ TIMER1_IRQn
#define CAPTURE_GPIO_RCU RCU_GPIOA
#define CAPTURE_GPIO GPIOA
#define CAPTURE_GPIO_PIN GPIO_PIN_1
#define CAPTURE_GPIO_AF GPIO_AF_1
#elif defined TIMER1_CH2_GPIO_B10
#define CAPTURE_TIMER_RCU RCU_TIMER1
#define CAPTURE_TIMER TIMER1
#define CAPTURE_CHN TIMER_CH_2
#define CAPTURE_INT_CHN TIMER_INT_CH2
#define CAPTURE_TIMER_IRQ TIMER1_IRQn
#define CAPTURE_GPIO_RCU RCU_GPIOB
#define CAPTURE_GPIO GPIOB
#define CAPTURE_GPIO_PIN GPIO_PIN_10
#define CAPTURE_GPIO_AF GPIO_AF_1
#elif defined TIMER1_CH3_GPIO_B11
#define CAPTURE_TIMER_RCU RCU_TIMER1
#define CAPTURE_TIMER TIMER1
#define CAPTURE_CHN TIMER_CH_3
#define CAPTURE_INT_CHN TIMER_INT_CH3
#define CAPTURE_TIMER_IRQ TIMER1_IRQn
#define CAPTURE_GPIO_RCU RCU_GPIOB
#define CAPTURE_GPIO GPIOB
#define CAPTURE_GPIO_PIN GPIO_PIN_11
#define CAPTURE_GPIO_AF GPIO_AF_1
#endif
uint32_t readvalue1 = 0, readvalue2 = 0;
__IO uint16_t ccnumber = 0;
__IO uint32_t ccount = 0;
__IO uint16_t cap_finish_flag = 0;
/*!
\brief configure the GPIO ports
\param[in] none
\param[out] none
\retval none
*/
static void timer_gpio_config(void)
{
rcu_periph_clock_enable(CAPTURE_GPIO_RCU);
/* TIMER1 GPIO */
gpio_af_set(CAPTURE_GPIO, CAPTURE_GPIO_AF, CAPTURE_GPIO_PIN);
gpio_mode_set(CAPTURE_GPIO, GPIO_MODE_AF, GPIO_PUPD_NONE, CAPTURE_GPIO_PIN);
gpio_output_options_set(CAPTURE_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, CAPTURE_GPIO_PIN);
}
/*!
\brief configure the TIMER peripheral
\param[in] none
\param[out] none
\retval none
*/
void timer_capture_config(void)
{
/* TIMER1 configuration: input capture mode -------------------
the external signal is connected to TIMER1 CHx pin
the rising edge is used as active edge
the TIMER1 CHxCV is used to compute the frequency value
------------------------------------------------------------ */
timer_parameter_struct timer_initpara;
timer_ic_parameter_struct timer_icinitpara;
timer_gpio_config();
/* enable the peripherals clock */
rcu_periph_clock_enable(CAPTURE_TIMER_RCU);
/* deinit a TIMER */
timer_deinit(CAPTURE_TIMER);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER1 configuration */
timer_initpara.prescaler = 63;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 65535;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_init(CAPTURE_TIMER, &timer_initpara);
/* TIMER1 CHx input capture configuration */
timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING;
timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
timer_icinitpara.icfilter = 0x00;
timer_input_capture_config(CAPTURE_TIMER, CAPTURE_CHN, &timer_icinitpara);
/* auto-reload preload enable */
timer_auto_reload_shadow_enable(CAPTURE_TIMER);
/* enable a TIMER */
timer_enable(CAPTURE_TIMER);
}
/*!
\brief timer start capture
\param[in] none
\param[out] none
\retval none
*/
void timer_start_capture(void)
{
cap_finish_flag = 0;
ccnumber = 0;
/* clear channel interrupt bit */
timer_interrupt_flag_clear(CAPTURE_TIMER, CAPTURE_INT_CHN);
/* channel interrupt enable */
timer_interrupt_enable(CAPTURE_TIMER, CAPTURE_INT_CHN);
/* clear channel interrupt bit */
timer_interrupt_flag_clear(CAPTURE_TIMER, TIMER_INT_UP);
/* channel interrupt enable */
timer_interrupt_enable(CAPTURE_TIMER, TIMER_INT_UP);
nvic_irq_enable(CAPTURE_TIMER_IRQ, 0);
}
/*!
\brief get frequency
\param[in] none
\param[out] none
\retval float frequency, unit: Hz
*/
float get_freq(void)
{
uint32_t timeout = 0;
float freq = 0.0f;
while(0 == cap_finish_flag)
{
delay_1ms(1u);
timeout++;
if(timeout > TIMER_CAP_TIMEOUT)
{
freq = 0;
nvic_irq_disable(CAPTURE_TIMER_IRQ);
timer_interrupt_disable(CAPTURE_TIMER, CAPTURE_INT_CHN);
timer_interrupt_disable(CAPTURE_TIMER, TIMER_INT_UP);
break;
}
}
if (0 != ccount)
{
freq = 1000000.0f / (float)ccount;
}
return freq;
}
/*!
\brief get period
\param[in] none
\param[out] none
\retval float period, unit: ms
*/
float get_period(void)
{
uint32_t timeout = 0;
float period = 0.0f;
while(0 == cap_finish_flag)
{
delay_1ms(1u);
timeout++;
if(timeout > TIMER_CAP_TIMEOUT)
{
period = 0;
nvic_irq_disable(CAPTURE_TIMER_IRQ);
timer_interrupt_disable(CAPTURE_TIMER, CAPTURE_INT_CHN);
timer_interrupt_disable(CAPTURE_TIMER, TIMER_INT_UP);
break;
}
}
if (timeout < TIMER_CAP_TIMEOUT)
{
period = (float)ccount/1000.0f;
}
return period;
}
/*!
\brief this function handles TIMER1 interrupt request.
\param[in] none
\param[out] none
\retval none
*/
void timer_isr(void)
{
static uint8_t cnt = 0;
if(SET == timer_interrupt_flag_get(CAPTURE_TIMER, TIMER_INT_FLAG_UP)) {
timer_interrupt_flag_clear(CAPTURE_TIMER, TIMER_INT_FLAG_UP);
if(1 == ccnumber)
{
cnt++;
}
}
if(SET == timer_interrupt_flag_get(CAPTURE_TIMER, CAPTURE_INT_CHN)) {
/* clear channel x interrupt bit */
timer_interrupt_flag_clear(CAPTURE_TIMER, CAPTURE_INT_CHN);
if(0 == ccnumber) {
/* read channel x capture value */
readvalue1 = timer_channel_capture_value_register_read(CAPTURE_TIMER, CAPTURE_CHN) + 1;
ccnumber = 1;
} else if(1 == ccnumber) {
/* read channel x capture value */
readvalue2 = timer_channel_capture_value_register_read(CAPTURE_TIMER, CAPTURE_CHN) + 1;
if(readvalue2 > readvalue1) {
ccount = (0xFFFF * cnt + readvalue2 - readvalue1);
} else {
ccount = (0xFFFF * (cnt - 1) + (0xFFFF - readvalue1) + readvalue2);
}
cap_finish_flag = 1;
ccnumber = 0;
cnt = 0;
nvic_irq_disable(CAPTURE_TIMER_IRQ);
timer_interrupt_disable(CAPTURE_TIMER, CAPTURE_INT_CHN);
timer_interrupt_disable(CAPTURE_TIMER, TIMER_INT_UP);
}
}
}
Interrupt handling function
extern void timer_isr(void);
/*!
\brief this function handles TIMER1 interrupt request.
\param[in] none
\param[out] none
\retval none
*/
void TIMER1_IRQHandler(void)
{
timer_isr();
}
|