STC单片机PCA代码测试的方法及过程解析

控制/MCU

1883人已加入

描述

MPC82G516为***笙泉公司生产的8位MCU,兼容8051。内建PCA功能6个模块,模块0—5对应P1.2—P1.7, P1.1为输入脉冲源ECI。本文记录了测试PCA的代码和过程,重点分析各寄存器的设置,还通过逻辑分析仪记录相关波形。STC15F60S2等芯片也内建PCA功能,不过仅3模块,但功能更为丰富,设置编程过程大同小异,可参考。

1、相关寄存器:

寄存器

功能

地址

7

6

5

4

3

2

1

0

描述

CCON

控制

D8

CF

CR

CCF5

CCF4

CCF3

CCF2

CCF1

CCF0

CR:启停PCA总计数器

CF:PCA总计数器溢出标志

CCF0-5:各模块中断标志

CMOD

模式

D9

CIDL

CPS1

CPS0

ECF

CIDL:空闲模式是否计数

CPS1、CPS0:时钟源:12分.2分.T0.ECI.四选一

ECF:PCA计数溢出中断

AUXIE

中断

AD

EKB

ES2

EBD

EPCA

EADC

ESPI

EPCA:PCA中断开关

CCAPM

0-5

模块模式

DA-

DF

ECOM

0-5

CAPP

0-5

CAPN

0-5

MAT

0-5

TOG

0-5

PWM

0-5

ECCF

0-5

ECOMn 允许比较

CAPPn 上升CAPNn 下降

MATn 匹配CCFn位

TOGn 匹配翻转引脚电平

PWM脉宽调制输出

ECCFn 使能中断信号CCFn

CCAPnL

捕获

寄存器

EA-EF

比较:先设初值,与PCA比较

捕获:捕获PCA值到寄存器

CCAPnH

FA-FF

PCAP

WM0-5

PWM

模式

F2-

F7

ECA

PnH

0-5

ECA

PnL

0-5

PWM时作为第9位

用于设定占空比

CL、CH

PCA

PCA总计数器

AUXR1

引脚

8E

P4KB

P4PCA

P4SPI

P4S2

GF2

DPS

P4PCA:引脚切换到P4口

2、比较、捕获模式设置寄存器CCAPM0-5:

CCAPMn

16进值

有/无中断

功能

备注

-000 0000

无操作

-x10 000x

20/21

16位CEXn引脚上升沿触发捕获模式

捕获值不处理仅进中断,相当于增加了外部中断功能

-x01 000x

10/11

16位CEXn引脚下降沿触发捕获模式

-x11 000x

30/31

16位CEXn引脚有跳变沿触发捕获模式

-100 100x

48/49

16位软件定时器

均需进中断重设比较值,并清0中断标志,因此最小定时值》=5us。差别是定时器仅利用中断信号,高速输出则利用对应引脚电平的翻转

-100 110x

4C/4D

16位高速输出

-100 0010

42/

8位PWM

占空比=1-[ECAPnH,CCAPnL]/256

3、PCA功能使用步骤:

1) 确定CCON=0x00;一般先清0

2)确定CMOD=0x00;00不开PCA中断,01开;脉冲源为FSOC/12

3)AUXIE = 0x04;打开PCA总中断开关,捕获及定时均要打开,PWM时可关闭

4)设置各模块工作模式寄存器CCAPMn,见表2

5)设置PCA计数器初值:CL=0;CH=0

6)定时或高速输出时,需设置CCAPnL及CCAPnH值

7)PWM功能时,需设置CCAPnH(及ECAPnH在PCAPWM寄存器中)

8)启动PCA计数:CR=1;如有必要打开总中断:EA=1

9)写中断处理函数,MPC82G516的PCA中断向量为10(53H),STC15F60S2为7

4、PCA功能逻辑图:

PCA

5、PCA中断逻辑示意图:

PCA

6、PCA中断向量

MPC82G516的PCA中断编号为10。STC15F60S2的中断矢量为7。

测试1:PCA总计数器溢出中断

思路:不使用任何模块,仅启动PCA总计数器,为方便观察,开通中断并在中断处理程序中设置观察变量(P2.1)作电平翻转,再用逻辑分析仪观察其变化。

步骤:

1、CCON清0,各中断标志清0,关闭PCA计数

2、CMOD:设置脉冲源,置位ECF(允许总PCA计数溢出中断)

3、打开各级中断:AUXIE中设EPCA,开总中断EA

4、启动PCA:CR=1

