STC51单片机14——利用51单片机测量信号的频率,高低频及转速显示

2023-10-25 12:11

本文主要是介绍STC51单片机14——利用51单片机测量信号的频率,高低频及转速显示,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

完整代码及仿真资料打包下载:

STC单片机14-利用51单片机测量信号的频率,高低频及转速显示 icon-default.png?t=M85Bhttps://download.csdn.net/download/fengyuzhe13/87325539

主程序:

/*
外部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标志
}

仿真结果:

这篇关于STC51单片机14——利用51单片机测量信号的频率,高低频及转速显示的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/282489

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

day-51 合并零之间的节点

思路 直接遍历链表即可,遇到val=0跳过,val非零则加在一起,最后返回即可 解题过程 返回链表可以有头结点,方便插入,返回head.next Code /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}*

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

lvgl8.3.6 控件垂直布局 label控件在image控件的下方显示

在使用 LVGL 8.3.6 创建一个垂直布局,其中 label 控件位于 image 控件下方,你可以使用 lv_obj_set_flex_flow 来设置布局为垂直,并确保 label 控件在 image 控件后添加。这里是如何步骤性地实现它的一个基本示例: 创建父容器:首先创建一个容器对象,该对象将作为布局的基础。设置容器为垂直布局:使用 lv_obj_set_flex_flow 设置容器

单片机毕业设计基于单片机的智能门禁系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍程序代码部分参考 设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订

C# dateTimePicker 显示年月日,时分秒

dateTimePicker默认只显示日期,如果需要显示年月日,时分秒,只需要以下两步: 1.dateTimePicker1.Format = DateTimePickerFormat.Time 2.dateTimePicker1.CustomFormat = yyyy-MM-dd HH:mm:ss Tips:  a. dateTimePicker1.ShowUpDown = t

列举你能想到的UNIX信号,并说明信号用途

信号是一种软中断,是一种处理异步事件的方法。一般来说,操作系统都支持许多信号。尤其是UNIX,比较重要应用程序一般都会处理信号。 UNIX定义了许多信号,比如SIGINT表示中断字符信号,也就是Ctrl+C的信号,SIGBUS表示硬件故障的信号;SIGCHLD表示子进程状态改变信号;SIGKILL表示终止程序运行的信号,等等。信号量编程是UNIX下非常重要的一种技术。 Unix信号量也可以