历史上的今天
返回首页

历史上的今天

今天是:2025年01月26日(星期日)

2019年01月26日 | STC12系列单片机PCA模块应用

2019-01-26 来源:eefocus

 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;

}

}


推荐阅读

史海拾趣

Dfx公司的发展小趣事

随着智能家居市场的不断发展,某智能家居企业面临着如何将各种智能设备无缝连接、实现高效协同的挑战。通过引入DFX的设计理念,该企业成功实现了智能家居产品的标准化、模块化和可扩展性设计。这种设计方式使得不同设备之间可以方便地进行连接和通信,提高了系统的整体性能和用户体验。同时,该企业还通过优化生产流程和加强质量控制等手段,确保了产品的稳定性和可靠性。

这些故事虽然基于虚构的情境,但融入了电子行业中常见的实际问题和发展趋势。通过引入DFX的设计理念,这些企业成功解决了面临的挑战,提升了产品竞争力并赢得了市场的认可。

G-Link Technology公司的发展小趣事

为了进一步扩大市场份额,蜂鸟无线积极实施国际化战略。公司先后在亚洲、欧洲和北美等多个地区设立了研发中心和销售网络,以更好地服务全球客户。在国际化过程中,蜂鸟无线注重与当地企业和政府机构的合作,共同推动无线通信技术的发展和应用。通过参与国际展会、举办技术交流会等活动,蜂鸟无线不仅提升了品牌知名度,还成功吸引了众多国际合作伙伴,为公司的全球化发展奠定了坚实基础。

CONEXANT公司的发展小趣事

在无线通信技术快速发展的时代,Conexant公司积极寻求与业界领先企业的合作机会。2001年,Conexant宣布将其无线业务部门与Alpha Industries合并,共同创建一个价值约30亿美元的新企业。这一合并不仅扩大了Conexant在无线通信领域的市场份额,也为其带来了更多的技术资源和市场机会。合并后的新企业以Conexant为主导,通过整合双方的优势资源,实现了无线业务的快速发展和市场份额的稳步提升。

Davico Industrial Ltd公司的发展小趣事

在语音通信领域,Conexant以其卓越的声卡技术赢得了市场的广泛认可。特别是在网络语音电话方面,Conexant声卡凭借其出色的性能和稳定性,成为了众多商务本和工作站的首选。惠普、联想等知名品牌的产品线中,都能看到Conexant声卡的身影。这一成功不仅源于Conexant对技术的持续投入和创新,也得益于其对市场需求的敏锐洞察和精准把握。

Emerson公司的发展小趣事

进入20世纪,Emerson迎来了一系列技术突破。1903年,公司成功研发出马力超过1/2的电机,这些电机被广泛应用于洗衣机、缝纫机等家用电器,进一步拓宽了公司的业务范围。此外,Emerson还积极开拓海外市场,通过并购和战略合作,逐步将业务拓展至全球范围。

富瀚(Fullhan)公司的发展小趣事
采用先进的检测技术和算法,能够更准确地判断电动机的运行状态,提供更高精度的保护。

问答坊 | AI 解惑

编程器使用问题

我在http://89s51.com/KE.htm买了这个编程器。现在销售人员找不到,想问下各位: 1.PCB板两排鱼骨针,是外接电路的?还是干什么用的. 2.软件中的测试区不管你换什么IC永远是32PIN的功能什么都没有变化. 3.编程区都没有怎么编程?在缓存区? 现在 ...…

查看全部问答>

基于C8051F020芯片的多功能计数器设计

引言  计数器作为一种测量工具.在实验分析、工业丁程制造、测试系统中发挥着巨大的作用。随着电子技术的发展.计数器的软硬件有了飞速发展,其应用领域不断扩展.功能也得到了加强。尤其是各种新型计数器的应用。极大地提高了测量的精度、测量的 ...…

查看全部问答>

EVC 要如何关闭其它正在执行程序

EVC 要如何关闭其它正在执行程序. 目前使用 FindWindow 来做,但因窗口名称可能会改变,所以不太适用,有否直接针对该执行文件的文件名称关闭程序 …

查看全部问答>

GetLocalTime取得的系统时间里面毫秒一直为0

在模拟器上运行的,一直为0. 不支持那么精确? 有没有其他的取得方法?谢谢…

查看全部问答>

wince启动信息

我现在板子的串口信息输出以下内容就 停了:(上略)OEMIoControl: Unsupported Code 0x10100b4 - device 0x0101 func 45 +OALIoCtlHalInitRTC(...) -OALIoCtlHalInitRTC(rc = 0) OEMIoControl: Unsupported Code 0x101008c - device 0x0101 fu ...…

查看全部问答>

一个毕业生需要大家帮助,谢谢!

  我本人马上就要毕业了,想在毕业后从事嵌入式方面的工作,我不是计算机本专业的,只是对这方面感兴趣才学的,一直在学着c和汇编,刚开始看arm开发,但是现在到了要毕业的时候了,家里人非要逼着我回我们那里工作,我家是山西的,几乎没 ...…

查看全部问答>

维持2轮电车平衡你们都用的陀螺仪?还有其他方案吗

近年来2轮电车,4轴飞行器都变得很流行。大家都用过什么样型号的陀螺,什么方案来测量啊。求推荐一便宜又比较精准,好用的方案。 …

查看全部问答>

TA TB 比较锁存器

MSP430F5438的TB模块的比较功能比TA模块多一个比较锁存器,请问这样设置有什么好处吗 …

查看全部问答>

我自己做的TI蓝牙和ZIGBEE脱机烧录代码工具!

可以擦除、读、写、加密片内flash;支持的型号:cc2540,cc2541,cc2530,cc2531, 我的脱机烧写工具实际测试烧写cc2540f256需要20到30秒左右!…

查看全部问答>