蓝桥杯51单片机的PCA使用(作为定时器)

        因为51单片机中的定时器数量较少,多个外设同时使用时可能会出现定时器不够用的情况,此时可以使用单片机中的PCA模块作为定时器来使用。

        STC15单片机中有3路可编程计数器阵列,PCA(Programmable Counter Array)是其中之一。它具有多个定时器/计数器和捕获/比较单元。PCA模块可以用于实现定时器、计数器、PWM(脉宽调制)和捕获等功能。本篇介绍PCA用作定时器的简单写法:

一:看数据手册来编程:

        通过数据手册可以看到PCA其实是和定时器的使用方式大同小异,也是需要打开中断,声明中断函数等等。可以看到它的中断号是7。

8ca52c93b0c447ffafd8697f360f9f7f.png

cb5cee16d09a489e858234ef7c85f20a.png

        既然和定时器使用方式差不多,那就是需要初始化pca,写好中断函数就可以了。

二:PCA初始化函数

        1.定时器初始化要配置TMOD,那PCA也需要配置它的模式寄存器CMOD。

        一般的使用将CIDL配置为0应该就可以,B4-B6应该是无效位,也将其配置为0就行,B1-B3是选择时钟源输入的模式,也就是选择是否将系统时钟进行分频后作为PCA的时钟源。 

      系统时钟频率通常指的是内部IRC(Internal RC)时钟的频率。内部IRC时钟是单片机内部集成的一个振荡器,它提供了单片机运行所需的时钟信号。 STC15F2K60S2单片机的内部IRC时钟频率为11.0592MHz。这是单片机默认的系统时钟源,可以通过STC-ISP烧录软件初始为12MHZ。可以通过配置寄存器来选择内部IRC时钟作为系统时钟源。

       所以当IRC时钟频率调为12MHZ,将PCA定时器的时钟源设置为 系统时钟/12 时,系统时钟频率为12MHz,则PCA定时器的时钟源频率为12MHz / 12 = 1MHz。所以B3B2B1=000。

        最后B0的ECF是PCA计数溢出中断使能位,置1代表允许CCON中的CF位的中断(我的理解是CF是个中断标志,通过CF的状态来决定是否进入中断,所以允许CF位的中断才能在计数溢出时进入中断函数)。所以CMOD我们配置好了,CMOD |= 0x01;

|= 的作用是把要置1的置1,不改变其它位。&= 是把要清零的位清零,不改变其它位。作用刚好相反,或置1 与清零。

021226aa68bd430fb6e1185588c8cf90.png         

        2.定时器初始化要配置TCON,PCA也需要配置它的控制寄存器CCON。

          前面配置CMOD时说过CF是计数溢出标志位,即在ECF=1允许CF中断时,若PCA计数溢出则CF被置1,进入中断函数。注意:进入中断后要手动将CF清零,否则就不能进入下一次中断(我尝试过不行)。CR置零,CR就是类似于定时器中的TR位,用来打开或关闭计数器。其余三位CCF也清零即可。所以CCON=0x00;

 ddf8387e5cea406dae95f2393dd46c35.png

         3.定时器中的装载值的TH和TL对应于PCA中的CH(8位)和CL(8位)。

        假设系统时钟频率为f_sys,并且将PCA定时器的时钟源设置为f_sys/12。每个PCA时钟周期的时间可以计算为1 / (f_sys / 12) 秒。因此,CH和CL加起来的最大计时值为 65535 * (1 / (f_sys / 12)) 秒。前面配置CMOD时我们将系统频率配置为了12MHZ,选择了 系统频率/12 作为PCA的时钟源,代入公式计算得到每个PCA时钟周期的时间是1us,CH加上CL是16位二进制,所以最大可计到65535us产生一次溢出。可以通过对CH和CL赋不同的初始值来得到间隔多久产生一次中断。

        4.打开总中断EA=1,打开PCA计数器CR=1

        这个和定时器初始化是一样的操作。

到这里pca初始化函数就写完了。

void pca_init()
{
	CMOD|=0x01;//PCA计数脉冲选择系统时钟/12作为时钟源
	CCON=0x00;//将溢出位cf(溢出标志位)置零cr(启停位)置零停止计数
	CH=0xd8; //8位
	CL=0xef; //8位
	EA=1;  //打开总中断
	CR=1;  //打开PCA计数器
}

二:中断函数

        这个和定时器的不可重装模式是一样的,需要在中断函数里手动重装CH和CL值,并且需要把CF清零。中断号为7。

void pca_interrupt() interrupt 7
{
	CF=0;  //计数器溢出后被置1,需要软件清零 才能进入下一次中断
	CH=0xd8; //8位
	CL=0xef; //8位
}

三:例程

        以蓝桥杯STC15F2K60S2单片机为例,使用PCA作为定时器实现LED以1秒间隔闪烁。

#include <stc15f2k60s2.h>

#define PWM_PERIOD 100  //CHCL为0xd8ef,换算为十进制是55535,所以每次溢出是10000us,当溢出100次时刚好是1秒

void Device(unsigned char p2dat,unsigned char p0dat)
{
	P0 = p0dat;
	P2 = (P2&0x1f)|p2dat;
	P2 = P2&0x1f;
}

void pca_init()
{
	CMOD|=0x01;//PCA技术脉冲选择为系统时钟不分频(B3为1),ECF位=1,允许寄存器CCON中CF位的中断 所以CMOD=0x09
	CCON=0x00;//将溢出位cf(溢出标志位)置零cr(启停位)置零停止计数
	CH=0xd8; //8位
	CL=0xef; //8位
	EA=1;  //打开总中断
	CR=1;  //打开PCA计数器
}

unsigned char i;
void pca_interrupt() interrupt 7
{
    static unsigned int pwm_count = 0;
	CF=0;  //计数器溢出后被置1,需要软件清零 才能进入下一次中断
	CH=0xd8; //8位
	CL=0xef; //8位
    pwm_count++;
    if (pwm_count >= PWM_PERIOD)
    {
        pwm_count = 0;
		if(i==0)Device(0x80,0x00);
		else 	Device(0x80,0xff);
		i = (i+1)%2;	
    }
}

void main() {
    pca_init();
	Device(0x80,0xff);//初始化关闭LED
    while (1) {
        // 主循环中可以进行其他操作
    }
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值