1.分析原理图
我们可以看到,上图就是一个NE555构建的方波发生电路,输出方波频率=1.44/2(R8+Rb3)C,如果有不懂NE555内部结构,工作原理的,可以到B站学习。实在不懂仿真也行,比如我下面就是仿真结果:
然后就是下图,NE555输出的方波信号输入到电容二极管组成的负压生成电路,产生大概4.3V的负压Vee供运放使用。这与本节内容无关,我只是一起讲了。
再看下图:NE555输出方波信号也接到了排针J3上,而且旁边就是P34引脚,又由于比赛时好像不会提供杜邦线,所以我们也只能用跳线帽将NET_SIG和P34连在一起,然后单片机通过P34引脚来测输出频率。
2.定时器测频
这里我就不得不狠狠的吐槽一波这板子的设计人员,既然你都用STC15F2K61S2了,为什么不能想着兼容设计把P34改成P35呢?我们知道,定时器0可以对P34引脚输入脉冲计数,定时器1可以对P35引脚输入脉冲计数,STC89C52和STC15F都是一样的。但是STC15F还有一个更好用,更灵活的外设:PCA
但是呢,槽点来了,CCP功能切换不到P34引脚,只能把PCA计数脉冲源切换到P34引脚,就很无语,你把P34替换成P35,既能兼容STC89C52使用定时器1对外部脉冲计数,也能兼容STC15F使用CCP功能,就不能好好阅读一下STC15F的用户手册嘛?
不过现在我也不打算就用定时器0来对外部输入脉冲计数,因为我的初衷是把板子上面的各个外设都封装一遍且互不干扰,现在定时器0已经被我用做前后台功能了,所以我得另寻他法。别说,还真有。
这里真的不得不佩服STC芯片的设计者们,使用一个PCA计数阵列就能实现脉冲捕获,PWM输出,软16位定时器,外部中断,D/A功能。关于此外设具体如何使用,请阅读STC15F用户手册!
我这里就是使用的PCA计数阵列对P34输入的脉冲进行计数,然后每1S获取计数值,计数值即频率。
3.代码封装库
代码注释即解析,请一定先仔细阅读PCA外设章节。
#include "capture.h"
u32 frequency=0; //得出频率,单位HZ
u8 Overflow=0; //PCA计数溢出次数
//PCA软件定时器对P34输入脉冲计数
void Capture_Init()
{
P_SW1 &=0XCF; //清除CCP_S1,CCP_S0位
P_SW1 |=0X10; //CCP在P34/ECI_2
CCON = 0; //清除CF标志 PCA定时器停止 清除模块0/1/2中断标志
CL = 0;CH = 0; //复位PCA计数值
CMOD = 0x07; //设置PCA时钟源:ECI输入,允许PCA溢出中断
CR = 1; //启动PCA计数器阵列计数
EA = 1; //开总中断
}
void PCA_isr() interrupt 7 //发生匹配中断
{
CF = 0; //清中断标志
CL = 0;CH = 0; //复位PCA计数值
Overflow++;
}
//每1S获取一次计数值,即频率
void Get_Frequency()
{
frequency = (Overflow<<16) | (CH<<8) |CL;
CL = 0;CH = 0;Overflow=0;
}
4.使用示例
#include "main.h"
bit KeyScan_Flag=0;
extern u32 frequency; //测得频率
void System_Init(void);
void Timer0_Init(void);
void main()
{
System_Init();
Timer0_Init();
Capture_Init();
while(1)
{
Nixie_Display(1,(frequency%100000000)/100000);
Nixie_Display(2,(frequency%10000000)/10000);
Nixie_Display(3,(frequency%1000000)/10000);
Nixie_Display(4,(frequency%100000)/10000);
Nixie_Display(5,(frequency%10000)/1000);
Nixie_Display(6,(frequency%1000)/100);
Nixie_Display(7,(frequency%100)/10);
Nixie_Display(8,frequency%10);
}
}
void Timer0_Isr() interrupt 1 //1ms中断一次
{
static u16 count1=0;
if(++count1==1000) //每1S获取一次计数值
{
Get_Frequency();
count1=0;
}
}
void Timer0_Init() //1毫秒@12.000MHz
{
AUXR &= 0x7F; //12T模式
TMOD &= 0xF0; //定时器0:16位自动重装载
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC;
TF0 = 0; //清除TF0标志
ET0 = 1; //使能定时器0中断
EA = 1; //开总中断
TR0 = 1; //定时器0开始计时
}
void System_Init()//系统上电初始化
{
//先锁存蜂鸣器,继电器所在573输出低电平,防止上电乱叫
P25=1;P26=0;P27=1; //74HC138-->Y5=0,else=1-->Y5C=1,else=0
P04=0;P06=0; //ULN2003输入经过非门送入达林顿管,低电平有效
P25=0;P26=0;P27=0;//锁存数据
//关闭所有LED灯
P25=0;P26=0;P27=1; //74HC138-->Y4=0,else=1-->Y4C=1,else=0
P0=0XFF;
P25=0;P26=0;P27=0;//锁存数据
}
我们通过旋转滑动变阻器RB3就能改变输出频率,演示效果如下,由于手头没有示波器,只能到学校再验证误差了。
NE555测频演示