/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url] main.c
* [url=home.php?mod=space&uid=895143]@version[/url] V3.00
* [url=home.php?mod=space&uid=247401]@brief[/url] Show how to use ECAP interface to get QEIA frequency
*
* [url=home.php?mod=space&uid=17282]@CopyRight[/url] (C) 2016 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include "NuMicro.h"
#define PLL_CLOCK 192000000
/*---------------------------------------------------------------------------------------------------------*/
/* Global variables */
/*---------------------------------------------------------------------------------------------------------*/
uint32_t u32Status;
uint32_t u32IC0Hold;
void TMR0_IRQHandler(void)
{
if(TIMER_GetIntFlag(TIMER0) == 1)
{
/* Clear Timer0 time-out interrupt flag */
TIMER_ClearIntFlag(TIMER0);
/*PA.0 gpio toggle */
PA0 ^= 1;
}
}
void ECAP0_IRQHandler(void)
{
/* Get input Capture status */
u32Status = ECAP_GET_INT_STATUS(ECAP0);
/* Check input capture channel 0 flag */
if((u32Status & ECAP_STATUS_CAPTF0_Msk) == ECAP_STATUS_CAPTF0_Msk)
{
/* Clear input capture channel 0 flag */
ECAP_CLR_CAPTURE_FLAG(ECAP0, ECAP_STATUS_CAPTF0_Msk);
/* Get input capture counter hold value */
u32IC0Hold = ECAP0->HLD0;
}
/* Check input capture channel 1 flag */
if((u32Status & ECAP_STATUS_CAPTF1_Msk) == ECAP_STATUS_CAPTF1_Msk)
{
/* Clear input capture channel 1 flag */
ECAP_CLR_CAPTURE_FLAG(ECAP0, ECAP_STATUS_CAPTF1_Msk);
}
/* Check input capture channel 2 flag */
if((u32Status & ECAP_STATUS_CAPTF2_Msk) == ECAP_STATUS_CAPTF2_Msk)
{
/* Clear input capture channel 2 flag */
ECAP_CLR_CAPTURE_FLAG(ECAP0, ECAP_STATUS_CAPTF2_Msk);
}
/* Check input capture compare-match flag */
if((u32Status & ECAP_STATUS_CAPCMPF_Msk) == ECAP_STATUS_CAPCMPF_Msk)
{
/* Clear input capture compare-match flag */
ECAP_CLR_CAPTURE_FLAG(ECAP0,ECAP_STATUS_CAPCMPF_Msk);
}
/* Check input capture overflow flag */
if((u32Status & ECAP_STATUS_CAPOVF_Msk) == ECAP_STATUS_CAPOVF_Msk)
{
/* Clear input capture overflow flag */
ECAP_CLR_CAPTURE_FLAG(ECAP0,ECAP_STATUS_CAPOVF_Msk);
}
}
void SYS_Init(void)
{
/* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);
/* Enable external XTAL 12MHz clock */
CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk);
/* Waiting for external XTAL clock ready */
CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);
/* Set core clock as PLL_CLOCK from PLL */
CLK_SetCoreClock(PLL_CLOCK);
/* Set PCLK0/PCLK1 to HCLK/2 */
CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);
/* Enable UART module clock */
CLK_EnableModuleClock(UART0_MODULE);
/* Enable ECAP0 module clock */
CLK_EnableModuleClock(ECAP0_MODULE);
/* Enable QEI0 module clock */
CLK_EnableModuleClock(QEI0_MODULE);
/* Enable TIMER0 module clock */
CLK_EnableModuleClock(TMR0_MODULE);
/* Select UART module clock source */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HXT, CLK_CLKDIV0_UART0(1));
/* Select TMR0 module clock source */
CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_HXT, 0);
/* Set GPB multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk);
SYS->GPB_MFPH |= (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
/* Set PA.10 for ECAP0_IC0*/
SYS->GPA_MFPH = (SYS->GPA_MFPL & ~SYS_GPA_MFPH_PA10MFP_Msk) |SYS_GPA_MFPH_PA10MFP_ECAP0_IC0;
/* Set PA multi-function pins for QEI0_A, QEI0_B, QEI0_INDEX */
SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA4MFP_Msk | SYS_GPA_MFPL_PA3MFP_Msk | SYS_GPA_MFPL_PA5MFP_Msk);
SYS->GPA_MFPL |= (SYS_GPA_MFPL_PA4MFP_QEI0_A | SYS_GPA_MFPL_PA3MFP_QEI0_B | SYS_GPA_MFPL_PA5MFP_QEI0_INDEX);
}
void UART0_Init(void)
{
/* Configure UART0 and set UART0 Baudrate */
UART_Open(UART0, 115200);
}
void ECAP0_Init(void)
{
/* Enable ECAP0*/
ECAP_Open(ECAP0, ECAP_DISABLE_COMPARE);
/* Select Reload function */
ECAP_SET_CNT_CLEAR_EVENT(ECAP0, (ECAP_CTL1_CAP0RLDEN_Msk|ECAP_CTL1_CAP1RLDEN_Msk));
/* Enable ECAP0 Input Channel 0*/
ECAP_ENABLE_INPUT_CHANNEL(ECAP0, ECAP_CTL0_IC0EN_Msk);
/* Enable ECAP0 source from IC0 */
ECAP_SEL_INPUT_SRC(ECAP0, ECAP_IC0, ECAP_CAP_INPUT_SRC_FROM_CH);
/* Select IC0 detect rising edge */
ECAP_SEL_CAPTURE_EDGE(ECAP0, ECAP_IC0, ECAP_RISING_EDGE);
/* Input Channel 0 interrupt enabled */
ECAP_EnableINT(ECAP0, ECAP_CTL0_CAPIEN0_Msk);
}
void QEI0_Init(void)
{
QEI_Open(QEI0,QEI_CTL_X4_FREE_COUNTING_MODE,0);
}
void Timer0_Init(void)
{
/* Open Timer0 in periodic mode, enable interrupt and 1 interrupt tick per second */
TIMER_Open(TIMER0,TIMER_PERIODIC_MODE,10000);
TIMER_EnableInt(TIMER0);
/* Enable Timer0 NVIC */
NVIC_EnableIRQ(TMR0_IRQn);
}
int32_t main(void)
{
uint32_t u32Hz=0, u32Hz_DET=0;
/* Unlock protected registers */
SYS_UnlockReg();
/* Init System, IP clock and multi-function I/O */
SYS_Init();
/* Lock protected registers */
SYS_LockReg();
/* Init UART0 for printf */
UART0_Init();
printf("\n");
printf("+----------------------------------------------+\n");
printf("| M480 ECAP with QEI Sample Code |\n");
printf("+----------------------------------------------+\n");
printf("\n");
printf(" !! GPIO PA.0 toggle periodically !!\n");
printf(" !! Connect PA.0 --> PA.4(QEI0_A) !!\n\n");
printf(" Press any key to start test\n\n");
getchar();
/* Initial ECAP0 function */
ECAP0_Init();
/* Initial QEI0 function */
QEI0_Init();
/* Initial Timer0 function */
Timer0_Init();
/* Configure PA.0 as output mode */
GPIO_SetMode(PA, BIT0, GPIO_MODE_OUTPUT);
/* Start Timer0 counting */
TIMER_Start(TIMER0);
/* Delay 200ms */
CLK_SysTickDelay(200000);
/* Init & clear ECAP interrupt status flags */
u32Status = ECAP_GET_INT_STATUS(ECAP0);
ECAP0->STATUS = u32Status;
/* ECAP_CNT starts up-counting */
ECAP_CNT_START(ECAP0);
while(1)
{
if(u32Status != 0)
{
/* Input Capture status is changed, and get a new hold value of input capture counter */
u32Status = 0;
/* Calculate the IC0 input frequency */
u32Hz_DET = (SystemCoreClock/2) / (u32IC0Hold + 1);
if(u32Hz != u32Hz_DET)
{
/* If IC0 input frequency is changed, Update frequency */
u32Hz = u32Hz_DET;
}
else
{
printf("\nECAP0_IC0 input frequency is %d (Hz),u32IC0Hold=0x%08x\n", u32Hz,u32IC0Hold);
TIMER_Stop(TIMER0); //Disable timer Counting.
break;
}
}
}
/* Disable External Interrupt */
NVIC_DisableIRQ(ECAP0_IRQn);
NVIC_DisableIRQ(TMR0_IRQn);
/* Disable ECAP function */
ECAP_Close(ECAP0);
/* Disable Timer0 IP clock */
CLK_DisableModuleClock(TMR0_MODULE);
/* Disable ECAP IP clock */
CLK_DisableModuleClock(ECAP0_MODULE);
printf("\nExit ECAP sample code\n");
while(1);
}
这段程序演示了如何使用NuMicro系列微控制器的ECAP(Enhanced Capture)接口和QEI(Quadrature Encoder Interface)接口来获取旋转编码器的输入频率。下面是主要功能和流程解析:
初始化和系统设置:
设置系统时钟和UART接口,配置用于调试输出的UART0。
启用和配置ECAP0、QEI0和TIMER0模块的时钟。
ECAP模块初始化:
打开ECAP0模块并禁用比较功能。
配置ECAP0的输入捕获通道(IC0),选择从通道输入源获取输入信号(这里与前一个例子不同)。
设置IC0检测上升沿触发,并启用IC0的输入捕获功能。
启用ECAP0的中断,用于处理捕获事件。
QEI模块初始化:
配置QEI0模块为X4自由计数模式,用于读取旋转编码器的计数值。
TIMER0定时器初始化:
配置TIMER0为周期模式,并启用定时器中断,每秒钟产生一次中断。
中断处理函数:
TMR0_IRQHandler():处理TIMER0定时器的中断事件,实现定时器中PA0引脚的周期性翻转。
ECAP0_IRQHandler():处理ECAP0模块的捕获事件,获取并处理输入捕获的状态和数据。
|