• 工作总结
  • 工作计划
  • 心得体会
  • 述职报告
  • 事迹材料
  • 申请书
  • 作文大全
  • 读后感
  • 调查报告
  • 励志歌曲
  • 请假条
  • 创先争优
  • 毕业实习
  • 财神节
  • 高中主题
  • 小学一年
  • 名人名言
  • 财务工作
  • 小说/有
  • 承揽合同
  • 寒假计划
  • 外贸信函
  • 励志电影
  • 个人写作
  • 其它相关
  • 生活常识
  • 安全稳定
  • 心情短语
  • 爱情短信
  • 工会工作
  • 小学五年
  • 金融类工
  • 搞笑短信
  • 医务工作
  • 党团工作
  • 党校学习
  • 学习体会
  • 下半年工
  • 买卖合同
  • qq空间
  • 食品广告
  • 办公室工
  • 保险合同
  • 儿童英语
  • 软件下载
  • 广告合同
  • 服装广告
  • 学生会工
  • 文明礼仪
  • 农村工作
  • 人大政协
  • 创意广告
  • 您现在的位置:六七范文网 > 寒假计划 > 正文

    C具有可燃性吗_基于STC89C51制作的具有记录天亮天黑时间功能的时钟

    来源:六七范文网 时间:2019-04-02 04:48:03 点击:

      【摘要】采用具有4K EEPROM的STC89C51作为微控制器,提出了提高定时器计时精度的简单方法,节省了时钟芯片的开销,采用定时器编写延时程序,使目标代码变得精简,通过软缓冲机制使传感器抗干扰性增强。
      【关键词】STC89C51;晶振;EEPROM
      
      前段时间做一个记录天亮天黑时间的仪器,要求能存储时间,并且时钟要精度高,需要的时候可以上传到电脑进行分析处理。传感器可以用光敏二极管和光敏三极管以及光敏电阻,考虑到易于调整最终选择了使用光敏电阻。在数码管的驱动上选择了MAX7219芯片刚好驱动八位共阴极数码管,因为手头上只有三个按键,所以在按键的设计上,采用一键多能的设计方法,按键的功能分布如下:
      K1:按动一次可以进行小时的调整,且小时位闪烁给出提示,按动第二次可以对分钟调整,同样给出提示,按下第三次时候可以对秒进行调整,秒位也闪烁一下进行提示,第四次显示传感器读数,第五次按下后进入上传和格式化内部EEPROM的操作,并且都会给出提示。
      K2:调整时间时候进行加操作,上传和格式化时候为上传指令键。
      K3:调整时间时候进行减操作,上传和格式化时候为格式化指令键。
      由于手头没有时钟芯片,又不想去买,就考虑如何用定时器做出高精度的计时器,在进行stc的下载中发现了一个奇怪的现象,显示我单片机的晶振和标称相差很多,更换了几个做测试,结果一样,终于被我发现原来定时器不准的最大原因在晶振本身是不准的,现在我按照STC编程软件提示的频率设计中断程序的定时器初始值,然后把中断跳转的指令消耗的时间考虑进去,进行了两天的测量,尽然与我笔记本的时间误差不到1s,获得较为精准的时间成功,这完全可以和普通的时钟芯片相比了。
      考虑到按键的延时函数,以前都是使用for循环那样写太老套了,在各种书上我们只能看到for循环和while循环的延时函数,这种软件延时显然不能有效的控制延时时间,于是我考虑在中断里加上一个延时变量。这样就可以更为精准的控制延时了。而且会使目标代码更为短小。
      以前没有使用过STC的内部EEPROM,由于要求能够存储足够多的数据,需要能掉电保护的存储器,查看了STC89C51的手册发现竟然有4K的EEPROM可以使用,心里大喜,把手册上提供的EEPROM读写和擦除操作代码直接复制过来就行了。
      传感器选择了光敏电阻,经过万用表的测量,电阻在光照较强的时候大约1K,在黑暗环境达到几百K,于是选择了手头上的一枚10K的电阻进行串联匹配,用于分压比较。因为这样只需要测量定值电阻上的分压比就行了,不用考虑电压源的稳定性。在AD转换上采用ADC0832一片就OK,还多出来一个通道呢。
      在通过电脑串口上传数据时候发现每次上传一位需要延时一下,给硬件足够的反应时间,要不接收会出错的,比如没有收到全部数据,数据丢失,等等。
      在判断何时记录时间时候,考虑到传感器可能会出现数值震荡或者不稳定情况,那么我就通过设定缓冲区来解决这个问题。定义X1和X2作为触发记录的上下限,其中X1
      sbit DIN=P2^0; //MAX7219串行数据 1脚
      sbit LOAD=P2^1; //MAX7219片选 12脚
      sbit CLK=P2^2;//MAX7219串行时钟 13脚
      sbit k1=P2^3;
      sbit k2=P2^4;
      sbit k3=P2^5;
      sbit AD0832_CLK=P1^0;
      sbit AD0832_DIO=P1^1;
      sbit AD0832_CS=P1^2;
      //寄存器宏定义
      #define DECODE_MODE 0x09 //译码控制寄存器
      #define INTENSITY 0x0A //亮度控制寄存器
      #define SCAN_LIMIT 0x0B //扫描界限寄存器
      #define SHUT_DOWN 0x0C //关断模式寄存器
      #define DISPLAY_TEST 0x0F //测试控制寄存器
      #define X1 15 //这里我把黑夜触发值设置为15
      #define X2 20 //把天亮触发值设置为20,实际上天彻底黑的值为0
      #define X ADC0832()
      //定义全局变量
      char times[5]=0; //定义hour,minute,second,秒计数,延时计数到数组times,并初始化为0,此处必须为有符号字符,为了下面调时间方便
      bit backup;//定义参考变量
      unsigned char set_parameter=0;
      unsigned int address=0; //此处为全局变量,对同名局部变量不构成影响。
      //函数声明
      void Write7219(unsigned char address,unsigned char dat);
      void Initial(void);
      void Key(void);
      void delay(void);
      void set();
      void up();
      void down();
      void flicker();
      void record(void);
      bit ERASE=0;
      bit UPLOAD=0;
      //通过定时器延时的延时函数
      void delay(void)
       {
       times[4]=0; while(times[4]5) set_parameter=0; // 如果超过设定的功能数目就归零。
       while(k1==0)
       if(k2==1&&k3==1) //如果按键k1被按下没有释放,同时k2和k3也没有被按下,这时候执行
       flicker(); //闪烁程序,熄灭可设置的位置,直到k1被释放。
      }
      void up() //k2的功能
      {
      if(set_parameter==1) times[0]++;delay(); //小时加加
      if(set_parameter==2) times[1]++;delay(); //分钟加加
      if(set_parameter==3) times[2]++;delay(); // 秒加加
      if(set_parameter==5) UPLOAD=1; //如果在EE模式下按下up键,启动UPLOAD标准。
      }
      //按键K3的作用是减小选定的变量,另外在特殊功能时候进行擦除的操作确认
      void down()
      {
      if(set_parameter==1) times[0]--;delay(); //小时
      if(set_parameter==2) times[1]--;delay(); //分钟
      if(set_parameter==3) times[2]--;delay(); //秒
      if(set_parameter==5) ERASE=1; //擦除判断为真,进行擦除
      }
      void flicker() //闪烁程序,用于设置时间时候的告警
      {
      if(set_parameter==1) { Write7219(1,15); Write7219(2,15);delay();}
      if(set_parameter==2) { Write7219(4,15); Write7219(5,15);delay();}
      if(set_parameter==3) { Write7219(7,15); Write7219(8,15);delay();}
      }
      //ADC0832模拟转数字的子函数
      unsigned char ADC0832()
      {
       unsigned char i=0,dat=0;
       AD0832_CS=1; //一个转换周期开始
       AD0832_CLK=0; //为第一个脉冲作准备
       AD0832_CS=0; //AD0832_CS置0,片选有效
       AD0832_DIO=1; //AD0832_DIO置1,规定的起始信号
       AD0832_CLK=1;AD0832_CLK=0; //第一个脉冲的下降沿,此前AD0832_DIO必须是高电平
      
       AD0832_DIO=1; //AD0832_DIO置1, 通道选择信号
       AD0832_CLK=1;AD0832_CLK=0; //第二个脉冲,第2、3个脉冲下沉之前,DI必须跟别
       //输入两位数据用于选择通道,这里选通道CH0
       AD0832_DIO=0; //DI置0,选择通道0
       AD0832_CLK=1;AD0832_CLK=0; //第三个脉冲下降沿
       AD0832_DIO=1; //第三个脉冲下沉之后,输入端AD0832
      _DIO失去作用,应置1,
       AD0832_CLK=1; //第四个脉冲
       for(i=0;iX2)?1:0; //初始化参考位back
       unsigned char i;
       TMOD=0x01; //定时器T0工作于方式1,
       EA=1;
       ET0=1;
       TH0=(65536-46067)/256;
       TL0=(65536-46067)%256;
       TR0=1;
      //下面进入死循环,开始所有指令
      while(1)
       {
       Initial(); //MAX7219初始化,在循环体内初始化,增强抗干扰性。
      //设置观察传感器数值时候的显示方式,前三位显示,后五位灭掉
       while(set_parameter==4)
       {
       Write7219(1, ADC0832()/100 ); //显示读数的百位
       Write7219(2, ADC0832()%100/10);//显示读数的十位
       Write7219(3, ADC0832()%10); //显示读数的个位
       Write7219(4, 15 ); //其余数码管关闭显示
       Write7219(5, 15 );
       Write7219(6, 15 );
       Write7219(7, 15 );
       Write7219(8, 15);
       Key(); //此处跳出该循环
       }
      //下面进行是否触发记录的判断
       if(XX2&&back==0)
       { for(i=0;iX2&&back==0)
       {back=1; record(); }
       }
      //当按下第五次K1键的时候进入上传和格式化EEPROM的操作
       while(set_parameter==5)
       {
       for(i=1;i<9;i++)
       {
       if(i==4||i==5) Write7219(i,11); //在数码管的中间两位4和5上显示EE
       else Write7219(i,10); //其余显示——
       }
       Key(); //为下次按下K1跳出该while循环提供出口
       if(UPLOAD) uploading(); //如果UPLOAD为真那么就运行上传指令
       if(ERASE ) format(); //如果ERASE为真就运行格式化操作
       }
       Key(); //此处按键处理程序负责时间的调整
       //以下代码负责显示时间:小时,分钟,秒
       Write7219(1, times[0]/10 );
       Write7219(2, times[0]%10 );
       Write7219(3,10 );
       Write7219(4, times[1]/10 );
       Write7219(5, times[1]%10 );
       Write7219(6,10);
       Write7219(7, times[2]/10 );
       Write7219(8, times[2]%10 );
       }
       //结束while大循环
      }
      //结束main函数进入时间中断函数
      void timesInterrupt (void) interrupt 1 using 0
      {
      TH0=(65536-46067)/256; //跳转进入中断一般需要两个周期数,另外根据STC下载软件显示的
      TL0=(65536-46067)%256; //实际晶振频率进行计算得到当前使用的晶振46067个指令周期为50ms
      times[3]++; times[4]++; //times[4]为延时函数的定时器变量,当需要时候进行初始化为0
       if(times[3]==20) //50ms*20=1s
       {times[3]=0; times[2]++;} //足够一秒后秒加1,初始化计数变量为0
       if(times[2]==60) //足够一分钟后,分加1
       {times[2]=0; times[1]++;}
       if(times[1]==60) //足够60分钟小时加1
       {times[1]=0; times[0]++;}
       if(times[0]==24)times[0]=0; //采用通用的24小时制,够一天了清零
       if(times[0]<0) times[0]=23; //此处定义防止数值溢出,否者小于0后取值将会超出实际意义的范围
       if(times[1]<0) times[1]=59; //防止溢出,同上
       if(times[2]<0) times[2]=59; //防止溢出,同上
      }
      以上就是全部代码以及细节相关的注释,希望大家找出其中不足之处或者可改进的地方,与我进行交流学习。
      
      作者简介:高杨(1986—),男,河南商水人,黑龙江科技学院在读研究生。

    推荐访问:天黑 时钟 天亮 功能