一、前言
C8051F340单片机的可编程技术阵列PCA0,可以工作在边沿触发的捕捉模式。
在该方式,CEXn引脚上出现的电平跳变导致PCA捕捉PCA计数器/定时器的值并将其装入到对应模块的16位捕捉/比较寄存器(PCA0CPLn和PCA0CPHn)。PCA0CPMn寄存器中的CAPPn和CAPNn位用于选择触发捕捉的电平变化类型:上升沿、下降沿。当捕捉发生时,PCA0CN中的捕捉/比较标志(CCFn)被置‘1’并产生中断请求(如果CCF中断被允许)。当转向中断服务程序时,CCFn位不能被硬件自动清除,必须用软件清0。如果CAPPn和CAPNn位都被设置辑‘1’,可以通过直接读CEXn对应端口引脚的状态来确定本次捕捉是由上升沿触发还是由下降沿触发。
二、程序展示
1、程序简介
本程序中应用定时器2产生方波通过P0.1输出,然后通过P0.0引入到PCA0。硬件上需要将P0.0和P0.1短接。
2、头文件部分
#include <c8051f340.h>
#define SYSCLK 12000000
#define T0_RELOAD 120 // 120为10us
#define T2_RELOAD 3000 //3000为250us
sfr16 PCA0CP0 = 0xFB;
sfr16 TMR2RL = 0xCA;
sfr16 TMR2 = 0xCC;
sbit T2_OUT = P0^1; // 用于测试的方波源
void OSCILLATOR_Init (void);
void PORT_Init (void);
void PCA0_Init (void);
void T2_Init (void);
3、主程序部分
main ()
{
PCA0MD = 0x00; // 关闭看门狗
PORT_Init (); //端口初始化
OSCILLATOR_Init (); // 晶振初始化
PCA0_Init (); //PCA0初始化
T2_Init (); // 定时器2初始化
EA = 1;
while (1)
{
if (TF2H)
{
T2_OUT = ~T2_OUT; // 通过定时器250us翻转一次P0.1的输出
TF2H = 0; // 清定时器2溢出标志
}
};
}
4、晶振初始化程序
void OSCILLATOR_Init (void)
{
OSCICN = 0x83; // 使用内部晶振12M
CLKSEL = 0x00;
}
5、端口初始化程序
void PORT_Init (void)
{
XBR0 = 0x00;
XBR1 = 0x41; //将CEX0配置到P0.0,
P0MDOUT |= 0x02; //设置 P0.1为推挽输出
}
6、PCA0初始化程序
void PCA0_Init (void)
{
TMOD &= 0xF0; // 清定时器0
TMOD |= 0x02; //8位自动重载
CKCON |= 0x04; //使用系统时钟
TH0 = 0xFF-T0_CLOCKS; // 设置T0重载值
TL0 = 0xFF-T0_CLOCKS; //设置初始值
PCA0CN = 0x00; //清除所有标志
PCA0MD = 0x04; //使用T0作为时基
PCA0CPM0 = 0x21; // 设置上升沿捕捉
EIE1 |= 0x10; // 允许PCA中断
CR = 1;
TR0 = 1; // 启动定时器0
}
7、定时器2初始化程序
void T2_Init (void)
{
CKCON |= 0x10; // 使用系统12M
TMR2RL = 0XFFFF-T2_RELOAD; // 重载值
TMR2 = 0XFFFF-T2_RELOAD;
TMR2CN = 0x04; // 设置定时器2工作在16位自动重载模式
}
8、PCA0 中断程序
void PCA0_ISR (void) interrupt 11
{
static unsigned int current_value, previous_value;
static unsigned int capture_period;
if (CCF0) //如果中断是由CCF0引起
{
CCF0 = 0; //清CCF0
current_value = PCA0CP0;
// 计算捕捉时间
capture_period = current_value - previous_value;
// 更新上一次的值
previous_value = current_value;
}
else // 中断如果由其他引起
{
PCA0CN &= ~0x86; // 清除其他中断标志
}
}