关于定时器 相信很多人都不会陌生,无论是51还是32,任何微控制器,都会有定时器

定时器控制器包含 4 组 32-位定时器,TIMER0~TIMER3,提供用户便捷的计数定时功能。定时器可执行很多功能,如频率测量,时间延迟,时钟发生,外部输入管脚事件计数和外部捕捉管脚脉宽测量等。

特性
 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 功能

/******************************************************************************
* @file main.c
* @version V1.00
* $Revision: 4 $
* $Date: 15/09/02 10:03a $
* @brief NuEdu Basic01 Timer Sample Code
* @note
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "M451Series.h"
#include "NuEdu-Basic01.h" /*---------------------------------------------------------------------------------------------------------*/
/* TMR0 IRQ handler */
/*---------------------------------------------------------------------------------------------------------*/
uint32_t volatile TimerCounter = ;
void TMR0_IRQHandler(void)
{
TimerCounter == ? (TimerCounter = ) : (TimerCounter++);
// clear Timer0 interrupt flag
TIMER_ClearIntFlag(TIMER0);//清空中断标志
}
/*---------------------------------------------------------------------------------------------------------*/
/* MAIN function */
/*---------------------------------------------------------------------------------------------------------*/
int main(void)
{
//Initial System
SYS_Init(); //Enable Timer0 clock and select Timer0 clock source
CLK_EnableModuleClock(TMR0_MODULE);//使能模块
CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_HXT, );//选取时钟源,和进行分频 //Initial Timer0 to periodic mode with 2Hz
TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, );
//Enable Timer0 interrupt
TIMER_EnableInt(TIMER0);
NVIC_EnableIRQ(TMR0_IRQn); //Initial 7-Segment
Open_Seven_Segment(); //Start Timer0
TIMER_Start(TIMER0); while()
{
Show_Seven_Segment(TimerCounter / , );
CLK_SysTickDelay();
Show_Seven_Segment(TimerCounter % , );
CLK_SysTickDelay();
}
} /*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/
 TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 2);
定时器的模式有以下几种:
#define TIMER_ONESHOT_MODE                      (0UL << TIMER_CTL_OPMODE_Pos)      /*!< Timer working in one-shot mode */
#define TIMER_PERIODIC_MODE (1UL << TIMER_CTL_OPMODE_Pos) /*!< Timer working in periodic mode */
#define TIMER_TOGGLE_MODE (2UL << TIMER_CTL_OPMODE_Pos) /*!< Timer working in toggle-output mode */
#define TIMER_CONTINUOUS_MODE (3UL << TIMER_CTL_OPMODE_Pos) /*!< Timer working in continuous counting mode */
#define TIMER_TOUT_PIN_FROM_TX (0UL << TIMER_CTL_TGLPINSEL_Pos) /*!< Timer toggle-output pin is from Tx pin */
#define TIMER_TOUT_PIN_FROM_TX_EXT (1UL << TIMER_CTL_TGLPINSEL_Pos) /*!< Timer toggle-output pin is from Tx_EXT pin */
#define TIMER_CAPTURE_FREE_COUNTING_MODE (0UL << TIMER_EXTCTL_CAPFUNCS_Pos) /*!< Timer capture event to get timer counter value */
#define TIMER_CAPTURE_COUNTER_RESET_MODE (1UL << TIMER_EXTCTL_CAPFUNCS_Pos) /*!< Timer capture event to reset timer counter */
#define TIMER_CAPTURE_FALLING_EDGE (0UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< Falling edge detection to trigger timer capture */
#define TIMER_CAPTURE_RISING_EDGE (1UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< Rising edge detection to trigger timer capture */
#define TIMER_CAPTURE_FALLING_AND_RISING_EDGE (2UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< Both falling and rising edge detection to trigger timer capture */
#define TIMER_COUNTER_FALLING_EDGE (0UL << TIMER_EXTCTL_CNTPHASE_Pos) /*!< Counter increase on falling edge detection */
#define TIMER_COUNTER_RISING_EDGE (1UL << TIMER_EXTCTL_CNTPHASE_Pos) /*!< Counter increase on rising edge detection */

