完整代码及仿真资料打包下载:
STC单片机14-利用51单片机测量信号的频率,高低频及转速显示-单片机文档类资源-CSDN下载
?
主程序:
/* 外部12M晶振,系统时钟12分频,T1定时 P3.4为信号输入端 按钮1:按下为高频段(1kHz-10kHz) ?? ??? 抬起为低频段(0Hz-1kHz) 按钮2:按下为显示频率(Hz) ?????? 抬起为显示转速(r/min) */ #include<reg52.h>??? //包含单片机寄存器的头文件 #include<intrins.h>? //包含_nop_()函数定义的头文件 sbit RS=P2^0;??? //寄存器选择位,将RS位定义为P2.0引脚 sbit RW=P2^1;??? //读写选择位,将RW位定义为P2.1引脚 sbit E=P2^2;???? //使能信号位,将E位定义为P2.2引脚 sbit BF=P0^7;??? //忙碌标志位,,将BF位定义为P0.7引脚 sbit FRE=P1^0;?? ??? ?//频率选择 sbit SHOW=P1^1;?? ??? ?//显示切换 sbit ff=P2^6; sbit kk=P2^7; unsigned char speed[6]={"000000"};
unsigned int time_n; unsigned long? number,num; //四个字节 unsigned char button1,button2,temp;
/***************************************************** 函数功能:延时1ms (3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒 ***************************************************/ void delay1ms() { ?? unsigned char i,j;?? ? ?? ? for(i=0;i<10;i++) ?? ?? for(j=0;j<33;j++) ?? ??? ;?? ??? ? ?} ?/***************************************************** 函数功能:延时若干毫秒 入口参数:n ***************************************************/ ?void delay(unsigned char n) ?{ ?? unsigned char i; ?? ?for(i=0;i<n;i++) ?? ??? delay1ms(); ?} /***************************************************** 函数功能:判断液晶模块的忙碌状态 返回值:result。result=1,忙碌;result=0,不忙 ***************************************************/ ?unsigned char BusyTest(void) ? { ??? bit result; ?? ?RS=0;?????? //根据规定,RS为低电平,RW为高电平时,可以读状态 ??? RW=1; ??? E=1;??????? //E=1,才允许读写 ??? _nop_();?? //空操作 ??? _nop_(); ??? _nop_(); ??? _nop_();?? //空操作四个机器周期,给硬件反应时间?? ? ??? result=BF;? //将忙碌标志电平赋给result ?? ?E=0; ??? return result; ? } /***************************************************** 函数功能:将模式设置指令或显示地址写入液晶模块 入口参数:dictate ***************************************************/ void WriteInstruction (unsigned char dictate) {? ? ??? while(BusyTest()==1); //如果忙就等待 ?? ? RS=0;????????????????? //根据规定,RS和R/W同时为低电平时,可以写入指令 ?? ? RW=0;? ? ?? ? E=0;?????????????????? //E置低电平(根据表8-6,写指令时,E为高脉冲, ???????????????????????????? // 就是让E从0到1发生正跳变,所以应先置"0" ?? ? _nop_(); ?? ? _nop_();???????????? //空操作两个机器周期,给硬件反应时间 ?? ? P0=dictate;??????????? //将数据送入P0口,即写入指令或地址 ?? ? _nop_(); ?? ? _nop_(); ?? ? _nop_(); ?? ? _nop_();?????????????? //空操作四个机器周期,给硬件反应时间 ?? ? E=1;?????????????????? //E置高电平 ?? ? _nop_(); ?? ? _nop_(); ?? ? _nop_(); ?? ? _nop_();?????????????? //空操作四个机器周期,给硬件反应时间 ?? ?? E=0;????????????????? //当E由高电平跳变成低电平时,液晶模块开始执行命令 ?} /***************************************************** 函数功能:指定字符显示的实际地址 入口参数:x ***************************************************/ ?void WriteAddress(unsigned char x) ?{ ???? WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x" ?} /***************************************************** 函数功能:将数据(字符的标准ASCII码)写入液晶模块 入口参数:y(为字符常量) ***************************************************/ ?void WriteData(unsigned char y) ?{ ??? while(BusyTest()==1); ? ?? ?? RS=1;?????????? //RS为高电平,RW为低电平时,可以写入数据 ?? ?? RW=0; ?? ?? E=0;??????????? //E置低电平(根据表8-6,写指令时,E为高脉冲, ?????????????????????? // 就是让E从0到1发生正跳变,所以应先置"0" ?? ?? P0=y;?????????? //将数据送入P0口,即将数据写入液晶模块 ?? ?? _nop_(); ?? ?? _nop_(); ??? ?? _nop_(); ???? _nop_();?????? //空操作四个机器周期,给硬件反应时间 ?? ?? E=1;????????? //E置高电平 ?? ?? _nop_(); ?? ?? _nop_(); ?? ?? _nop_(); ?? ? _nop_();??????? //空操作四个机器周期,给硬件反应时间 ?? ? E=0;??????????? //当E由高电平跳变成低电平时,液晶模块开始执行命令 ?} /***************************************************** 函数功能:对LCD的显示模式进行初始化设置 ***************************************************/ void LcdInitiate(void) { ?? delay(15);???????????? //延时15ms,首次写指令时应给LCD一段较长的反应时间 ?? WriteInstruction(0x38);? //显示模式设置:16×2显示,5×7点阵,8位数据接口 ?? ?delay(5);?? //延时5ms ?? ?WriteInstruction(0x38); ?? ?delay(5); ?? ?WriteInstruction(0x38); ?? ?delay(5); ?? ?WriteInstruction(0x0c);? //显示模式设置:显示开,无光标,光标不闪烁 ?? ?delay(5); ?? ?WriteInstruction(0x06);? //显示模式设置:光标右移,字符不移 ?? ?delay(5); ?? ?WriteInstruction(0x01);? //清屏幕指令,将以前的显示内容清除 ?? ?delay(5); ?}
void TimerInitiate(unsigned char f) { ??? if(f==0)//高频 ?? ?{ ????? TMOD=0x15;??? // TMOD=0001 0101B,使用T1 16位定时,T0 16位计数 ????? EA=1;???????? //开总中断 ?? ?? ET1=1;??????? //使用定时器T1的中断??? ? ?? ?? TH1=0x3c;?????? //定时器T1高8位赋初值 ?? ?? TL1=0xb0;?????? //定时器T1低8位赋初值 ?? ?? TF1 = 0;?? ??? ?//清除TF1标志 ?? ?? ET0=0;??????? //不使用定时器T0的中断??? ? ?? ?? TH0=0;?????? //计数器T0高8位赋初值 ?? ?? TL0=0;?????? //计数器T0低8位赋初值 ?? ?? TR1=1;??????? //启动T1?? ?? ? ?? ?? TR0=1;??????? //启动T0 ?? ? ?? ??? ff=0; ?? ?} ?? ?else{? //低频 ????? TMOD=0x15;??? // TMOD=0001 0101B,使用T1 16位定时,T0 16位计数 ????? EA=1;???????? //开总中断 ?? ?? ET1=1;??????? //使用定时器T1的中断??? ? ?? ?? TH1=0x3c;?????? //定时器T1高8位赋初值 ?? ?? TL1=0xb0;?????? //定时器T1低8位赋初值 ?? ?? TF1 = 0;?? ??? ?//清除TF1标志 ?? ?? ET0=1;??????? //使用定时器T0的中断??? ? ?? ?? TH0=0xff;?????? //计数器T0高8位赋初值 ?? ?? TL0=0xff;?????? //计数器T0低8位赋初值 ?? ?? TF0 = 0;?? ??? ?//清除TF0标志 ?? ?? TR1=1;??????? //启动T1?? ?? ? ?? ?? TR0=1;??????? //启动T0 ?? ? ?? ??? ff=0;?? ? ?? ?}
}
void show(unsigned char k) { ?? unsigned char i=4; //?? unsigned long num;
?? num=number;?? ??? ?//防止数据在使用过程中发生变化 ? ??? ?if(k==0){?? ?//显示频率 ?? ??? WriteAddress(0x07);? // 设置显示位置为第一行的第7个字 ?? ??? WriteData('H'); ?? ??? WriteData('z'); ?? ??? WriteData(' '); ?? ??? WriteData(' '); ?? ??? WriteData(' '); ?? ??? if(button1==0) num= num *20; //T1定时50ms,乘以20得到频率 ?? ??? else num=1000000/num; ?? ? } ?? ? else {?? ??? ? //显示转速 ?? ??? WriteAddress(0x07);? // 设置显示位置为第一行的第7个字 ?? ??? WriteData('r'); ?? ??? WriteData('/'); ?? ??? WriteData('m'); ?? ??? WriteData('i'); ?? ??? WriteData('n'); ?? ???? if(button1==0) num= num *1200; //T1定时50ms,乘以20得到频率,再乘以60得到转速 ?? ??? ?else num=60000000/num;?? ?? ? ?? ?? } ?? ??? speed[0]=num%10+0x30; ?? ??? speed[1]=num/10%10+0x30; ?? ??? speed[2]=num/100%10+0x30; ?? ??? speed[3]=num/1000%10+0x30; ?? ??? speed[4]=num/10000%10+0x30; ?? ??? speed[5]=num/100000%10+0x30; ?? ??? i=5; ?? ??? while(i>0)?? ? { ?? ?? ??? ?? if(speed[i]==0x30) { ?? ??? ? ??? ? speed[i]=' '; ?? ??? ??? ? i--; ?? ??? ?? } ?? ??? ?? else break; ?? ??? }
?? ??? WriteAddress(0x00);? // 设置显示位置为第一行的第5个字 ?? ??? i=6; ?? ??? do{ ?? ??????? i--;?? ?? ??? ? ?? ??????? WriteData(speed[i]);? // 显示字符 ?? ??? ?? delay(150); ?? ??? }while(i!=0)?? ?; }
void main(void)??????????? //主函数 ?{ //?? unsigned long i,j; //?? ??? ?i=1; //?? ??? ?j=i<<16; //?? ??? ?if(j==0x010000) P3=0;?? ? //?? ??? ?while(1){ // //?? ??? ?} ?? ? ? ??? LcdInitiate();???????? //调用LCD初始化函数 ? ??? delay(10); ??? button1=FRE; ??? TimerInitiate(button1); ??? WriteInstruction(0x01);//清显示:清屏幕指令 ??? while(1) ???? { ?? ??? ?? button2=SHOW; ?? ??? ??? show(button2); ?? ??? ??? temp=FRE; ?? ??? ??? if(temp!=button1){ ?? ??? ????? button1=temp; ???????????? TimerInitiate(button1);?? ??? ?? ? ?? ??? ??? }?? ??? ? ?? ?}?? ??? ??? ? ??? ??? ? }
void Timer1() interrupt 3?? ? //定时50ms { ? TR1=0;?? //关闭定时器T1 ? if(button1==0)?? ? ? { ???? //? number= TH0<<8+TL0;?? ? //不能直接对TH0、TL0这样操作,不然会出错 ?? ?? temp=TH0; ????? number=temp<<8; ?? ?? number= number + TL0;?? ??? ?//number为50ms内T0计数总值 ????? TH0=0; ????? TL0=0; ?? } ?? else? time_n++;? ? ??? ?? TH1=0x3c;?????? //定时器T1高8位赋初值 ?? ?? TL1=0xb0;?????? //定时器T1低8位赋初值?? ??? ??? ?? ? ??? TR1=1;? ? ?? ?TF1 = 0;?? ??? ?//清除TF1标志 ?? ?ff=~ff; }
void Timer0() interrupt 1?? ??? //计数 { ? TR0=0;?? //关闭定时器T0 ?if(button1==0)?? ? ?? number=0;//代表频率太低,应该切换到低频档 ?else { ??? ?? temp=TH1; ????? number=temp<<8; ?? ?? number= number + TL1; //?? ?? number=6000; ????? if(time_n>0)?? ??? //猜测0<<16会出错 ?? ???? number=time_n<<16+ number-0x3cb0;?? ??? ?//number为一个周期的长度 ?? ?? else number=number-0x3cb0; ?? ?? //num=time_n*1000; ?? ?? time_n=0; ????? TH0=0xff; ????? TL0=0xff; ??? ?? TH1=0x3c;?????? //定时器T1高8位赋初值 ?? ?? TL1=0xb0;?????? //定时器T1低8位赋初值 ?? ?? kk=~kk;?? ? ?} ??? TR0=1;? ? ?? ?TF0= 0;?? ??? ?//清除TF0标志 }
?
|