打印
[DemoCode下载]

定时器计数

[复制链接]
2277|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V3.00
* $Revision: 3 $
* $Date: 14/01/28 11:45a $
* [url=home.php?mod=space&uid=247401]@brief[/url]    M051 Series Timer Driver Sample Code
*
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include "M051Series.h"

#define PLLCON_SETTING      CLK_PLLCON_50MHz_HXT
#define PLL_CLOCK           50000000


/*---------------------------------------------------------------------------------------------------------*/
/* Global Interface Variables Declarations                                                                 */
/*---------------------------------------------------------------------------------------------------------*/
volatile uint32_t g_au32TMRINTCount[4] = {0};


/*---------------------------------------------------------------------------------------------------------*/
/*  Create Counter Source by GPIO PORT2                                                                    */
/*---------------------------------------------------------------------------------------------------------*/
void GeneratePORT2Counter(uint32_t u32Pin, uint32_t u32Counts)
{
    while(u32Counts--)
    {
        GPIO_PIN_ADDR(2, u32Pin) = 1;
        GPIO_PIN_ADDR(2, u32Pin) = 0;
    }
}

/**
* @brief       Timer1 IRQ
*
* @param       None
*
* [url=home.php?mod=space&uid=266161]@return[/url]      None
*
* [url=home.php?mod=space&uid=1543424]@Details[/url]     The Timer1 default IRQ, declared in startup_M051Series.s.
*/
void TMR1_IRQHandler(void)
{
    if(TIMER_GetIntFlag(TIMER1) == 1)
    {
        /* Clear Timer1 time-out interrupt flag */
        TIMER_ClearIntFlag(TIMER1);

        g_au32TMRINTCount[1]++;
    }
}

void SYS_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Enable IRC22M clock */
    CLK->PWRCON |= CLK_PWRCON_IRC22M_EN_Msk;

    /* Waiting for IRC22M clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_IRC22M_STB_Msk);

    /* Switch HCLK clock source to HIRC */
    CLK->CLKSEL0 = CLK_CLKSEL0_HCLK_S_HIRC;

    /* Set PLL to Power-down mode and PLL_STB bit in CLKSTATUS register will be cleared by hardware.*/
    CLK->PLLCON |= CLK_PLLCON_PD_Msk;

    /* Enable external 12 MHz XTAL */
    CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk;

    /* Enable PLL and Set PLL frequency */
    CLK->PLLCON = PLLCON_SETTING;

    /* Waiting for clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk | CLK_CLKSTATUS_XTL12M_STB_Msk);

    /* Switch HCLK clock source to PLL, STCLK to HCLK/2 */
    CLK->CLKSEL0 = CLK_CLKSEL0_STCLK_S_HCLK_DIV2 | CLK_CLKSEL0_HCLK_S_PLL;

    /* Enable peripheral clock */
    CLK->APBCLK = CLK_APBCLK_UART0_EN_Msk | CLK_APBCLK_TMR1_EN_Msk;

    /* Peripheral clock source */
    CLK->CLKSEL1 = CLK_CLKSEL1_UART_S_PLL | CLK_CLKSEL1_TMR1_S_HCLK;

    /* Update System Core Clock */
    /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
    SystemCoreClockUpdate();

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Set P3 multi-function pins for UART0 RXD, TXD and T1 */
    SYS->P3_MFP = SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0 | SYS_MFP_P35_T1;
}

void UART0_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init UART                                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Reset IP */
    SYS_ResetModule(UART0_RST);

    /* Configure UART0 and set UART0 Baudrate */
    UART_Open(UART0, 115200);
}

