利用STC单片机的PCA模块可以测量脉冲宽度
代码参考STCISP上的范例程序
1所需硬件:
1 PWM模块 信号发生器
2 STC8A8K单片机
2 ECBM设置,如图
由上图可以看出本次试验并没有启用PCA计数器溢出回调函数,因为计算必须在中断中快速进行。开始我也是在回调函数中计算,但数据很不稳定。取消回调函数后数据很稳定。
在nvic.c中声明如图变量
具体代码:
unsigned char cnt=0;
volatile unsigned char finshFlag=0; //存储PCA计时溢出次数
unsigned long count0=0; //记录上一次的捕获值
unsigned long count1=0; //记录本次的捕获值
unsigned long length=0; //存储信号的时间长度
中断中的程序
中断程序的代码
/*-------------------------------------------------------
PCA的各种中断处理函数。
-------------------------------------------------------*/
#if ECBM_PCA_LIB_EN
void nvic_pca_function(void)interrupt 7{
if(PCA_GET_IT_FLAG){
PCA_CLS_IT_FLAG;
cnt++;
#if ECBM_PCA_CALLBACK_EN
pca_timer_callback();
#endif
}
if (CCF0)
{
CCF0 = 0;
count0 = count1; //备份上一次的捕获值
((unsigned char *)&count1)[3] = CCAP0L;
((unsigned char *)&count1)[2] = CCAP0H;
((unsigned char *)&count1)[1] = cnt;
((unsigned char *)&count1)[0] = 0;
length = count1 - count0; //计算两次捕获的差值,即得到时间长度
finshFlag=1;
}
main.c
#include "ecbm_core.h" //加载库函数的头文件。
#define T 0.090422454//11.0592M时钟周期
extern unsigned char cnt;
extern unsigned char finshFlag;
extern unsigned long length;
double freq;
void main(void){ //main函数,必须的。
system_init(); //系统初始化函数,也是必须的。
pca_init();
uart_printf(1,"ECBM 测量频率测试\r\n");//打印count变量的值
while(1){
if(finshFlag)
{
freq=1000000L/(length*T);
// uart_printf(1,"length=%ld\r\n",length);//打印count变量的值
uart_printf(1,"freq=%3.2fHz\r\n",freq);
delay_ms(200);
finshFlag=0;
}
}
}
运行效果
附:STC8G1K08 P5.4输出362.83Hz 外部晶振11.0592M/240/127=362.83Hz
#include "reg51.h"
#define MCLKOCR (*(unsigned char volatile xdata *)0xfe05)
#define CLKDIV (*(unsigned char volatile xdata *)0xfe01)
#define CKSEL (*(unsigned char volatile xdata *)0xfe00)
#define XOSCCR (*(unsigned char volatile xdata *)0xfe03)
sfr P_SW2 = 0xba;
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P_SW2 = 0x80;
XOSCCR = 0xc0; //启动外部晶振
while (!(XOSCCR & 1)); //等待时钟稳定
CLKDIV=0XF0;
CKSEL = 0x01; //选择外部晶振
// MCLKOCR = 0x01; //主时钟输出到P5.4口
// MCLKOCR = 0x02; //主时钟2分频输出到P5.4口
MCLKOCR = 0x7F; //主时钟4分频输出到P5.4口
// MCLKOCR = 0x84; //主时钟4分频输出到P1.6口
P_SW2 = 0x00;
while (1);
}