定时器计数模式
定时器控制器提供四种定时器计数模式: one-shot, periodic, toggle-output 和 continuous counting 计数模式

One–shot模式 
如果定时器工作在单周期 (one-shot) 模式(TIMERx_CTL[28:27]为00,且CNTEN (TIMERx_CTL[30])置1),则定时器的计数器开始计数。一旦CNT (TIMERx_CNT[23:0])计数器的值达到CMPDAT (TIMERx_CMP[23:0])的值时,TIF (TIMERx_INTSTS[0])标志将变为1,CNT的值和 CNTEN位将由定时器控制器自动清零,然后定时器计数操作停止。与此同时,如果INTEN (TIMERx_CTL[29])位使能,则定时器中断信号产生并送到 NVIC通知CPU。

Periodic模式

如果定时器工作在周期 (periodic) 模式(TIMERx_CTL[28:27]为01)且CNTEN (TIMERx_CTL[30])置1,则定时器的计数器开始向上计数。一旦CNT (TIMERx_CNT[23:0])计数器的值达到CMPDAT (TIMERx_CMP[23:0])的值时,TIF (TIMERx_INTSTS[0])标志将变为1,CNT的值将由定时器控制器自动清零,然后定时器重新计数。与此同时,如果INTEN (TIMERx_CTL[29])使能,则定时器中断信号产生并送到 NVIC 通知 CPU 。在该模式,定时器控制器周期性地操作计数和 与CMPDAT的值比较,直到CNTEN位由软件清0

Toggle-Output模式

如果定时器工作在触发输出 (toggle-out) 模式(TIMERx_CTL[28:27]为10)且CNTEN (TIMERx_CTL[30])位置1,则定时器的计数器开始计数。toggle-out 模式的计数操做大部分与周期模式是一样的,除了该模式当TIF (TIMERx_INTSTS[0])位设置时,有相关的T0 ~ T3管脚来输出信号,因此,管脚T0 ~ T3上的触发输出信号以 50% 的占空周期反复改变。

Continuous Counting模式

如果定时器工作在连续计数 (continuous counting) 模式(TIMERx_CTL[28:27]为11)且CNTEN (TIMERx_CTL[30])位置1,则定时器的计数器开始计数。一旦CNT (TIMERx_CNT[23:0])的值达到CMPDAT (TIMERx_CMP[23:0])的值时,TIF (TIMERx_INTSTS[0])标志将变为1,但CNT的值继续保持向上计数。与此同时,如果INTEN (TIMERx_CTL[29])使能,则定时器中断信号产生并送到 NVIC 通知 CPU 。在该模式,用户可以立刻改变不同的CMPDAT值,而不需要停止定时器计数和重新开始定时器计数。
例如,CMPDAT的值设置为 80。当CNT 达到 80时,TIF标志将被置1,定时器计数器继续计数,而且CNT的值将不回到0,而是继续计数,81, 82, 83,˙˙˙ 到 (224 -1),然后再一次 0, 1, 2, 3, ˙˙˙ 到 224 -1,如此往复。接下来,如果软件改变CMPDAT的值为200并且清除TIF标志位,当CNT的值达到200时,TIF标志将再次变为1,。最后,软件改变CMPDAT的值为500并且清除TIF标志,当CNT的值达到500时,TIF标志将再次变为1。
在该模式,计数器计数是连续的。所以该操作模式叫做连续计数模式。

事件计数模式
定时器控制器也提供这样的应用,能对输入事件(来自管脚Tx x=0~3)计数并将事件的次数反应到
CNT (TIMERx_CNT[23:0]) 的值。也可以称为事件计数功能。该功能下, EXTCNTEN
(TIMERx_CTL[24])位需置位并且定时器外设时钟源必须设为HCLKPCLKx (x= 0~1)。
软件可以通过CNTDBEN (TIMERx_EXTCTL[7])位来使能或关闭Tx管脚消抖电路。如果Tx管脚的消
抖电路关闭,输入事件频率必须少于1/3 PCLKxHCLK,如果消抖电路打开,输入事件的频率须小
于1/8 PCLKxHCLK , 以保证CNT 的值是正确的。软件也可以通过设置CNTPHASE
(TIMERx_EXTCTL[0])来选择边沿检测Tx管脚的相位。
事件计数模式下,定时器计数操作模式可以设置为单次,周期,和连续计数模式来计算来自Tx管脚
的输入事件CNT (TIMERx_CNT[23:0])的值。

