STC8A单片机频率计的代码发啦
zvs吧
全部回复
仅看楼主
level 12
先放电路图,下面发代码
2019年10月07日 10点10分 1
level 12
#include "STC8.h"
sbit hold=P3^2;
unsigned char qumo[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
unsigned long int fh=0;
unsigned char tri=1;
unsigned int ms=0;
void dsmg(unsigned char zifu)
{
P0=qumo[zifu];
}
/*
void delay1s() //?? 0us
{
unsigned char a,b,c;
for(c=167;c>0;c--)
for(b=171;b>0;b--)
for(a=16;a>0;a--);
}
*/
void counter0on()//用16位自动重装载模式不正常,不进中断
{
TMOD|=0x06;
TH0=0x00;
TL0=0x00;
TR0=1;
ET0=1;
EA=1;
}
void timer1on()
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD|= 0x00; //xxxx 0000 16位自动重装载模式
TL1 = 0xB0; //设置定时初值
TH1 = 0x3C; //设置定时初值
TF1 = 0; //清除TF1标志
EA = 1;
ET1 = 1;
TR1 = 1;
}
void ex0on()//外部中断0接按键用于保存数据
{
IT0=1;
EX0=1;
EA=1;
}
void delay1ms(void) //@36MHz
{
unsigned char i, j;
i = 36;
j = 1;
do
{
while (--j&&tri);
} while (--i&&tri);
}
void scansmg(unsigned char dws[6])
{
unsigned char sanp=0x80,sani=0,t=6;
P2=~sanp;
while(t--&&tri)
{
dsmg(dws[sani]);
delay1ms();
P0=0x00;
sani++;
P2=~(sanp>>sani);
}
}
void chaifen(unsigned long int dws,unsigned char dwssz[6])
{
unsigned char i=0;
unsigned long int chai=100000;
unsigned char dwst=0;
while(dwst<6)
{
dwssz[dwst]=dws/chai;
dws=dws%chai;
chai=chai/10;
dwst++;
}
while(!dwssz[i]&&i<5)//消无意义0
{
dwssz[i]=16;
i++;
}
}
/*
void xiao0(unsigned char dwssz[8])//消0集成到拆分里了
{
unsigned char i=0;
while(!dwssz[i]&&i<7)
{
dwssz[i]=16;
i++;
}
}
*/
void Sys_clk()
{
P_SW2 = 0x80;
XOSCCR = 0x80; //选择有源晶振 1000 0000
while (!(XOSCCR & 1)); //等待时钟稳定
CLKDIV = 0x00; //时钟不分频
CKSEL = 0x01; //选择外部晶振 0000 0001
P_SW2 = 0x00;
}
void main()
{
unsigned char dwssz[6];
unsigned long int dws=888888;
unsigned long int result;
Sys_clk();
P0M0=0xFF;
P0M1=0x00;
counter0on();
timer1on();
P3=0xff;
chaifen(dws,dwssz);
ex0on();
while(1)
{
scansmg(dwssz);
// P1=TL0;//调试用,用二进制显示数值
if(ms>=60)
{
ms=0;
result=(TL0+256*fh);
fh=0;//做频率计启用这行
TL0=0;//同上
chaifen(result,dwssz);
// TL0++;//用于测试计时精度
tri=1;
}
}
}
void counter0() interrupt 1
{
fh++;
}
void timer1() interrupt 3
{
//TH1 = 0x3C;//16位自动重装载模式不需要这两行了
//TL1 = 0xB0;
ms++;
if(ms>=60)
{
tri=0;
}
}
void Int0() interrupt 0//保持数据
{
EA=0;
P0=0x00;
delay1ms();
delay1ms();
delay1ms();
if(!hold)
{
TR0=!TR0;
TR1=!TR1;
}
while(!hold);
delay1ms();
delay1ms();
delay1ms();
EA=1;
}
2019年10月07日 10点10分 2
缩进格式全部被百度吃掉了,应该不影响使用
2019年10月07日 11点10分
level 12
代码如上,仅适用于stc8a单片机。有些调试过程做的标注和残留的废弃代码痕迹可以删除,无作用。
整个项目的概述看这贴:https://tieba.baidu.com/p/6281661015?red_tag=3452376824
2019年10月07日 10点10分 3
level 10
谢谢老板
2019年10月07日 14点10分 4
level 1
完美
2019年10月08日 07点10分 5
level 12
补充一个,布线图,基本上是按洞洞板设计的,可以直接用洞洞板做
2019年10月09日 03点10分 6
level 8
讲道理,一块STC8性能还是很强的,专门做这个有点浪费了。
2019年10月09日 05点10分 7
是么,我还担心不够,现在基本上是在中断里穿插主程序,中断非常频繁。中断间隔短,我不敢在中断里写更多东西,只能发回主程序里计算,中断结束返回主程序里的位置又不固定,主程序又要循环数码管,因此之前的代码会出现来不及计算而漏统计外部脉冲的情况。现在改了不知还会不会
2019年10月09日 06点10分
就是那个ms=60,时间到1s的标志。到1s就对外部脉冲个数读取计算清零,因为外部脉冲很快,计数器中断很频繁,如果将判断1s和之后操作放在放在定时器中断里又可能被脉冲计数器的中断嵌套了,或者阻碍了脉冲计数器的中断。
2019年10月09日 07点10分
现在只能将ms=60给主程序判断,但是定时器中断ms=60是返回到主程序的时候主程序正在做别的东西,响应ms=60就被推迟了一点,就造成了漏统计外部脉冲。现在只能在所有主程序循环里都加上tri这个标志,让每次到1s时就tri=0立刻结束循环尽快回到读取计算清零的判断里。但是如果回的速度不够快,还是可能漏
2019年10月09日 07点10分
你的代码看着头疼,不要用拼音哎。 测量原理是什么?对单位时间内的脉冲数统计计算是吗?计数器不是自动增加的吗,每一次脉冲触发硬件自增?不需要软件干涉呀。
2019年10月09日 11点10分
level 1
[真棒]
2020年07月07日 23点07分 8
1