PCA16位定时器

Posted ReCclay

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PCA16位定时器相关的知识,希望对你有一定的参考价值。

#include "STC15W4K.H"   // 包含STC15W4K寄存器定义文件
sbit LED=P0^0;
void main (void)

//步长计算方法:T*(SYSclk/12)
//0.005*(22118400/12) = 2400H
    CCAP0L=0;        // 给PCA模块0的CCAP0L置初值
    CCAP0H=0x24;     // 给PCA模块0的CCAP0H 置初值
    CCAPM0=0x49;     // 设置PCA模块0为16位定时器
    EA=1;            // 开总中断 
    CR=1;            // 启动定时器
    while(1);            // 等待中断

void PCA(void) interrupt 7       // 每5ms进入一次PCA中断 
   
    unsigned int temp;  
    temp=(CCAP0H<<8)+CCAP0L+0x2400; // 运算符“+”的优先级大于“<<”
    //注意此处有类型提升
    CCAP0L=temp;        // 取计算结果的低8位
    CCAP0H=temp>>8;     // 取计算结果的高8位
    CCF0=0;             // 清 PCA 模块0 中断标志
    LED =!LED;          // 在P0.0输出脉冲宽度为5ms的方波


#include "STC15W4K.H"   // 包含STC15W4K寄存器定义文件
sbit LED_1s=P0^0;
unsigned char Count;     // 中断次数变量
void port_mode()        // 端口模式

    P0M1=0x00; P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00;
    P4M1=0x00; P4M0=0x00;P5M1=0x00; P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00; 

void main (void)

    port_mode();         // 所有IO口设为准双向弱上拉方式。
    Count=200;           // 设置Count计数器初值
    CMOD=0x80;           // #10000000B   空闲模式下停止PCA计数器工作
                         // 选择PCA时钟源为Fosc/12,禁止PCA计数器溢出时中断
    CCON=0;              // 清零PCA计数器溢出中断请求标志位CF
    // CR = 0, 不允许 PCA 计数器计数,清零PCA 各模块中断请求标志位CCFn
    CL=0;                // 清零PCA 计数器 
    CH=0;
    CCAP0L=0;            // 给PCA模块0的CCAP0L置初值
    CCAP0H=0x24;         // 给PCA模块0的CCAP0H 置初值
    CCAPM0=0x49;         // 设置PCA模块0为16位定时器,ECCF0=1允许PCA模块0中断
    // 当[CH,CL]=[CCAP0H,CCAP0L]时,CCF0=1,产生中断请求
    EA=1;                // 开整个单片机所有中断共享的总中断控制位
    CR=1;                // 启动PCA计数器(CH,CL)计数
    while(1);            // 等待中断

void PCA(void) interrupt 7 //PCA中断服务程序

    // 每5ms中断一次
    union                   //定义一个联合,以进行16位加法
           
        unsigned int num;
        struct              // 在联合中定义一个结构
                    
            unsigned char Hi,Lo;
        Result;
    temp;  
    temp.num=(unsigned int)(CCAP0H<<8)+CCAP0L+0x2400;
    CCAP0L=temp.Result.Lo;     // 取计算结果的低8位
    CCAP0H=temp.Result.Hi;     // 取计算结果的高8位
    CCF0=0;                    // 清 PCA 模块0 中断标志
    Count--;                   // 修改中断计数
    if (Count==0)
    
        Count=200;             // 恢复中断计数初值
        LED_1s =!LED_1s;       // 在P0.0输出脉冲宽度为1秒钟的方波(0.5Hz)
    

共用体嵌套在结构体内简直6的一批。
原理呢?

这么来看的话,其实也就很好理解了,num是int类型的,也就决定了这个共用体占有两个字节的内存,恰好它和一个结构体的两个char成员共用这块内存,那第一个就可以表示高字节。第二个就可以表示低字节。

但是

多字节变量的字节序取决于单片机架构和编译器,并非是固定的。所以使用这种嵌套的方法的话,一定要清楚字节。