在p2.1可观察到65.536宽度电平翻转。程序如下:

程序:

#include “REG_MPC82G516.H”

#include “intrins.h”

sbit LED =P2^1;//测试LED

void PCA_isr() interrupt 10 //注意中断向量号为10,STC15F为7

{

CF=0;//清中断

LED=!LED;//LED取反

}

void main()

{

CCON=0;

CL=0;

CH=0;

CMOD=0x01;//12分频。使用0x03则为系统时钟2分频

AUXIE=0x04;

EA=1;

CR=1;

while(1);

}

FOSC/12:PCA计数每65.531ms溢出一次(理论值应为65.536ms)

如果改脉冲源为FOSC/2:PCA计数每10.922ms溢出一次

测试2:PCA模块0用作捕获模式,CEX0引发中断

思路:

模块0设置为捕获模式,捕获信号由模块0对应的引脚P1.2输出,可上升、下降或边缘触发,具体通过设置CCAPM0来实现,见表2。

下降沿触发捕获:CCAPM0=0x11 (00010001),即CAPN0=1、ECCF0=1可直接短接CEX0/P1.2与地来获得下降沿;

上升沿触发捕获:CCAPM0=0x21 (00100001) 需先短接CEX0/P1.2与地、再释放来获得上升沿;

注意MCU的四个端口复位后均为“准双向口”,开路时内部有弱上拉。

当CEX0触发捕获时,捕获到的数据并不作处理(如带仿真,可仿真时查看到该捕获值),因此本程序相当于为单片机增加了一个外部中断功能。

程序:

#include “REG_MPC82G516.H”

#include “intrins.h”

sbit LED =P2^1;//测试LED

sbit LED2=P2^2;//接LED观察

void PCA_isr() interrupt 10

{

unsigned charTmpL;//临时变量,暂存捕获值

unsigned charTmpH;

//CF=0; //清中断(PCA计数溢出,这里不必使用)

LED=!LED;//LED取反

if (CCF0)//当CEX0(P1.2)触发捕获时,引发中断CCF0

{

TmpL=CCAP0L;

TmpH=CCAP0H;

CCF0=0;//软件清中断

//P12=1;//拉高测试引脚,用于下次下降沿触发

LED2=!LED2;//可接发光二极管观察中断产生情况

}

}

void main()

{

CCON=0;

CL=0;

CH=0;

CMOD=0x00;//模式:FSOC/12、ECF禁止PCA中断(以免产生无效中断)

AUXIE=0x04;//打开PCA总中断

CCAPM0 =0x11;//模块0设置为外部引脚上升沿触发捕获模式,并产生模块0的中断信息CCF0

EA=1;

CR=1;

//P12=1;

while(1);

}

测试3:PCA模块0、1用作16位定时模式

思路:

PCA各模块如用作定时器,因16位PCA计数器启动后,总是从0000—FFFF循环计数,比较寄存器[CCAPnH + CCAPnL]如装载固定值的话,每个PCA计数周期(65535个脉冲)只能产生一次比较相同输出,为了实现自定义的计数值,必须在每次计数中断后给[CCAPnH + CCAPnL]加一个固定值,这样PCA计数到新值后又能产生中断输出,达到定时器的目的;

编程步骤:

1) CCON清0,各中断标志清0,关闭PCA计数

2)CMOD:设置脉冲源,置位ECF(允许总PCA计数溢出中断)

3)PCA计数器CH+CL=0000,比较寄存器[CCAPnH + CCAPnL]+=T(T为定时值)

4)设置本模块工作方式为16位定时器:CCAPM0 =0x49

5)打开各级中断:AUXIE=0x04 开总中断EA

6) 启动PCA:CR=1

7) 中断处理程序:添加代码 [CCAPnH + CCAPnL]+=T,作为下次比较值

观察办法:

在中断程序中设置变量LED/P2.1(模块1用LED2),每次中断反转以输出方波(接逻辑仪分析)

代码:(模块0定时1ms,模块1定时3ms)

#include “REG_MPC82G516.H”

#include “intrins.h”

sbit LED =P2^1;//测试LED

sbit LED2=P2^2;//接LED观察

unsigned int t0=1000;//定义16位变量t,定时1ms

unsigned int t1=3000;//定义16位变量t,定时3ms

unsigned int value0;

unsigned int value1;

void PCA_isr() interrupt 10

{

if(CCF0)

{

CCF0=0;//清中断,因PCA计数溢出中断已禁止,所以这里不必再清CF

CCAP0L = value0; //更新比较值

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分