In the official Application note, we can see that the PCNT oversampling routine uses a 32 Khz clock source as the reference clock source. There is also an orthogonal code. Although the external signal is used as the clock of the PCNT module, we rarely use orthogonal code.
In addition, we can better master this function only when we have used it. Therefore, we still use our STK to understand how PCNT uses external signals as the clock.
But one thing to note is that synchronization is a problem. If the external signal is a low-speed signal, and we need to modify the PCNT working mode, synchronization takes a long time.
Therefore, if it is a low-speed signal, we recommend that you use 32768 to sample the external signal to count the pulse signal. However, if it is a high-speed external signal, you can use this signal for both signal and clock.
Note that the G series PRS does not support PCNT. The TG series, PCNT, and even the number of pulses transmitted from the PRS. For more information, see the LESense demo.
In addition, the Timer can also be used to calculate the pulse frequency.
Hardware preparation:
Use tg stk. The pulse signal is generated by Timer, and the CCP0 and location3 of Timer0 are used in the program to point to the pd1. PCNT uses the S0 input of PCNT0 (remember that only the signal on S0 can be used as an external clock), that is, PD6. As shown in 1:
Add an LED lamp (PD7) foot.
In addition, to complete the overall function, you need to transient the 6th and 16 feet of the 20 PIN expansion port. Connect the PD1 and PD6 feet. The final result is that you can see that a light is turned off every 2 seconds.
Software preparation:
There aren't many complicated things. Please check the routine directly:
# Include "efm32.h"
# Include "efm32_cmu.h"
# Include "efm32_emu.h"
# Include "efm32_gpio.h"
# Include "efm32_prs.h"
# Include "efm32_system.h"
# Include "efm32_timer.h"
# Include "efm32_chip.h"
# Include "efm32_pcnt.h"
/* Define TOP value */
// The default clock source is 14 MHz and the timer frequency is 256.
// Make a 10Hz PWM output
# Define TOP 1 54687
/*************************************** **************
Note:
LFA clock uses LFRCO as the clock source by default. However, after LFRCO is reset,
Disabled by default.
However, to initialize PCNT and switch it to an external clock signal, you still need to use
LFRCO is used as the clock, so it is added
CMU_ClockSelectSet (cmuClock_LFA, cmuSelect_LFRCO)
**************************************** *************/
Void PCNT_Initial (void)
{
CMU_ClockSelectSet (cmuClock_LFA, cmuSelect_LFRCO );
/* Enabling all necessary clocks */
CMU_ClockEnable (cmuClock_CORELE, true);/* Enable CORELE clock */
CMU_ClockEnable (cmuClock_GPIO, true);/* Enable clock for GPIO module */
CMU_ClockEnable (cmuClock_PCNT0, true);/* Enable clock for PCNT module */
// CMU_PCNTClockExternalSet (0, true );
/* Configure PC4 as intput to drive pulse counter */
GPIO_PinModeSet (gpioPortD, 6, gpioModeInput, 0 );
/* Set configuration for pulse counter */
PCNT_Init_TypeDef pcntInit =
{
. Mode = pcntModeExtSingle, // pcntModeOvsSingle, // * clocked by LFACLK */
. Counter = 0,/* Set initial value to 0 */
. Top = 9,/* Set top to max value */
. NegEdge = false,/* positive edges */
. Countdown = false,/* up count */
. Filter = true,/* filter enabled */
};
/* Initialize Pulse counter */
Pcnt_init (pcnt0, & pcntinit );
/* Enable PCNT overflow interrupt */
Pcnt_intenable (pcnt0, 0x2 );
/* Enable pcnt1 interrupt vector in Objective C */
Nvic_enableirq (pcnt0_irqn );
/* Route PCNT1 input to location 0-> PCNT1_S0IN on PC4 */
PCNT0-> ROUTE = PCNT_ROUTE_LOCATION_LOC3;
}
Void Timer_Initial (void)
{
/* Enable clock for GPIO module */
CMU_ClockEnable (cmuClock_GPIO, true );
/* Enable clock for TIMER0 module */
CMU_ClockEnable (cmuClock_TIMER0, true );
/* Set CC0 location 3 pin (PD1) as output */
GPIO_PinModeSet (gpioPortD, 1, gpioModePushPull, 0 );
/* Select CC channel parameters */
TIMER_InitCC_TypeDef timerCCInit =
{
. Eventctrl = timereventeveryedge,
. Edge = timeredgeboth,
. Prssel = timerprsselch0,
. Cufoa = timeroutputactionnone,
. Cofoa = timeroutputactionnone,
. Cmoa = timeroutputactiontoggle,
. Mode = timerccmodepwm,
. Filter = false,
. PrsInput = false,
. Coist = false,
. OutInvert = false,
};
/* Configure CC channel 0 */
TIMER_InitCC (TIMER0, 0, & timerCCInit );
/* Route CC0 to location 3 (PD1) and enable pin */
TIMER0-> ROUTE | = (TIMER_ROUTE_CC0PEN | TIMER_ROUTE_LOCATION_LOC3 );
/* Set Top Value */
TIMER_TopSet (TIMER0, TOP/10 );
/* Set compare value starting at 0-it will be incremented in the interrupt handler */
TIMER_CompareBufSet (TIMER0, 0, TOP/20 );
/* Select timer parameters */
TIMER_Init_TypeDef timerInit =
{
. Enable = true,
. DebugRun = true,
. Prescale = timerPrescale256,
. ClkSel = timerClkSelHFPerClk,
. FallAction = timerInputActionNone,
. RiseAction = timerInputActionNone,
. Mode = timerModeUp,
. DmaClrAct = false,
. QuadModeX4 = false,
. OneShot = false,
. Sync = false,
};
/* Configure timer */
TIMER_Init (TIMER0, & timerInit );
}
/*************************************** ***********************************//**
* @ Brief Main function
* Main is called from _ iar_program_start, see assembly startup file
**************************************** *************************************/
Int main (void)
{
/* Initialize chip */
CHIP_Init ();
Timer_Initial ();
PCNT_Initial ();
GPIO_PinModeSet (gpioPortD, 7, gpioModePushPull, 0 );
While (1)
{
/* Go to EM1 */
EMU_EnterEM1 ();
}
}
Void PCNT0_IRQHandler (void)
{
/* Clear PCNT1 overflow interrupt flag */
PCNT_IntClear (PCNT0, 0x2 );
GPIO_PinOutToggle (gpioPortD, 7 );
}