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

相关文章

51单片机学习记录———定时器

文章目录 前言一、定时器介绍二、STC89C52定时器资源三、定时器框图四、定时器模式五、定时器相关寄存器六、定时器练习 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出~ 提示:以下是本篇文章正文内容,下面案例可供参考 一、定时器介绍 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。 定时器作用: 1.用于计数系统,可

JAVA读取MongoDB中的二进制图片并显示在页面上

1:Jsp页面: <td><img src="${ctx}/mongoImg/show"></td> 2:xml配置: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001

零基础STM32单片机编程入门(一)初识STM32单片机

文章目录 一.概要二.单片机型号命名规则三.STM32F103系统架构四.STM32F103C8T6单片机启动流程五.STM32F103C8T6单片机主要外设资源六.编程过程中芯片数据手册的作用1.单片机外设资源情况2.STM32单片机内部框图3.STM32单片机管脚图4.STM32单片机每个管脚可配功能5.单片机功耗数据6.FALSH编程时间,擦写次数7.I/O高低电平电压表格8.外设接口

【操作系统】信号Signal超详解|捕捉函数

🔥博客主页: 我要成为C++领域大神🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞👍收藏⭐评论✍️ 本博客致力于知识分享,与更多的人进行学习交流 ​ 如何触发信号 信号是Linux下的经典技术,一般操作系统利用信号杀死违规进程,典型进程干预手段,信号除了杀死进程外也可以挂起进程 kill -l 查看系统支持的信号

据阿谱尔APO Research调研显示,2023年全球髓内钉市场销售额约为4.7亿美元

根据阿谱尔 (APO Research)的统计及预测,2023年全球髓内钉市场销售额约为4.7亿美元,预计在2024-2030年预测期内将以超过3.82%的CAGR(年复合增长率)增长。 髓内钉市场是指涉及髓内钉制造、分销和销售的行业。髓内钉是一种用于整形外科手术的医疗器械,用于稳定长骨骨折,特别是股骨、胫骨和肱骨。髓内钉通常由不銹钢或钛等材料制成,并插入骨的髓管中,以在愈合过程中提供结构支

vue+elementUI下拉框联动显示

<el-row><el-col :span="12"><el-form-item label="主账号:" prop="partyAccountId" :rules="[ { required: true, message: '主账号不能为空'}]"><el-select v-model="detailForm.partyAccountId" filterable placeholder="

DDS信号的发生器(验证篇)——FPGA学习笔记8

前言:第一部分详细讲解DDS核心框图,还请读者深入阅读第一部分,以便理解DDS核心思想 三刷小梅哥视频总结! 小梅哥https://www.corecourse.com/lander 一、DDS简介         DDS(Direct Digital Synthesizer)即数字合成器,是一种新型的频率合成技术,具有低成本、低功耗、高分辨率、频率转换时间短、相位连续性好等优点,对数字信

[FPGA][基础模块]跨时钟域传播脉冲信号

clk_a 周期为10ns clk_b 周期为34ns 代码: module pulse(input clk_a,input clk_b,input signal_a,output reg signal_b);reg [4:0] signal_a_widen_maker = 0;reg signal_a_widen;always @(posedge clk_a)if(signal_a)

将一维机械振动信号构造为训练集和测试集(Python)

从如下链接中下载轴承数据集。 https://www.sciencedirect.com/science/article/pii/S2352340918314124 import numpy as npimport scipy.io as sioimport matplotlib.pyplot as pltimport statistics as statsimport pandas

温湿度采集及OLED显示

目录 软件I2C和硬件I2C每隔2秒钟采集一次温湿度数据,显示到OLED上,同时通过串口发送到上位机的“串口助手”软件 软件I2C和硬件I2C "I2C"代表Inter-Integrated Circuit,是一种用于在数字电路之间进行通信的串行通信协议。软件I2C和硬件I2C是两种实现这种协议的方式。 软件I2C是通过软件来模拟I2C通信协议的实现方式。在这种情况下,微控制