分享

应广单片机-16位计数定时器

 共同成长888 2020-10-17

16位计数器的使用

PMS132B内置一个16位硬件计数器,我一般都是用来做定时器中断

下面这个是数据手册上面介绍的

只能向上计数
只能向上计数,计数初始值可以通过stt16指令来设置,待会看代码里面,用来做中断就是当计数溢出是触发中断,具体的看例程吧。

/************************************************************************************/
/*  16位计数定时器T16     */
/************************************************************************************/
#define USER_TIMER_CONFIG()$ T16M IHRC, /16, BIT10 //对t16寄存器进行配置   时钟:IHRC 分频:/16  中断源:BIT10   
#define ENABLE_TIMER()SET1 INTEN.2 //$ INTEN T16 //开定时器中断
#define DISENABLE_TIMER()SET0 INTEN.2 //关定时器中断
#define INIT_TIMER_VALUE(n)STT16 n//装载定时器计数值
#define EA_INT()ENGINT//开总中断
#define DIS_INT()DISGINT//关总中断
#define CONST_TIME_VALUE        0//0x10E//224//  (BIT - CONST_TIME_VALUE) / (IHRC / 分频) = us
word    T16val;
/************************************************************************************/
//一次中断的时间计算公式   (BIT - CONST_TIME_VALUE) / (IHRC / 分频) = us
//                         (2^10 - 0) / (16 / 4) = 1024us    
void Set_User_T16(void)
{
USER_TIMER_CONFIG();
T16val = CONST_TIME_VALUE;
INIT_TIMER_VALUE(T16val);
INTRQ = 0;//清除INTRQ
EA_INT();
ENABLE_TIMER();
}

voidFPPA0 (void)
{
.ADJUST_ICSYSCLK=IHRC/4, IHRC=16MHz//SYSCLK=IHRC/2
    // SetPortA();
    // SetPortB();
    Set_User_T16();


while (1)
{
//...
//wdreset;
        //主函数功能实现区

}
}


voidInterrupt (void)
{
pushaf;

if (Intrq.T16)
{//T16 Trig
//User can add code
Intrq.T16=0;
T16val = CONST_TIME_VALUE;
        INIT_TIMER_VALUE(T16val);
        //中断执行区
        
        
}

popaf;
}

有关其他的外部IO引脚中断目前正在研究中,没弄明白怎么回事,这个计数器中断时可以直接使用的,数据手册里面的计算公式跟我们实际测量出来的不一样,上面那个公式是我自己测量总结的,可行,大家也可以这样配置然后在中断里面通过IO口翻转看一下进一次中断的时间,下面那个是编译器里面使用手册对T16的计算方法。

在这里插入图片描述

有关16位计数器的就分享到这里,下次更新8位计数器和11位计数器的使用。

今天看到了官方的DEMO,16位定时器的中断时间还是跟我们实际测量到的不一样,先看一下官方给的DEMO 吧,`BIT p_Key_In : PA.0; // At ICE, has the circuit, you can try it.
BIT p_LED_Out : PA.1; //

void FPPA0 (void)
{
.ADJUST_OTP_IHRCR 4MIPS // IHRC/4 = 4MIPS, WatchDog Disable, RAM 0,1 temporary be used

$p_LED_OutOut, Low;
$p_Key_InIn;//, Pull;
PAPH=_FIELD(p_Key_In);

$ T16MIHRC, /1, BIT11;//16MHz / 1 = 16MHz : the time base of T16.   //这里是官方的对16位计数器寄存器的配置

BYTEKey_Flag;
BITf_Key_In:Key_Flag._BIT(p_Key_In);
Key_Flag=_FIELD(p_Key_In);

BYTESys_Flag=0;
BITf_Key_Trig:Sys_Flag.0;
BITf_LED_On:Sys_Flag.1;
BITt16_10ms:Sys_Flag.2;
BITt16_1s:Sys_Flag.3;
BITt16_over2:Sys_Flag.4;
BITt16_over3:Sys_Flag.5;

// pmode Program_Mode;
// fppen = 0xFF;

BYTEt16_flag;
BYTEcount1, count2, count3;
BYTEcnt_Key_10ms=4;//Key debounce time = 40 mS

while (1)
{
if  (INTRQ.T16)
{
INTRQ.T16=0;
If (--count1 == 0)//DZSN  count
{
count1=39;//256uS * 39 = 9,984 uS ≤ 10 mS 
t16_10ms=1;
}
}

//
WORD T16_Cnt, T_100mS;
ldt16 T16_Cnt;
if (T16_Cnt.15)
{
t16_over3 = 1;
}
else if (t16_over3)
{
t16_over3 = 0;
if (–count3 == 0)
{
count3 = 244; // 4,096uS * 244 = 999,424 uS ≤ 1S
t16_1s = 1;
}
}
//*
if (T16_Cnt.12)
{
t16_over2 = 1;
}
else if (t16_over2)
{
t16_over2 = 0;
if (–count2 == 0)
{
count2 = 195; // 512uS * 195 = 99,840 uS ≤ 100 mS
T_100mS++;
}
}
//
A = (t16_flag ^ T16_Cnt$1) & 0x20; // Another way for calucate 100 mS
if (! ZF) // it use t16_flag.5 ^ T15_Cnt.13
{ // the code is more little,
t16_flag ^= A; // but, not everyone like it.
if (–count2 == 0)
{
count2 = 195;
T_100mS++;
}
}
//
/

while (t16_10ms)
{
t16_10ms=0;

A=(PA ^ Key_Flag) & _FIELD(p_Key_In);//only check the bit of p_Key_In.
if (! ZF)
{//if is not same,
if (--cnt_Key_10ms == 0)
{//and over debounce time.
Key_flag^=_FIELD(p_Key_In);
f_Key_Trig=1;//so Trigger, when stable at 30 mS.
}
elsebreak;
}
cnt_Key_10ms=4;break;
}

if (f_Key_Trig)
{
f_Key_Trig=0;

if (! f_Key_In)
{
if (p_LED_Out)
{//3 )if next key in, then LED off
f_LED_On=0;
p_LED_Out=0;
}
else
{//1 )when first key press, then LED on
p_LED_Out=1;
}
}
else
{
if (p_LED_Out)
{//2 )when first key release, then start to count
f_LED_On=1;
T_100mS=0;
}
else
{//4 )nothing to do
}
}
}

if (f_LED_On)
{
if (T_100mS >= 50)
{//Over 5 S, then close
f_LED_On=0;
p_LED_Out=0;
}
}
}

}
`

官方这个DEMO直接在大循环里面判断的中断,实际建项目的时候,会出来一个单独的中断函数,下面看一下实际建项目的源代码,是我自己写的,然后用逻辑分析仪抓取出了波形。

#include"extern.h"

//.outfile %S_%T_%x.PDK

typedef byte u8; 
typedef word u16;
typedef EWORD u24;
typedef DWORD u32;

#define     SetPortA()      paph=0x18;pac=0x10;pa=0x00  
#define     SetPortB()      pbph=0x00;pbc=0x00

#define     LED_ON()        PA.4 = 1
#define     LED_OFF()       PA.4 = 0

u16 T16val;
u8 gCnt;

void sys_init(void)
{
    T16val = 0;
    gCnt = 0;
    
}

/************************************************************************************/
/*  16位计数定时器T16     */
/************************************************************************************/
#define USER_TIMER_CONFIG()$ T16M IHRC, /1, BIT11 //对t16寄存器进行配置   时钟:IHRC 分频:/16  中断源:BIT10   
#define ENABLE_TIMER()SET1 INTEN.2 //$ INTEN T16 //开定时器中断
#define DISENABLE_TIMER()SET0 INTEN.2 //关定时器中断
#define INIT_TIMER_VALUE(n)STT16 n//装载定时器计数值
#define EA_INT()ENGINT//开总中断
#define DIS_INT()DISGINT//关总中断
#define CONST_TIME_VALUE        0//0x10E//224//  (BIT - CONST_TIME_VALUE) / (IHRC / 分频) = us

/************************************************************************************/
//一次中断的时间计算公式   (BIT - CONST_TIME_VALUE) / (IHRC / 分频) = us
//                         (2^10 - 0) / (16 / 4) = 1024us    
void Set_User_T16(void)
{
USER_TIMER_CONFIG();
T16val = CONST_TIME_VALUE;
INIT_TIMER_VALUE(T16val);
INTRQ = 0;//清除INTRQ
EA_INT();
ENABLE_TIMER();
}

voidFPPA0 (void) //主函数
{
.ADJUST_ICSYSCLK=IHRC/4, IHRC=16MHz//SYSCLK=IHRC/2
    SetPortA();
    SetPortB();
    sys_init();
    Set_User_T16();


while (1)
{
//...
//wdreset;
        //主函数功能实现区

}
}


voidInterrupt (void) //中断函数
{
pushaf;

if (Intrq.T16)
{//T16 Trig
//User can add code
Intrq.T16=0;
T16val = CONST_TIME_VALUE;
        INIT_TIMER_VALUE(T16val);
        //中断执行区
        if (gCnt) {  // 利用IO口翻转看中断时间
            LED_OFF();
            gCnt = 0;
        } else {
            LED_ON();
            gCnt = 1;
        }
        
}

popaf;
}

16位计数器的中断源是BIT11,/1分频,时钟IHRC16M,跟官方例程里面的一样,下面是我测量出来的波形,翻转一次的时间是130us,根据我上面程序里面的公式(2^11-0)/(16/1) = 128us,测量出来多了一点点,是运行程序锁消耗的时间,为什么官方给出的数据跟实际测量的不一样我就不得而知了。

评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符“速评一下”

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多