电子科技大学现代电子信息系统综合实验课程设计代码(单片机+频率计)2

接上一篇博客:
https://blog.csdn.net/Jinyindao243052/article/details/107821839

这是另外一种思路:

有两种测频模式,一个高频模式,一个低频模式

T0和T1都是计时器

单片机中断方案代码

#include <reg51.h>
#include <absacc.h>
#include <ctype.h>

sbit KEY2 = P2^0;		//按键1	high mode
sbit KEY3 = P2^1;		//按键2	low mode
sbit KEY4 = P2^2;       //按键3 切换档位
sbit LED0=P0^0;
sbit LED1=P0^1;
sbit LED2=P0^2;

unsigned char flag;//阀门开否
unsigned char mode;//模式 :0低频 1:高频
unsigned char DispBuf[8];
unsigned char s[8];
unsigned char d;//档位
unsigned int t;//阀门长度/毫秒
unsigned long count;
unsigned long f;
unsigned long j;//循环变量
unsigned int wait;
unsigned int a=0;
//直接引用模块
void delay_l(unsigned int t){	   //一个小改编,low mode使用的延时函数
	do
	{
		TH0 = 0xFF;
		TL0 = 0x69;
		TR0 = 1;
		while ( !TF0 );
		TR0 = 0;
		TF0 = 0;
	} while ( --t != 0 );
}
void delay(unsigned int t){	   //high mode使用的延时函数
	do
	{
		TH0 = 0xFA;
		TL0 = 0x24;
		TR0 = 1;
		while ( !TF0 );
		TR0 = 0;
		TF0 = 0;
	} while ( --t != 0 );
}
unsigned char KeyScan(){	  //按键检测
	unsigned char k = '\0';	 	
	if ( KEY2 == 0 ) k = 'h';
	if ( KEY3 == 0 ) k = 'l';
	if ( KEY4 == 0 ) k = 'd';//切换阀门长度
	return k;
}

void DispClear(){	    //清空缓存
	unsigned char i;
	for ( i=0; i<8; i++ )
	{
		DispBuf[i] = 0x00;
	}
}

void DispInit(){
	DispClear();	
	EA = 0;
	TMOD &= 0x0F;
	TMOD |= 0x10;
	TH1 = 0xFC;
	TL1 = 0x66;
	TR1 = 1;
	ET1 = 1;
	EA = 1;//EA=1 是打开总中断
}

void SysInit(){
	TMOD &= 0xF0;
	TMOD |= 0x01;	//设置定时器T0为16位定时器
	DispInit();		//数码管扫描显示初始化
	IT0 = 1;//如果IT0设置为0,则外部中断0引脚被拉至低电平即可引发外部中断
}

void T1INTSVC() interrupt 3	  //定时器1,定时器中断,负责扫描数码管
{	  
	code unsigned char com[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
	static unsigned char n = 0;
	TR1 = 0;
	TH1 = 0xFC;
	TL1 = 0x66;
	TR1 = 1;
	XBYTE[0x7800] = 0xFF;		
	XBYTE[0x7801] = ~DispBuf[n];	
	XBYTE[0x7800] = ~com[n];	
	n++;
	n &= 0x07;
}
//自己实现的实现函数
unsigned long HighMod(unsigned int t)//阀门长度t=100或1000,测频率法
{
	 count=0;
	  EX0=1;//EX0是外部中断0的使能控制位,如果EX0设置为0,则外部中断0失效
	  delay(t);
	  EX0=0;
	 return count;

}

unsigned long LowMod()//低频模式下测量脉冲宽度,测周期法
{  

   unsigned long wait = 0;
   unsigned long th0 = 0;
   unsigned long tl0 = 0;
   unsigned long avg=0;
   unsigned char i;
   for(i=0;i<20;i++)//采用测周法
	{count = 1;
	EX0 = 1;
	flag=0;
	while(!flag){	
		delay_l(1);
		wait++;
		if(wait>=1000000) break;//等待了1000000下,待测脉冲没有跳动一下,退出不再等
	}
	while(flag){delay_l(1);count++;};//上升沿到来,flag置为1,开始计算脉冲宽度,下一个上升沿到来,flag再次为0,停止计时,时长储存在flag中
	avg+=count;
	EX0 = 0;
	}
	avg/=20;//20次测得的脉冲宽度求均值,作为实际脉冲宽度	
	return avg;
}

void time0() interrupt 0  T0,外部中断
{
	  if (mode==0)//低频模式
	  {
	    flag=1-flag;
	  }
	  if (mode==1)//高频模式
	  {
	    count=count+1;
	  	a=a+1;
	  }

}
unsigned long freq_h(unsigned long count)//高频模式下计算频率值f
{
     unsigned long temp=count;
   	 if(t==100)//t是阀门长度
	 {
	   f=10*temp;
	 }
	 if(t==1000)
	 {
	   f=temp;
	 }

	 return f;
}

unsigned long freq_l(unsigned long count)//低频模式下计算频率值f
{
     unsigned int temp=0;
	 temp=count;
 	 f =(int)(100000/temp);
	 return f;
}


void display (unsigned long f)//刷新 DispBuf
{
  code unsigned char Tab[] ={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};   //0-9的码字
	unsigned char i;
	for ( i=0; i<8; i++ ){
		unsigned long int c;
		c = f%10;
		f = (f-c)/10;
		DispBuf[i] = Tab[c];//DisBuf低位对应数值低位
	}
	if (mode==0)
	{DispBuf[1] |= 0x80;}
}

void main()
{
    unsigned char key = 'h';  //按键检测返值
	mode=1;
	t=1000;
	SysInit();
	display(0);
	for(;;)
	{
	  while(1)
	  {
	  delay(50);
	  key=KeyScan();
	  if (key!='\0')//如果有键按下,退出循环
	  {
	    break;
	  }
	  }
		if (key=='h')
		{
		LED0=0;
		LED1=1;
		mode=1;
		count=HighMod(t);
		f=freq_h(count);
		display(f);
		}
		if (key=='l')
		{
		LED0=1;
		LED1=0;
		mode=0;
		count=LowMod();
		f=freq_l(count);
		display(f);
		}
		if (key=='d')
		{
		  LED2=~LED2;//LED2翻转
		  if(t==100)
 		 {t=1000;LED2=0;}//切换到1000阀门,LED2关闭
 		 else
  		{t=100;LED2=1;}
		LED0=0;//
		LED1=1;
		ET1=0;//停止刷新数码管,更新频率
		mode=1;
		count=HighMod(t);
		f=freq_h(count);
		display(f);
		ET1=1;//更新完数码管,继续刷新频率
		}
	while(1)
	{
	delay(5);
	key=KeyScan();
	if(key=='\0')
	{break;}
	}
	EA=1;
	ET1=1;
	TR1=1;
	}


} 

参考:
https://www.cnblogs.com/alantechnique/p/5453647.html
https://zhidao.baidu.com/question/1241874441618237339.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值