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功能逻辑图:
5、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;//更新比较值
CCAP0H=value0>>8;
value0+=t0;//累加定时间隔值
LED=!LED;//LED取反
}
if (CCF1)
{
CCF1=0;//清中断,因PCA计数溢出中断已禁止,所以这里不必再清CF
CCAP1L=value1;//更新比较值
CCAP1H=value1>>8;
value1+=t1;//累加定时间隔值
LED2=!LED2;//LED2取反
}
}
void main()
{
CCON=0;
CL=0;
CH=0;
value0=t0;
CCAP0L=t0;//更新比较值
CCAP0H=t0>>8;
value0+=t0;//累加定时间隔值
value1=t1;//如改成value1=3500,进中断后还是按照value1=3000,则可让波形2延时0.5ms,如下页波形图
CCAP1L=t1;//更新比较值
CCAP1H=t1>>8;
value1+=t1;//累加定时间隔值
CMOD=0x00;//模式:FSOC/12、关ECF允许PCA中断
AUXIE=0x04;//打开PCA总中断
CCAPM0 =0x49;//模块0设置16位定时器,并产生模块0的中断信息CCF0
CCAPM1=0x49;//模块1相同设置
EA=1;
CR=1;
while(1);
}
下图1、通道1按1ms定时输出(LED),通道2按3ms定时输出(LED2),因二个模块用的是同一时钟,理论上起始波应对准,但逻辑仪显示相差3us(图中不明显,可观察T1-T2的值),原因为:尽管二个模块同时产生中断的,但中断处理时先处理模块0,翻转LED,再处理模块1,所以1的波形有延时。,假如需这二个输出完全同步,则可在main程序中修正初始值为value1=2997即可。
下图2:首次初始值改为value1=3500,则可把波形2的相位往后500us。
测试4:PCA模块0、1用作高速输出模式
思路:
这个测试比较好做,沿用上述程序,直接修改指令“CCAPM0 = 0x4D;”,即CCAPM0=01001101B,第6、3、2、0位置位,跟上面PCA模式“16位定时”相比,仅多置位TOGn位,即让模块0在其CEX0/P1.2不断翻转高低电平,形成脉冲输出。程序同时也启动模块1,代码不再列出。
高速输出分析:
考虑模式名称为“高速输出”,程序重设t0=30,t1=90,即脉冲宽度缩小为30us和90us。程序运行时,利用逻辑分析仪观察P1.2/P1.3二脚的输出信号,同时也观察中断程序中设置的二个LED翻转信息(写LED,实际输出频率高,接LED无法观察,而用逻辑分析仪观察其设置引脚P2.1/P2.2)。波形如下图:
上图可以得到:
1)模块0(30u)和模块1(90us)完全同步,见标志T1绿色线,因为各模块共享PCA计数器;
2)上图T1-T2=4.875us,是从CCF0置位后程序进入中断处理到LED=1的时间约长5us。当中断处理程序对CCF0清0后,模块0才能在下次比较时重新产生中断。这个时间就是影响最小计时的因素,可见5us或许为高速输出的最小值,详见下述分析。
中断处理所需时间分析:
假设仅启动模块0,中断响应后必须重装CCAP0的值,指令如下:
LED =1;//设置测试变量
CCF0=0;//清模块0中断
CCAP0L=value0; //更新比较值
CCAP0H=value0>>8;
value0+=t0;//累加t0,准备下次比较值
LED =0;//测试变量
上述语句中,LED的二句仅作观察用。为缩小中断处理时间,可省去。进入仿真调试后,复制出从中断起到中断返回共有18条汇编指令,共耗费25个机器周期,如下表所示:
指令序号
指令地址
指令码
指令
周期数
执行时间
1.
C:0x0053
0200E2
LJMP
PCA_isr(C:00E2)
2
7周期
2.25us
0.321us/t
2.
C:0x00E2
C0E0
PUSH
0xE0
2
3.
C:0x00E4
C0D0
PUSH
PSW(0xD0)
2
4.
C:0x00E6
D2A1
SETB
LED(0xA0.1)
1
5.
C:0x00E8
C2D8
CLR
CCF0(0xD8.0)
1
12周期
2.75us
0.23us/t
6.
C:0x00EA
850DEA
MOV
CCAP0L(0xEA),0x0D
2
7.
C:0x00ED
E50C
MOV
A,value0(0x0C)
1
8.
C:0x00EF
F5FA
MOV
CCAP0H(0xFA),A
1
9.
C:0x00F1
E509
MOV
A,0x09
1
10.
C:0x00F3
250D
ADD
A,0x0D
1
11.
C:0x00F5
F50D
MOV
0x0D,A
1
12.
C:0x00F7
E508
MOV
A,t0(0x08)
1
13.
C:0x00F9
350C
ADDC
A,value0(0x0C)
1
14.
C:0x00FB
F50C
MOV
value0(0x0C),A
1
15.
C:0x00FD
C2A1
CLR
LED(0xA0.1)
1
16.
C:0x00FF
D0D0
POP
PSW(0xD0)
2
17.
C:0x0101
D0E0
POP
0xE0
2
18.
C:0x0103
32
RETI
2
合计
25
实测>5us
由上述分析可见,如果需要输出5us间隔的方波,按上述程序将无法完成,因为中断处理程序耗时超过5us。如果设t0=5,将会出现如何现象呢?经测试得到如下图波形:
实际模块0在每个PCA计数溢出之间可观察到9次电平翻转(9条竖线),放大后如下:
上图第一行为模块0输出,第二行为中断程序处理的LED电平翻转,可见其宽度达到了5.375us,已经超过5us的设定值,当完成第9次输出后,标记小旗2处,中断程序执行CCF0=0前,PCA计数5us已到,硬件在CCF0=1此再置位CCF0,此后即刻被指令CCF0=0清除。尽管程序已经更新了value值,但PCA计数已经越过此值,也不会产生比较一致的中断信号,因此硬件要等到下次PCA计数值到达value值时才会再次产生中断,这也就是为什么间隔65.535ms才产生几个正常输出的原因。
然而,如果去除LED=!LED这条指令后,5us的高速输出能正常进行。然而当设置为4us间隔后,输出又如上图,每65ms才输出3次。
测试5:PCA模块0、1输出PWM
要用作PWM,因不需要进中断处理,程序更为简单,关键是设置模式CCAPM0=0x42即可。
主程序:
void main()
{
CCON=0;//关PCA、清0全部PCA中断标志
CL=0;
CH=0;
CCAP0H=0xC0;//模块0输出25%占空比PWM
CCAP1H=0x40;//模块1输出75%占空比PWM
CMOD=0x00;//模式:FSOC/12、关ECF禁止PCA中断
//AUXIE=0x04;//打开PCA总中断(PWM输出时不需产生中断)
CCAPM0 =0x42;//模块0设置PWM
CCAPM1=0x42;//模块1相同设置
PCAPWM0 &=0xFC;//第9位ECAP0H=0,该位在需要0%占空比时设为1
PCAPWM1 &=0xFC;//第9位ECAP1H=0
//EA=1;
CR=1;
while(1);
}
实测如下:输出周期256us,模块0输出占空比25%,模块1输出占空比75%。
几个特点:
1、当使用FSOC/12作为PCA计数源时,PWM周期为256us,如果需要不同的周期,就得使用T0作为计数源或外部输入;
2、当CCAPnH=0xFF时,占空比达到最小值0.39%(1/256),如果要达到0%占空比输出,则必须启用PCAPWM0寄存器的ECAP0H位,设为1,同时CCAP0H=0即可。
3、用作PWM功能时,PCA不需产生中断,因而AUXIE 寄存器及其他相差中断的位不必设置。
本文链接: http://epca.immuno-online.com/view-698501.html