STC12系列单片机PCA模块应用

发布者:chaxue1987最新更新时间:2019-01-26 来源: eefocus关键字:STC12系列  单片机  PCA模块 手机看文章 扫描二维码
随时随地手机看文章

 STC12C5系列单片机属于增强性单片机,有多强呢?带有SPI接口,PCA模块,定时器输出,16K+的片上ROM,越来越妖孽了!前面见识了定时器输出功能,现在来领教一下STC12C5A60S单片机的PCA捕捉比较模块,后面有心情再看看SPI模块。


按我个人理解捕捉比较的意思应该是捕捉外部引脚上的跳变,与预设的值比较,然后做相应的动作。下文按这个理解展开。老规矩,寄存器功能介绍省略了,懒得抄手册了。


虽然说寄存器设置的说明不介绍,不过表格还是得给一张,这样条理比较清晰,如下:



1)PCA模块PWM的应用,感觉设置寄存器最少的一个:


PWM(脉宽调制,改变输出方波的占空比)估计拥有最广泛的应用空间(恕我眼见浅),据说常有人用PWM做心跳灯向妹子表白,不知道有没有成功;还有改变直流电机的输出转速。。。 


怎么理解PWM这个功能呢?刚去了趟WC突然想到了:在一个有0xFF个刻度的跑表上,CH是秒表,CCAPnH是表面上的一个绊脚石,当CH遇到绊脚石,直接给跪了,一直跪到下一轮0x00,继续站起来行走。如果CCAPnH没被移动,CH还在同一个地方周而复始的摔倒(人说不要再同一个地方摔倒)。然后计算从0x00-0xFF这段时间里,CH站着走路占了这段时间的百分之几,给跪占了剩下的多少(路遇倒地不扶也就算了还做应用题)!


#include

 

enum sState

{

    sInit=0,sPca,sClk,sPwm,sClkOut,

};

 

#define CCF1_INT 0x02

#define CCF0_INT 0x01

 

#define ResetPCA() \

do{ \

    CCON = 0; \

    CL = 0; \

    CH = 0; \

    CMOD = 0x00; \

    CCAPM0 = 0x00; \

    CCAPM1 = 0x00; \

}while(0); \

#define StartPCA() \

do{ \

    CR = 1; \

}while(0); \

#define StopPCA() \

do{ \

    CR = 0; \

}while(0); \

#define SetModnCmp(n) \

do{ \ 

    CCAPM##n |= PCA0_ECOM; \

    CCAPM##n |= PCA0_MAT; \    

}while(0); \

 

#define SetModnTog(n) \

do{ \

    CCAPM##n |= PCA0_TOG; \

}while(0); \

#define SetCapnMod(n,mod) \

do{ \

    CCAPM##n |= mod; \

}while(0); \

#define SetCCAPn(n,hi,lo) \

do{ \

    CCAP##n##H = hi; \

    CCAP##n##L = lo; \    

}while(0); \

//ECCFn 使能CCFn中断。使能寄存器CCON的比较/捕获标志CCFn,用来产生中断。

#define EnPcaModnInt(n) \

do{ \

    CCAPM##n |= PCA0_ECCF; \    

}while(0); \

 

//PCA0_ECOM 允许比较器功能控制位

//PCA0_PWM 脉宽调制模式。当PWMn=1时,CEXn脚用作脉宽调制输出

#define SetPwmMod(n) \

do{ \

    CCAPM##n |= PCA0_ECOM|PCA0_PWM; \    

}while(0); \

 

unsigned int CCAPnHVal = 0x80,CCAPnLVal = 0x80; 

 

void delay()

{

    int i=0,j=0;

    for(i=0;i<1000;i++)

    {

        for(j=0;j<110;j++);

    }

}

 

int main()

{

    unsigned char sState = sInit;

    ResetPCA();

    //pwm有比较功能 但没用到匹配...真特立独行

    //只要设置CCAPMn的PWM位和比较位

    SetPwmMod(0);

    

    //设置占空比,有点类似定时器Mod2,TH自动装载到TL

    //此处是CCAPnH自动装载到CCAPnL(8位);CH装载到CL(8位)

    //CH-CL低于    CCAPnH-CCAPnL输出0,其他输出1

    while(1)

    {

        StopPCA();

        SetCCAPn(0,CCAPnHVal,CCAPnLVal);

        if(CCAPnHVal == 0xF0)

            CCAPnLVal = CCAPnHVal = 0x00;

        else

            CCAPnLVal = CCAPnHVal = CCAPnLVal+0x10;

        //启动pca模块

        StartPCA();

        delay();

    }

}