外部捕捉模式
事件捕捉功能是当检测到Tx_EXT管脚(x=0~3)边沿电平有变化时,CNT (TIMERx_CNT[23:0])会送
到CAPDAT (TIMERx_CAP[23:0])。在该模式下,需把CAPFUNCS (TIMERx_EXTCTL[4])位设置为
0,用来选择Tx_EXT变化时用作事件捕捉功能,而且定时器外设时钟源必须设为PCLKx (x=
0~1)HCLK。
软件可以通过CAPDBEN (TIMERx_EXTCTL[6])位来使能或关闭Tx_EXT管脚消抖电路。在Tx_EXT
的消抖电路关闭时,Tx_EXT管脚的转变频率必须少于1/3 PCLKxHCLK,在Tx_EXT的消抖电路打
开时,Tx_EXT管脚的转变频率必须少于1/8 PCLKxHCLK,以保证捕捉功能能够正常工作。软件也
可以通过设置CAPEDGE (TIMERx_EXTCTL[2:1])位来选择Tx_EXT管脚的边沿转变检测方式。.
在事件捕捉模式,软件不用考虑定时器计数器工作模式的选择,只有当检测到Tx_EXT管脚有边沿
变化时捕捉事件才会发生。

如果CPU不清除CAPIF状态标志,用户应知道此时的定时器会保持TIMERx_CAP寄存器的值不变,
且不会保存新的捕捉值。

外部复位计数模式
当检测到Tx_EXT管脚(x=0~3)有边沿转变时,定时器同样提供事件复位计数器功能来复位CNT
(TIMERx_CNT[23:0]) 的值。在该模式, 大部分设置与事件捕捉功能相同, 除了CAPFUNCS
(TIMERx_EXTCTL[4])位必须设置为1来选择Tx_EXT转变时用作为事件复位计数器。

定时器触发功能 
定时器控制器提供定时器超时溢出中断或捕捉中断来触发PWM,DAC和EADC. 如果TRGSSEL (TIMERx_CTL[18])为0, 超时溢出中断信号用于触发PWM, EADC和DAC. 如果TRGSSEL (TIMERx_CTL[18]) 为 1, 捕捉中断信号用于触发PWM, EADC 和 DAC.
当TRGPWM (TIMERx_CTL[19])被置1, 如果定时中断信号产生, 定时器控制器将产生一个触发脉冲作为PWM外部时钟源。
当TRGDAC (TIMERx_CTL[20]) 被置1, 如果定时中断信号产生, 定时器控制器将触发DAC开始转换。
当TRGEADC (TIMERx_CTL[21]) 被置1, 如果定时中断信号产生, 定时器控制器将触发EADC开始转换。
Timer0定时器控制器也提供定时器超时中断来触发触摸按键(Touch-Key)的扫描,当WKTKEN (TIMER0_CTL[17])被置1且芯片在Power-down模式,如果Timer0超时中断信号产生, Timer0 控制器也会触发触摸按键(Touch-Key)的扫描. 在此功能模式下, timer0模块时钟源应设置为内部低速 内部低速 RC 振 荡器 (LIRC)的 10 kHz 时钟 或者外部低速晶体 外部低速晶体 外部低速晶体 (LXT) 的32.768 kHz时

这一段时间真的太安逸了,思维都懒惰了,想当初在大学时利用定时器就可以做个时钟出来,现在居然一心只为了完成任务,没有了原有的项目热情,以后一定要努力,绝不放过任何提升自己的机会。

最上面的程序是利用数码管来进行0到99的计数,我觉得着呢有必要讲一讲数码管的知识

数码管的一种是半导体发光器件,数码管可分为七段数码管和八段数码管,区别在于八段数码管比七段数码管多一个用于显示小数点的发光二极管单元DP(decimal point),其基本单元是发光二极管

直流驱动