下面利用定时器T0作脉冲源

#include "STC15W4K.H"   // 包含STC15W4K寄存器定义文件
sbit LED_1s=P0^0;
unsigned char Count=200;        // 中断次数变量
void port_mode()        // 端口模式

    P0M1=0x00; P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00;
    P4M1=0x00; P4M0=0x00;P5M1=0x00; P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00; 

void main (void)

    port_mode();      // 所有IO口设为准双向弱上拉方式。
    // 初始化定时器T0为8位自动重装方式
    TMOD=0x02;     // 设置T0为8位自动重装方式
    TH0=246;       // 来256-246=10个脉冲就中断
    TL0=246;       // 来256-246=10个脉冲就中断
    TR0=1;         // 启动定时器0 
    // 初始化PCA模块0为16位定时器方式
    CMOD=0x84;     // #10000100B   空闲模式下停止PCA计数器工作
                   // 选择PCA时钟源为T0溢出信号,禁止PCA计数器溢出时中断
    CCON=0;        // 清零PCA计数器溢出中断请求标志位CF
                   // CR = 0, 不允许 PCA 计数器计数,清零PCA 各模块中断请求标志位CCFn
    CL=0;          // 清零PCA 计数器 
    CH=0; 
    CCAP0L=0x99;   // 给PCA模块0的CCAP0L置初值
    CCAP0H=0x03;   // 给PCA模块0的CCAP0H 置初值
    CCAPM0=0x49;   // 设置PCA模块0为16位定时器,ECCF0=1允许PCA模块0中断
                   // 当[CH,CL]=[CCAP0H,CCAP0L]时,CCF0=1,产生中断请求
    EA=1;          // 开整个单片机所有中断共享的总中断控制位
    CR=1;          // 启动PCA计数器(CH,CL)计数
//  INT_CLKO =INT_CLKO|0x01;  //允许T0/P3.5时钟输出,调试观察TO是否正常
    while(1);            // 等待中断

void PCA(void) interrupt 7 //PCA中断服务程序

    // 每5ms中断一次
    union                   //定义一个联合,以进行16位加法
           
            unsigned int num;
            struct              // 在联合中定义一个结构
                        
                unsigned char Hi,Lo;
            Result;
    temp;  
    temp.num=(unsigned int)(CCAP0H<<8)+CCAP0L+0x399;
    CCAP0L=temp.Result.Lo;     // 取计算结果的低8位
    CCAP0H=temp.Result.Hi;     // 取计算结果的高8位
    CCF0=0;                    // 清 PCA 模块0 中断标志
    Count--;                   // 修改中断计数
    if (Count==0)
    
        Count=200;             // 恢复中断计数初值
        LED_1s =!LED_1s;       // 在P0.0输出脉冲宽度为1秒钟的方波(0.5Hz)
    

理解这个程序务必先理解好,所谓的配置寄存器达到定时器的原理:

PCA的计数器每隔时钟源分之1就加1,直到和比较寄存器的值(CCAPnH和CCAPnL相同)就产生PCA中断,在中断中再对比较寄存器加相同的步值,以此做定时器的功能。

要定时5ms,使用八位自动重装载模式,10个脉冲就溢出,计数一个脉冲对应的时间为12/SYSclk,是个脉冲对应时间为120/SYSclk,那么对应的脉冲频率就是SYSclk/120,也就是120分频了。
实际计算一下,22118400/120*0.05 = 921.6=0x0399

以上是关于PCA16位定时器的主要内容,如果未能解决你的问题,请参考以下文章

CMT2380F32模块开发9-可编程计数阵列 PCA例程

CMT2380F32模块开发9-可编程计数阵列 PCA例程

51单片机定时器初值计算以及初值计算软件

STC15系列CCP/PWM/PCA介绍

11.STC15W408AS单片机CCP/PCA/PWM应用

11.STC15W408AS单片机CCP/PCA/PWM应用