PWM0的输出引脚是P1.3在我的开发板上正好连了一个红色LED,忽明忽亮的,眼都刺瞎了!用示波器测试时的确输出可变的波形。(无图无真相随我BB)


本来想用中断控制pwm占空比,不过没成功,没法调试好麻烦,只能用这种粗线条的延时了。


2) 在看PCA捕捉功能之前,先看下51MCU的计数器功能,PCA的捕捉功能应该是加强版计数器:


2a) 51的定时器对系统时钟计数,计满诺干个时钟脉冲后,产生溢出;计数器对外部输入信号计数,计满诺干负跳变后,产生溢出。传说,计算流水线上的工件数会用到计数器功能。想象一下点钞机里的票票经过光感时,使计数器不断的加一,想想是不是有点小激动?醒醒了,拿钱不是自己的。还是看下面的代码了


#include

 

#define MakeByte(target, Hi,Lo) \  

do{ \  

    target |= (((Hi)<<4)|(Lo)); \   

}while(0); \  

  

#define SetTH(n,val) \  

do{ \  

    TH##n = val; \  

}while(0); \  

  

#define SetTL(n,val)  \  

do{ \  

    TL##n = val; \  

}while(0); \  

  

#define EnableET(n) \  

do{ \  

    ET##n = 0x01; \  

    IE |= 0x80; \  

}while(0); \

 

#define StartClk(val) \

do{ \

TCON |= val; \

}while(0); \

sbit P10=P1^0;

 

int main()

{

//T0工作在方式2 计数器模式

MakeByte(TMOD,0x00,0x06);

SetTH(0,0xFF);

SetTL(0,0xFF);


EnableET(0);

//启动定时器

StartClk(0x10);

while(1);

}  

 

void IsrT0() interrupt 1 

{

    //TH自动装入0xFF,再计满一个负跳变又能进入isr

    P10 = ~P10;

}

程序对P3.4引脚采样,遇到负跳变计数器加1,因为设置计数溢出是0xFF,因此只要有负跳变就产生中断,对P1.0引脚取反。因为文章是关于PCA的,所以不能安排MCU计数器模块抢了镜头~



蓝色波形是信号发生器的输出,黄色波形是P1.0的输出。因为2个负跳变产生一个完整的波形,因此P1.0方波周期正好对应2个信号发生器的周期。


2b) 回到文章的主角PCA模块,当PCA模块工作在捕获模式时,对外部输入CEXn(P13/P14)的跳变进行采样。当采样到有效跳变时,PCA硬件将PCA计数器阵列寄存器(CH和CL)的值装载到捕获寄存器(CCAPnH和CCAPnL)中。如果CCON中的CCFn位和CCAPMn中的ECCFn位被置位,将产生中断。


#include

 

enum sState

{

sInit=0,sPca,sClk,sPwm,sClkOut,

};

 

#define CCF1_INT 0x02

#define CCF0_INT 0x01

 

#define ResetPCA() \

do{ \

CCON = 0; \

CL = 0; \

CH = 0; \

CMOD = 0x00; \

CCAPM0 = 0x00; \

CCAPM1 = 0x00; \

}while(0); \

#define StartPCA() \

do{ \

CR = 1; \

}while(0); \

#define StopPCA() \

do{ \

CR = 0; \

}while(0); \

#define SetModnCmp(n) \

do{ \ 

CCAPM##n |= PCA0_ECOM; \

CCAPM##n |= PCA0_MAT; \

}while(0); \

 

#define SetModnTog(n) \

do{ \

CCAPM##n |= PCA0_TOG; \

}while(0); \

#define SetCapnMod(n,mod) \

do{ \

CCAPM##n |= mod; \

}while(0); \

#define SetCCAPn(n,hi,lo) \

do{ \

CCAP##n##H = hi; \

CCAP##n##L = lo; \

}while(0); \

//ECCFn 使能CCFn中断。使能寄存器CCON的比较/捕获标志CCFn,用来产生中断。

#define EnPcaModnInt(n) \

do{ \

CCAPM##n |= PCA0_ECCF; \

}while(0); \

 

//PCA0_ECOM 允许比较器功能控制位

//PCA0_PWM 脉宽调制模式。当PWMn=1时,CEXn脚用作脉宽调制输出