/*---------------------------------------------------------------------------------------------------------*/
/*  MAIN function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int main(void)
{
    volatile uint32_t u32InitCount;

    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Init System, peripheral clock and multi-function I/O */
    SYS_Init();

    /* Lock protected registers */
    SYS_LockReg();

    /* Init UART0 for printf */
    UART0_Init();

    printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %d Hz\n", SystemCoreClock);
    printf("+-------------------------------------------------+\n");
    printf("|    Timer1 External Counter Input Sample Code    |\n");
    printf("+-------------------------------------------------+\n\n");

    printf("# Timer Settings:\n");
    printf("  Timer1: Clock source is HCLK(50 MHz); Continuous counting mode; Interrupt enable;\n");
    printf("          External counter input enable; TCMP is 56789.\n");
    printf("# Connect P2.0 to T1 pin and pull P2.0 High/Low as T1 counter input source.\n\n");

    /* Configure P2.0 as GPIO output pin and pull pin status to Low first */
    GPIO_SetMode(P2, 0, GPIO_PMD_OUTPUT);
    P20 = 0;

    /* Initial Timer1 default setting */
    TIMER_Open(TIMER1, TIMER_CONTINUOUS_MODE, 1);

    /* Configure Timer1 setting for external counter input function */
    TIMER_SELECT_TOUT_PIN(TIMER1, TIMER_TOUT_PIN_FROM_TX_PIN);
    TIMER_SET_PRESCALE_VALUE(TIMER1, 0);
    TIMER_SET_CMP_VALUE(TIMER1, 56789);
    TIMER_EnableEventCounter(TIMER1, TIMER_COUNTER_FALLING_EDGE);
    TIMER_EnableInt(TIMER1);

    /* Enable Timer1 NVIC */
    NVIC_EnableIRQ(TMR1_IRQn);

    /* Clear Timer1 interrupt counts to 0 */
    g_au32TMRINTCount[1] = 0;

    /* Start Timer1 counting */
    TIMER_Start(TIMER1);

    /* To check if TDR of Timer1 must be 0 as default value */
    if(TIMER_GetCounter(TIMER1) != 0)
    {
        printf("Default counter value is not 0. (%d)\n", TIMER_GetCounter(TIMER1));

        /* Stop Timer1 counting */
        TIMER_Close(TIMER1);
        while(1);
    }

    /* To generate one counter event to T1 pin */
    GeneratePORT2Counter(0, 1);

    /* To check if TDR of Timer1 must be 1 */
    while(TIMER_GetCounter(TIMER1) == 0);
    if(TIMER_GetCounter(TIMER1) != 1)
    {
        printf("Get unexpected counter value. (%d)\n", TIMER_GetCounter(TIMER1));

        /* Stop Timer1 counting */
        TIMER_Close(TIMER1);
        while(1);
    }

    /* To generate remains counts to T1 pin */
    GeneratePORT2Counter(0, (56789 - 1));

    while(1)
    {
        if((g_au32TMRINTCount[1] == 1) && (TIMER_GetCounter(TIMER1) == 56789))
        {
            printf("Timer1 external counter input function ... PASS.\n");
            break;
        }
    }

    /* Stop Timer1 counting */
    TIMER_Close(TIMER1);

    while(1);
}

/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/


沙发
玛尼玛尼哄|  楼主 | 2016-7-24 21:12 | 只看该作者
This sample code is showing how to use counter function on timer-1 counter input pin.

使用特权

评论回复
板凳
玛尼玛尼哄|  楼主 | 2016-7-24 21:17 | 只看该作者
定时器控制器包括4组32位的定时器, TIMER0~TIMER3, 方便用户的定时器控制应用。定时器模块可支
持例如频率测量,计数,间隔时间测量,时钟产生,延迟时间等功能。定时器可在计时溢出时产生中断
信号,也可在操作过程中提供计数的当前值

使用特权

评论回复
地板
玛尼玛尼哄|  楼主 | 2016-7-24 21:17 | 只看该作者
特征
y 4 组 32-位定时器,带24位向上定时器和一个8位的预分频计数器
y 每个定时器都有独立的时钟源
y 24位向上计数器,通过TDR(定时器数据寄存器)可读取
y 4种工作模式:单脉冲模式(one-shot), 周期模式(periodic),开关模式(toggle)和连续计数(continuouscounting)模式操作模式

使用特权

评论回复
5
玛尼玛尼哄|  楼主 | 2016-7-24 21:18 | 只看该作者
每个通道带一个8位预分频计数器,一个24位向上计数器,一个24位比较寄存器和一个中断请求信号。
参阅图 6.8-1的定时器控制框图。每个通道有3个时钟源选项,图 6.8-2说明了时钟源控制功能。 可软件
编程配置8位预分频系数来确定24位向上计数器的时钟周期。



使用特权

评论回复
6
玛尼玛尼哄|  楼主 | 2016-7-24 21:19 | 只看该作者
定时器操作模式
定时器控制器提供4种工作模式,单脉冲(one-shot)模式、周期(periodic)模式、开关( toggle)和 连
续计数(continuous counting)模式。 . 每种操作功能模式如下所示:
单脉冲模式
如果定时器工作在单脉冲 模式且CEN (定时器使能位) 置1, 定时器的计数器开始计数. 一旦定时器计
数器的值达到定时器比较器寄存器 (TCMPR) 的值, 且IE (中断使能位) 置1, 则定时器中断标志置
位,产生中断信号并送到NVIC通知CPU. 表明定时器计数发生溢出. 如果IE (interrupt enable bit) 置
0, 无中断信号产生. 在此工作模式下, 一旦定时器计数器的值达到定时器比较寄存器 (TCMPR) 的
值, 定时器计数器的值返回初始值且CEN (定时器使能位)由定时器控制器清零. 一旦定时器计数器的
值达到定时器比较寄存器(TCMPR) 的值,定时器计数操作停止,。也就是说, 在编程比较寄存器
( TCMPR)的值与CEN(定时器使能位)置1后,定时器操作定时器计数和与TCMPR值的比较仅执
行一次.因此,该操作称为单脉冲 模式

使用特权

评论回复
7
玛尼玛尼哄|  楼主 | 2016-7-24 21:19 | 只看该作者
周期 模式
如果定时器工作在周期模式且CEN (定时器使能位)置1, 定时器计数器开始计数. 一旦定时器计数器
的值达到定时器比较寄存器 (TCMPR)的值, 且IE (中断使能位) 设置为1, 则定时器中断标志置位且
产生中断信号,并发送到NVIC通知CPU. 表示定时器计数溢出发生. 如果IE (中断使能位)设置为0,
无中断信号发生. 在该工作模式下, 一旦定时器计数器的值达到定时器比较器寄存器(TCMPR) 的值,
定时器计数器的值返回计数初始值且CEN 保持为1 (持续使能计数). 定时器计数器重新开始计数. 如
果软件清除中断标志, 一旦定时器计数器的值与定时器比较寄存器(TCMPR)的值匹配且IE (中断使
能位)设置为1 中断标志置位,产生中断信号并送到NVIC再次通知CPU. 也就是说, 定时器操作定时
器计数和与TCMPR比较功能是周期性进行的. 直到CEN设置为0,定时器计数操作才会停止.中断信
号的产生也是周期性的. 因此, 这种操作模式称为周期模式.

使用特权

评论回复
8
玛尼玛尼哄|  楼主 | 2016-7-24 21:23 | 只看该作者
开关模式
如果定时器工作在开关模式且CEN (定时器使能位)置1, 定时器计数器开始计数. 一旦定时器计数器的值
与定时器比较寄存器TCMPR的值匹配时, 且IE (中断使能位)设置为 1, 则定时器中断标志置位,产生中断
信号并送到NVIC通知CPU. 表示定时器发生计数溢出. 相应开关输出(tout) 信号置1. 在这种操作模式, 一
旦定时器计数器的值与定时器比较寄存器TCMPR的值匹配, 定时器计数器的值返回到计数初始值且
CEN 保持为 1 (持续使能计数). 定时器计数器重新开始计数. 如果中断标志由软件清除,一旦定时器计数
器的值与定时器比较寄存器中TCMPR的值匹配且IE (中断使能位) 置1, 则定时器中断标志置位,发生中
断信号,并送到NVIC再次通知CPU. 相应开关输出 (tout)信号置0. 定时器计数操作在CEN设置为0之后
才停止. 因此, 开关输出 (tout)信号 以50%的占空比反复改变. 所以这种操作模式称为开关模式.

使用特权

评论回复
9
玛尼玛尼哄|  楼主 | 2016-7-24 21:23 | 只看该作者
连续计数模式
如果定时器工作在连续计数模式且CEN (定时器使能位)置1, 如果IE(中断使能位)设置为1, 当TDR =
TCMPR 时,相关的中断信号产生。用户可以立即改变TCMPR的值,而不需要禁用或重启定时器计
数。例如, TCMPR的值先被设置为80(TCMPR的值应当小于224 -1并且大于1), 当TDR的值等于80
时,如果IE (中断使能位)设置为1,定时器产生中断, TIF(定时器中断标志)将被置位,产生中断信号并
送到NVIC通知CPU,且CEN 保持为 1 (持续使能计数),但是TDR的值不会返回到零,而是继续计数81,
82, 83,˙˙˙ to 224 -1, 0, 1, 2, 3, ˙˙˙ to 224 -1。接下来,如果用户设置TCMPR为200,且TIF被清
零,当TDR的值达到200,定时器中断发生, TIF被置位,产生中断信号并送到NVIC再次通知CPU。最后,用户设置TCMPR为500,并再一次清零TIF,当TDR的值达到500,定时器中断发生, TIF被置位,
产生中断信号并送到NVIC通知CPU。从应用的角度看,中断的产生取决于TCMPR。在该模式下,定时
器计数是连续的,所以这种操作模式被称为连续计数模式.

使用特权

评论回复
10
玛尼玛尼哄|  楼主 | 2016-7-24 21:25 | 只看该作者

使用特权

评论回复
11
玛尼玛尼哄|  楼主 | 2016-7-24 21:27 | 只看该作者
定时器必须掌握好理论,然后结合逻辑图,配合寄存器表操作。

使用特权

评论回复
12
zhuotuzi| | 2016-7-24 22:33 | 只看该作者
   /* Configure Timer1 setting for external counter input function */
    TIMER_SELECT_TOUT_PIN(TIMER1, TIMER_TOUT_PIN_FROM_TX_PIN);
    TIMER_SET_PRESCALE_VALUE(TIMER1, 0);
    TIMER_SET_CMP_VALUE(TIMER1, 56789);
    TIMER_EnableEventCounter(TIMER1, TIMER_COUNTER_FALLING_EDGE);
    TIMER_EnableInt(TIMER1);