是指每个数码管的每一个段码都由一个单片机的I/O端口进行驱动,或者使用如BCD码二-十进制译码器译码进行驱动。优点是编程简单,显示亮度高,缺点是占用I/O端口多。
 

动态显示驱动

是将所有数码管通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示。将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是那个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。
 

共阴极和共阳极的表示方法看下文:

1.共阴数码管0-F编码表:
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
2.共阳数码0-f管编码表:
uchar code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
 
在单片机中,我们通常去控制共阴端或共阳端去作为数码管的位选信号,同时给段显相应的数码值,做动态扫描以达到多数码管同时显示。
 
// 数码管扫描
void LedScan()
{
    static unsigned char i = 0;  // 动态扫描的索引
    
    P0 = 0xFF;   // 消隐
    switch (i)
    {
        case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;// 选中数码管0同时送要显示的数据
        case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;// 选中数码管1同时送要显示的数据
        case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
        case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
        case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
        case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5]; break;
        default: break;
    }
}
 
void InterruptTimer0() interrupt 1
{
TH0 = 0xFC;
TL0 = 0x67;
LedScan();
// 定时器中扫描数码管
KeyScan();
// 扫描按键
}
以上是51单片机的程序,但是表示方法都是一样的,

void Show_Seven_Segment(unsigned char no, unsigned char number)
{
SEG_A_OFF;
SEG_B_OFF;
SEG_C_OFF;
SEG_D_OFF;
SEG_E_OFF;
SEG_F_OFF;
SEG_G_OFF;
SEG_H_OFF;
SEG_CONTROL1_OFF;
SEG_CONTROL2_OFF;
switch(no)
{
//show 0
case 0:
SEG_A_ON;
SEG_B_ON;
SEG_C_ON;
SEG_D_ON;
SEG_E_ON;
SEG_F_ON;

break;

//show 1
case 1:
SEG_B_ON;
SEG_C_ON;
break;

//show 2
case 2:
SEG_A_ON;
SEG_B_ON;
SEG_G_ON;
SEG_E_ON;
SEG_D_ON;
break;

//show 3
case 3:
SEG_A_ON;
SEG_B_ON;
SEG_G_ON;
SEG_C_ON;
SEG_D_ON;
break;

//show 4
case 4:
SEG_F_ON;
SEG_B_ON;
SEG_G_ON;
SEG_C_ON;
break;

//show 5
case 5:
SEG_A_ON;
SEG_F_ON;
SEG_G_ON;
SEG_C_ON;
SEG_D_ON;
break;

//show 6
case 6:
SEG_A_ON;
SEG_F_ON;
SEG_E_ON;
SEG_G_ON;
SEG_C_ON;
SEG_D_ON;
break;

//show 7
case 7:
SEG_A_ON;
SEG_B_ON;
SEG_C_ON;
SEG_F_ON;
break;

//show 8
case 8:
SEG_A_ON;
SEG_B_ON;
SEG_C_ON;
SEG_D_ON;
SEG_E_ON;
SEG_F_ON;
SEG_G_ON;
break;

//show 9
case 9:
SEG_A_ON;
SEG_B_ON;
SEG_C_ON;
SEG_F_ON;
SEG_G_ON;
break;
}

switch(number)
{
case 1:
SEG_CONTROL1_ON;
break;

//show 1
case 2:
SEG_CONTROL2_ON;
break;
}
}

M451则是这么表示的,其实是一样的。
根据M451的定时器,我们可以计算出它的一些特点,

uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq)
{
uint32_t u32Clk = TIMER_GetModuleClock(timer);
uint32_t u32Cmpr = , u32Prescale = ; // Fastest possible timer working freq is (u32Clk / 2). While cmpr = 2, pre-scale = 0.
//最快可能的定时器工作频率是(u32Clk / 2)。 当cmpr = 2时,预标度= 0。
if(u32Freq > (u32Clk / ))
{
u32Cmpr = ;
}
else
{
if(u32Clk > )
{
u32Prescale = ; // real prescaler value is 8
u32Clk >>= ;
}
else if(u32Clk > )
{
u32Prescale = ; // real prescaler value is 4
u32Clk >>= ;
}
else if(u32Clk > )
{
u32Prescale = ; // real prescaler value is 2
u32Clk >>= ;
} u32Cmpr = u32Clk / u32Freq;
} timer->CTL = u32Mode | u32Prescale;
timer->CMP = u32Cmpr; return(u32Clk / (u32Cmpr * (u32Prescale + )));
}
uint32_t TIMER_GetModuleClock(TIMER_T *timer)
{
uint32_t u32Src;
const uint32_t au32Clk[] = {__HXT, __LXT, , , , __LIRC, , __HIRC}; if(timer == TIMER0)
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR0SEL_Msk) >> CLK_CLKSEL1_TMR0SEL_Pos;
else if(timer == TIMER1)
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1SEL_Msk) >> CLK_CLKSEL1_TMR1SEL_Pos;
else if(timer == TIMER2)
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR2SEL_Msk) >> CLK_CLKSEL1_TMR2SEL_Pos;
else // Timer 3
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR3SEL_Msk) >> CLK_CLKSEL1_TMR3SEL_Pos; if(u32Src == )
{
return (SystemCoreClock);
} return (au32Clk[u32Src]);
}
它是自动选取时钟源的。
不明白的话看一下寄存器是怎么写的,对照一下。
    printf("# Timer0 Settings:\n");
printf(" - Clock source is HXT \n");
printf(" - Time-out frequency is 1 Hz\n");
printf(" - Periodic mode \n");
printf(" - Interrupt enable \n");
printf("# Timer1 Settings:\n");
printf(" - Clock source is HCLK \n");
printf(" - Time-out frequency is 2 Hz\n");
printf(" - Periodic mode \n");
printf(" - Interrupt enable \n");
printf("# Timer2 Settings:\n");
printf(" - Clock source is HIRC \n");
printf(" - Time-out frequency is 4 Hz\n");
printf(" - Periodic mode \n");
printf(" - Interrupt enable \n");
printf("# Timer3 Settings:\n");
printf(" - Clock source is HXT \n");
printf(" - Time-out frequency is 8 Hz\n");
printf(" - Periodic mode \n");
printf(" - Interrupt enable \n");
printf("# Check Timer0 ~ Timer3 interrupt counts are reasonable or not.\n\n"); /* Open Timer0 in periodic mode, enable interrupt and 1 interrupt tick per second */
TIMER0->CMP = __HXT;
TIMER0->CTL = TIMER_CTL_INTEN_Msk | TIMER_PERIODIC_MODE;
TIMER_SET_PRESCALE_VALUE(TIMER0, ); /* Open Timer1 in periodic mode, enable interrupt and 2 interrupt ticks per second */
TIMER1->CMP = ((SystemCoreClock / ) / );
TIMER1->CTL = TIMER_CTL_INTEN_Msk | TIMER_PERIODIC_MODE;
TIMER_SET_PRESCALE_VALUE(TIMER1, ); /* Open Timer2 in periodic mode, enable interrupt and 4 interrupt ticks per second */
TIMER2->CMP = ((__HIRC / ) / );
TIMER2->CTL = TIMER_CTL_INTEN_Msk | TIMER_PERIODIC_MODE;
TIMER_SET_PRESCALE_VALUE(TIMER2, ); /* Open Timer3 in periodic mode, enable interrupt and 8 interrupt ticks per second */
TIMER3->CMP = ((__HXT / ) / );
TIMER3->CTL = TIMER_CTL_INTEN_Msk | TIMER_PERIODIC_MODE;
TIMER_SET_PRESCALE_VALUE(TIMER3, ); /* Enable Timer0 ~ Timer3 NVIC */
NVIC_EnableIRQ(TMR0_IRQn);
NVIC_EnableIRQ(TMR1_IRQn);
NVIC_EnableIRQ(TMR2_IRQn);
NVIC_EnableIRQ(TMR3_IRQn); /* Clear Timer0 ~ Timer3 interrupt counts to 0 */
g_au32TMRINTCount[] = g_au32TMRINTCount[] = g_au32TMRINTCount[] = g_au32TMRINTCount[] = ;
u32InitCount = g_au32TMRINTCount[]; /* Start Timer0 ~ Timer3 counting */
TIMER_Start(TIMER0);
TIMER_Start(TIMER1);
TIMER_Start(TIMER2);
TIMER_Start(TIMER3); /* Check Timer0 ~ Timer3 interrupt counts */
printf("# Timer interrupt counts :\n");

 

附一张时钟源的选择

/******************************************************************************
* @file main.c
* @version V1.00
* $Revision: 4 $
* $Date: 15/09/02 10:03a $
* @brief NuEdu Basic01 Timer Sample Code
* @note
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "M451Series.h"
#include "NuEdu-Basic01.h" /*---------------------------------------------------------------------------------------------------------*/
/* TMR0 IRQ handler */
/*---------------------------------------------------------------------------------------------------------*/ uint32_t volatile TimerCounter = ;
void GPD_IRQHandler(void)
{ /* To check if PC.5 interrupt occurred */
if(GPIO_GET_INT_FLAG(PD, BIT3))
{
Write_Buzzer(,,);
} // else
// {
// /* Un-expected interrupt. Just clear all PC interrupts */
// PC->INTSRC = PC->INTSRC;
// printf("Un-expected interrupts.\n");
// }
}
void TMR0_IRQHandler(void)
{
TimerCounter == ? (TimerCounter = ) : (TimerCounter++);
// clear Timer0 interrupt flag
if(Get_Key_Input()&0x01)
{
TimerCounter++;
Show_Seven_Segment(TimerCounter / , );
//CLK_SysTickDelay(200);
Show_Seven_Segment(TimerCounter % , );
//CLK_SysTickDelay(200);
}
if(Get_Key_Input()&0x02)
{
TimerCounter--;
Show_Seven_Segment(TimerCounter / , );
//CLK_SysTickDelay(200);
Show_Seven_Segment(TimerCounter % , );
//CLK_SysTickDelay(200);
}
TIMER_ClearIntFlag(TIMER0);
}
/*---------------------------------------------------------------------------------------------------------*/
/* MAIN function */
/*---------------------------------------------------------------------------------------------------------*/
int main(void)
{
int i=;
//Initial System
SYS_Init();
/* Configure PD.3 as Quasi-bidirection mode and enable interrupt by falling edge trigger */
PD->MODE = (PD->MODE & (~GPIO_MODE_MODE3_Msk)) | (GPIO_MODE_QUASI << GPIO_MODE_MODE3_Pos);
//Enable Timer0 clock and select Timer0 clock source
CLK_EnableModuleClock(TMR0_MODULE);
CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_HXT, );
PD->INTTYPE |= (GPIO_INTTYPE_LEVEL << GPIO_INTTYPE_TYPE3_Pos);
PD->INTEN |= GPIO_INTEN_FLIEN3_Msk;
NVIC_EnableIRQ(GPD_IRQn); //Initial Timer0 to periodic mode with 2Hz
TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, );
//Enable Timer0 interrupt
TIMER_EnableInt(TIMER0);
NVIC_EnableIRQ(TMR0_IRQn);
Open_Buzzer();
//Initial 7-Segment
Open_Seven_Segment();
Initial_Key_Input();
//Start Timer0
TIMER_Start(TIMER0); while()
{ /* Configure PC.5 as Quasi-bidirection mode and enable interrupt by falling edge trigger */ if(Get_Key_Input()&0x04)
{
Write_Buzzer(, ,i++);
}
if(Get_Key_Input()&0x08)
{
Write_Buzzer(, ,i--);
} Show_Seven_Segment(TimerCounter / , );
CLK_SysTickDelay();
Show_Seven_Segment(TimerCounter % , );
CLK_SysTickDelay(); if(TimerCounter==)
{
Write_Buzzer(, ,);
} }
} /*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/

这部分需要我认真调试,观察,有一些不对的地方

说说M451例程讲解之定时器的更多相关文章

  1. M451例程讲解之GPIO.H

    到了CORTEX-M4,几乎每一快都有很大的知识量,单单GPIO库文件这一项就有很长的章节要描述,加油吧 GPIO.h.是最基础的一个库文件,下面结合数据手册来一一进行讲解: 先把库文件粘上,方便一一 ...

  2. M451例程讲解之按键

    /**************************************************************************//** * @file main.c * @ve ...

  3. 说说M451例程讲解之LED

    /**************************************************************************//** * @file main.c * @ve ...

  4. 说说M451例程讲解之串口

    /**************************************************************************//** * @file main.c * @ve ...

  5. CH58X/CH57X/V208的Broadcaster(广播者)例程讲解

    在对ble进行应用的时候,每个用户的需求可能不尽相同.这里着重介绍从机Broadcaster例程,只广播不连接. 使用该例程时可以在手机使用APP上对Broadcaster进行调试. 安卓端在应用市场 ...

  6. 【iCore4 双核心板_ARM】例程八:定时器PWM实验——呼吸灯

    实验原理: STM32的定时器有PWM功能,iCore4的蓝色LED连接在定时器的输出接口上, 可以通过定时器的PWM输出控制LED的亮度,从而实验呼吸灯的功能. 核心代码: int main(voi ...

  7. 【GMT43智能液晶模块】例程七:定时器PWM实验——简易电子琴

    实验原理: STM32定时器有PWM功能,GMT43模块上带有一无源蜂鸣器,其 PWM输入控制信号接在STM32定时器输出接口上(PB4/TIM3_CH1),可 以通过定时器的PWM输出频率从而控制蜂 ...

  8. 【iCore3 双核心板】例程八:定时器PWM实验——呼吸灯

    实验指导书及代码包下载: http://pan.baidu.com/s/1dEnH5dB iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...

  9. CH58X/CH57X/V208 Observer(观察者)例程讨论讲解

    使用的是沁恒的CH582M的Observer例程与官方的demo板. 本例程的功能是主机扫描到从机的MAC地址并打印出来. 先对宏定义进行理解讨论. 最大响应扫描数为8,在串口调试助手那里可以看到打印 ...

随机推荐

  1. WEP无线网络密码破解

    一,五分钟实现无线WEP入侵的特点: 众所周知WEP加密入侵需要用户通过监听等方法接收到足够数量的WEP验证数据包,然后通过分析软件使用暴力破解的方法穷举法还原出WEP加密密钥的明文信息.五分钟实现无 ...

  2. Android_08手机联系人编码中SimpleAdapter的使用说明

    1. SimpleAdapter  adapter = new SimpleAdapter(this, list1,R.layout.my_layout, new String[] { "n ...

  3. 解决Enter键与input 、a标签触发的事件的冲突

    无论是 <button type="button" onclick="console.log('123');">123</button> ...

  4. mysql numberic types ---- mysql 数值类型详解

    编程语言中大多都有数据类型一说.虽然mysql 的sql 语句与标准sql 有别.但是宏观上看还是差不多的:下面我们说一下mysql数据库中的数值类型 一.在mysql里有那些类型可以表示数值: 1. ...

  5. Informix 語法

    1.修改表名稱 RENAME TABLE old_table_name TO new_table_name; 2.分頁 select  SKIP 0 FIRST 1 * from tablename ...

  6. HDU 1016:Prime Ring Problem

    Prime Ring Problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  7. C语言的存储类型和关键字extern、static

    1.C语言中每个变量都有3个性质:存储期限.作用域.链接 1)存储期限:变量的存储期限决定了为变量预留的内存被释放的时间.共2种,自动存储期限(auto),静态存储期限(static),自动存储(au ...

  8. Linux 内存中的Cache,真的能被回收么?

    您真的了解Linux的free命令么? 在Linux系统中,我们经常用free命令来查看系统内存的使用状态.在一个RHEL6的系统上,free命令的显示内容大概是这样一个状态: 这里的默认显示单位是k ...

  9. 基于Redis实现延时队列服务

    背景 在业务发展过程中,会出现一些需要延时处理的场景,比如: a.订单下单之后超过30分钟用户未支付,需要取消订单 b.订单一些评论,如果48h用户未对商家评论,系统会自动产生一条默认评论 c.点我达 ...

  10. spring配置:context:property-placeholder 读取配置文件信息 在配置文件中使用el表达式填充值

    spring将properties文件读取后在配置文件中直接将对象的配置信息填充到bean中的变量里. 原本使用PropertyPlaceholderConfigurer类进行文件信息配置.Prope ...