#define SetPwmMod(n) \

do{ \

CCAPM##n |= PCA0_ECOM|PCA0_PWM; \

}while(0); \

 

//当PCA模块工作在捕获模式时,对外部输入CEXn的跳变进行采样。

//当采样到有效跳变时,PCA硬件将PCA计数器阵列寄存器(CH和CL)的值装载到捕获寄存器(CCAPnH和CCAPnL)中。

//如果CCON中的CCFn位和CCAPMn中的ECCFn位被置位,将产生中断。

//当P1.3出现下降沿时产生中断 对P1.5取反

 

void delay()

{

    int i=0,j=0;

    for(i=0;i<200;i++)

    {

        for(j=0;j<110;j++);

    }

}

 

int main()

{

unsigned char sState = sInit;

ResetPCA();

EA = 1;

//捕捉模式,捕捉到跳变沿时触发中断

//CH-CL不用与CCAPnH-CCAPnL比较,因此不用使能ECOMn

//也不需要设置PCA计数器阵列寄存器(CH和CL)以及捕获寄存器(CCAPnH和CCAPnL)

SetCapnMod(0,PCA0_CAPN);

//开启PCA中断

EnPcaModnInt(0);

//启动pca模块

StartPCA();

while(1)

{

P12 = ~P12;

delay();

}

}

 

void PCA_ISR(void) interrupt 7