使用特权

评论回复
13
天灵灵地灵灵| | 2016-7-24 22:49 | 只看该作者
定时器的多种模式掌握好定义,使用起来就简单了。

使用特权

评论回复
14
capturesthe| | 2016-7-25 14:39 | 只看该作者
玛尼玛尼哄 发表于 2016-7-24 21:12
This sample code is showing how to use counter function on timer-1 counter input pin.

这个timer-1是什么意思啊

使用特权

评论回复
15
598330983| | 2016-7-25 22:00 | 只看该作者
4种工作模式:单脉冲模式(one-shot), 周期模式(periodic),开关模式(toggle)和连续计数(continuouscounting)模式操作模式

使用特权

评论回复
16
玛尼玛尼哄|  楼主 | 2016-7-30 17:28 | 只看该作者
/* Initial Timer1 default setting */
    TIMER_Open(TIMER1, TIMER_CONTINUOUS_MODE, 1);

    /* Configure Timer1 setting for external counter input function */
    TIMER_SELECT_TOUT_PIN(TIMER1, TIMER_TOUT_PIN_FROM_TX_PIN);
    TIMER_SET_PRESCALE_VALUE(TIMER1, 0);
    TIMER_SET_CMP_VALUE(TIMER1, 56789);
    TIMER_EnableEventCounter(TIMER1, TIMER_COUNTER_FALLING_EDGE);
    TIMER_EnableInt(TIMER1);

使用特权

评论回复
17
玛尼玛尼哄|  楼主 | 2016-7-30 17:29 | 只看该作者
在该工作模式下, 一旦定时器计数器的值达到定时器比较器寄存器(TCMPR) 的值,
定时器计数器的值返回计数初始值且CEN 保持为1 (持续使能计数).

使用特权

评论回复
18
heisexingqisi| | 2016-7-30 19:43 | 只看该作者
定时器是微控制器中最基本的接口之一,它的用途非常广泛,常用于计数、延时、提供定时脉
冲信号等。在实际应用中,对于转速、位移、速度、流量等物理量的测量,通常也是由传感器转换
成脉冲电信号,通过使用定时器来测量其周期或频率,再经过计算处理获得。
定时器控制器包含 4 组 32-位定时器,TIMER0~TIMER3,提供用户便捷的计数定时功能。
定时器可执行很多功能,如频率测量,时间延迟,时钟发生,外部输入管脚事件计数和外部捕捉管
脚脉宽测量等。

使用特权

评论回复
19
heisexingqisi| | 2016-7-30 19:44 | 只看该作者
特征
 4 组 32 位定时器,带 24 位向上计数器和一个 8 位的预分频计数器
 每个定时器都可以设置独立的时钟源
 提供 one-shot, periodic, toggle 和 continuous 四种计数操作模式
 通过 CNT (TIMERx_CNT[23:0])可读取内部 24 位向上计数器的值
 支持事件计数功能
 通过 CAPDAT (TIMERx_CAP[23:0])可读取 24-bit 捕捉值
 支持外部管脚捕捉功能,可用于脉宽测量
 支持外部引脚事件计数,可用于复位 24 位向上定时器
 如果定时器中断信号产生,支持芯片从空闲/掉电模式唤醒
 支持 Timer0 超时溢出中断来触发 Touch-Key 扫描
 支持 Timer0 ~ Timer3 超时溢出中断或捕捉中断来触发 PWM,EADC 和 DAC 功能

使用特权

评论回复
20
heisexingqisi| | 2016-7-30 19:48 | 只看该作者
使用定时器实现定时中断,实现 Led 每 250ms 进行闪烁
void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
位置:clk.c。
功能:使能当前硬件对应的时钟模块。
参数:
u32ModuleIdx:使能当前哪个时钟模块,若使能定时器 0,填入参数为 TMR0_MODULE;若使能串口 0,填入参数为
UART0_MODULE,更多的参数值参考 clk.c



uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq)
位置:timer.c。
功能:使能对应的定时器。
参数:
timer:哪一组定时器。
u32Mode:定时器工作模式。
u32Freq:定时器工作频率。
返回:当前定时器的工作频率.





static __INLINE void TIMER_Start(TIMER_T *timer)
位置:timer.h。
功能:启动对应的定时器。
参数:
timer:哪一组定时器



static __INLINE void TIMER_EnableInt(TIMER_T *timer)
位置:timer.h。
功能:使能对应的定时器产生中断。
参数:
timer:哪一组定时器。





使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

179

主题

3088

帖子

2

粉丝