{

switch(CCON&0x03)

{

//模块0触发中断

case CCF0_INT:

//清除模块中断标志位

CCON &= (0x00<

P15 = ~P15;

break;

//模块1触发中断

case CCF1_INT:

CCON &= (0x00<

break;

default:

break;

}

}


程序烧写到MCU后,用跳线帽连接P12和P13,使得P13对P12的输出经行采样。下面是示波器的输出:



蓝色波形是P12引脚的输出,黄色波形是P15引脚的输出。图中(我的低端示波器)可以很明显的看出P13上采样到一个负跳表,P15发生一次翻转。


这个功能跟计数器每次计满一个脉冲就触发中断类似,不过感觉没有计数器那么灵活,它可以计数256个跳变,不过PCA捕捉可以同时捕捉双边沿,可用于脉宽测量;




STC MCU PCA模块还有其他功能,不过感觉有点无聊,就不一一展示了,不过代码还是要贴上来已做备忘:


#include

 

enum sState

{

sInit=0,sPca,sClk,sPwm,sClkOut,

};

 

#define CCF1_INT 0x02

#define CCF0_INT 0x01

 

#define ResetPCA() \

do{ \

CCON = 0; \

CL = 0; \

CH = 0; \

CMOD = 0x00; \

CCAPM0 = 0x00; \

CCAPM1 = 0x00; \

}while(0); \

#define StartPCA() \

do{ \

CR = 1; \

}while(0); \

#define SetModnCmp(n) \

do{ \ 

CCAPM##n |= PCA0_ECOM; \

CCAPM##n |= PCA0_MAT; \

}while(0); \

 

#define SetModnTog(n) \

do{ \

CCAPM##n |= PCA0_TOG; \

}while(0); \

#define SetCapnMod(n,mod) \

do{ \

CCAPM##n |= mod; \

}while(0); \

#define SetCCAPn(n,hi,lo) \

do{ \

CCAP##n##H = hi; \

CCAP##n##L = lo; \

}while(0); \

//

#define EnPcaModnInt(n) \

do{ \

CCAPM##n |= PCA0_ECCF; \

}while(0); \

 

#define SetPwmMod(n) \

do{ \

CCAPM##n |= PCA0_ECOM|PCA0_PWM; \

}while(0); \

 

int main()

{

unsigned char sState = sInit;

 

ResetPCA();

EA = 1;

while(1)

{

switch(sState)

{

case sInit:

//输入提示

break;

default: 


sState = sInit;

break;

case sPca:

ResetPCA();

//捕捉模式,捕捉到跳变沿时触发中断

//CH-CL不用与CCAPnH-CCAPnL比较,因此不用使能ECOMn

//也不需要设置PCA计数器阵列寄存器(CH和CL)以及捕获寄存器(CCAPnH和CCAPnL)

SetCapnMod(0,PCA0_CAPN|PCA0_CAPP);

//开启PCA中断

EnPcaModnInt(0);

sState = sInit;

break;

case sClk:

                        //软件定时器功能

                        ResetPCA();

//定时器功能

//CH-CL增加计数值,然后与CCAPnH和CCAPnL比较,相等触发中断

//有比较功能 设置比较和匹配控制位

SetModnCmp(0);

//设置 CCAPnH和CCAPnL,当CH-CL计数值==CCAPnH-CCAPnL中的预制值

//发生中断

SetCCAPn(0,0x80,0x00);

//开启PCA中断

EnPcaModnInt(0);

sState = sInit;

break;

case sPwm:

ResetPCA();

//pwm有比较功能 但没用到匹配...真特立独行

//只要设置CCAPMn的PWM位和比较位

SetPwmMod(0);

//设置占空比,有点类似定时器Mod2,TH自动装载到TL

//此处是CCAPnH自动装载到此处是CCAPnL(8位);CH装载到CL(8位)

//CH-CL低于 CCAPnH-CCAPnL输出0,其他输出1

SetCCAPn(0,0x80,0x80);

sState = sInit;

break;

case sClkOut:

                        //高速输出功能

                        ResetPCA();

//当PCA计数器的CH-CL与CCAPnH-CCAPnL中的预制值相等时

//CCPn发生翻转,这个功能也用到比较-匹配

SetModnCmp(0);

SetModnTog(0);

EnPcaModnInt(0);

sState = sInit;

break;   

}

//启动pca模块

StartPCA();

}

}

 

void PCA_ISR(void) interrupt 7

{

switch(CCON&0x03)

{

//模块0触发中断

case CCF0_INT:

//清除模块中断标志位

CCON &= (0x00<

break;

//模块1触发中断

case CCF1_INT:

CCON &= (0x00<

break;

default:

break;

}

}


关键字:STC12系列  单片机  PCA模块 引用地址:STC12系列单片机PCA模块应用

上一篇:STC12C5A60S2之串口
下一篇:STC12C5A60S2双串口通信

推荐阅读最新更新时间:2024-03-16 16:23

怎么用8051单片机控制步进电机
在本文中,讲解了怎么用8051单片机控制步进电机。步进电机广泛用于工业、医疗、消费电子应用。简而言之,它用于任何需要物体精确旋转或定位的地方。 一、什么是步进电机? 步进电机是一种无刷电机,可将电脉冲转换为机械旋转。顾名思义,它根据输入脉冲逐步旋转。步进电机通常具有多个励磁线圈(相)和带齿转子。电机的步长由转子上的相数和齿数决定。步长是转子在一步中的角位移。如果步进电机有4相50个齿,则需要50×4=200步才能旋转一整圈。所以步距角将为360/200=1.8°。 我们使用的步进电机有4极和一个1/64减速齿轮机构,用于增加扭矩。电机的步距角为5.64°。但考虑减速机时,输出轴的步距角为5.64/64°。步进电机的内部示意
[单片机]
怎么用8051<font color='red'>单片机</font>控制步进电机
51单片机实验——十六进制计数器
1.实验题目: 用P0.0- P0.03设计一个在0-15之间自动计数的十六进制计数器,每个数持0.2s。 代码采用SWITCH语句,利用for循环实现16进制的计数器设计。 四个IO口相连接的LED灯按照0000-1111的二进制变化顺序进行计数。 2.KEIL代码 #include reg51.h #include intrins.h sbit P00=P0^0; sbit P01=P0^1; sbit P02=P0^2; sbit P03=P0^3; void Delay200ms();//声明延时函数 void main() { int i=0; while(1) { for(i=0;i 1
[单片机]
51<font color='red'>单片机</font>实验——十六进制计数器
单片机控制红外编码探测障碍物
1 探测障碍的原理 在室内自动感知障碍的设备中,常使用红外线探测障碍物的存在与否。探测的基本原理是:在测量的范围内,主动向探测方向发射红外信号,如果存在障碍物,就会把发射的信号反射回发送端。在发送端,如果收到反射的信号,就确认障碍物的存在。 但是在实际应用中,红外干扰源较多;而且在有反射光的情况下,由于光线的干扰,很容易判断失误,出现虚警。因此,有些设备在发射信号时,改进为发送一串连续的红外脉冲,然后接收反射的信号。如果接收到的红外脉冲数量超过某一门限值时,就判断障碍存在。这种方法尽管在一定程度上可以降低虚警率,但实验表明,在较强的反射光和使用电子镇流器方式的日光灯起辉时,仍很容易出现干扰现象。 本文提出解决干扰的方案是:由
[单片机]
PIC单片机的中断资源及应用
    摘要: PIC系列单片机是美国Microchip技术公司推出的8位嵌入式控制器。它以其控制速度高、工作电压低、功耗小及性价比高等优点而备受青睐。本文以PIC16CXX系列单片机为例介绍了PIC单片机中断资源的特点、应用及应用中应注意的问题,并给出了具体的应用源程序。     关键词: PIC单片机 中断资源 中断源 唤醒 1 PIC单片机简介 PIC系列单片机是美国Microchip技术公司推出的高性能价格比的8位嵌入式控制器(Embedded Controller),它采用了精简指令集计算机RISC(Reduced Instruction Set Computer)和哈佛(H
[工业控制]
51单片机寄存器间接寻址方式与举例
寄存间接寻址方式是指寄存器中存放的是操作数的地址,即操作数是通过寄存器间接得到的,因此称为寄存器间接寻址。 MCS-51单片机规定工作寄存器的R0、R1做为间接寻址寄存器。用于寻址内部或外部数据存储器的256个单元。为什么会是256个单元呢?我们知道,R0或者R1都是一个8位的寄存器,所以它的寻址空间就是2的八次方=256。 例:MOV R0,#30H ;将值30H加载到R0中 MOV A,@R0 ;把内部RAM地址30H内的值放到累加器A中 MOVX A,@R0 ;把外部RAM地址30H内的值放到累加器A中 大家想想,如果用DPTR做为间址寄存器,那么它的寻址范围是多少呢?DPTR是一个16位的寄存器,所以它
[单片机]
AVR单片机的全功能工业控制器设计
引言   在自动控制产品的设计过程中,实现方案的选择常常是很矛盾的。使用可编程逻辑控制器(PLC)和人机界面(HMI)来实现,开发速度较快,但成本太高,所开发的产品没有市场竞争力;使用单片机开发,成本低但开发周期长、开发量大且通用性不好。用户需要的是一种成本低、开发周期较短、通用性较好的控制器,因此全功能工业控制器有很大的应用市场。   全功能工业控制器的整个电路分为信号隔离输入部分、控制器输出部分、实时时钟与历史数据存储部分、彩色液晶显示和触摸屏控制部分、通信接口等。 1 信号隔离输入电路   信号隔离输入电路分为开关量隔离输入、模拟量隔离输入、高速电脉冲隔离输入,电路如图1所示,开关量的隔离输入较为简单,输入信号采用
[单片机]
AVR<font color='red'>单片机</font>的全功能工业控制器设计
电子工程师传经授道:AVR单片机经典使用经验
使用更好的器件只是为设计实现一个好的系统创造了一个好的基础和可能性,如果还采用和沿袭以前传统的硬件和软件设计思想和方法的话,是不能用好AVR的,甚至也不能真正的了解AVR的特点和长处。 AVR具有上手入门快,开发方便简单的特点,但要充分体会和发挥AVR的优点,还需要应用工程师本身的硬软件设计开发能力的不断学习、实践提高。 AVR与传统类型的单片机相比,除了必须能实现原来的一些基本的功能,其在结构体系、功能部件、性能和可靠性等多方面有很大的提高和改善。 功能越好的器件,需要具备更高技术和能力的人来使用和驾驭它。就象一部好的F1赛车,只有具备高超技术的驾驶员才能充分体会到车的特点,并能最大限度的发挥出车的性能。 “外行看
[模拟电子]
电子工程师传经授道:AVR<font color='red'>单片机</font>经典使用经验
ARM 逐步蚕食工业市场 核心MCU固守优势
嵌入式应用MCU业务被证明是半导体产品市场上一项赚钱的业务。根据市场调研公司iSuppli的统计,仅仅在中国,目前嵌入式应用MCU市场每年都有20亿美元左右的规模。因此,在半导体业务增速放缓,经济大环境并不乐观的情况下,大多数拥有MCU业务的公司都在加强该项业务。而在此过程中,MCU厂商的策略各有不同。    CortexM3拓展消费和工业市场或将形成三足鼎立局面    毫无疑问,基于ARMCortex-M3的MCU产品目前在嵌入式MCU市场掀起了一股热潮。多家MCU企业已经推出或计划推出基于该核心的MCU。例如,意法半导体、恩智浦、Atmel和东芝半导体等企业已推出多款基于ARMCortex-M3的MCU。德州仪器通过
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved