找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1631|回复: 2
打印 上一主题 下一主题
收起左侧

单片机智能路灯,为什么按键按下的时候,TIME没有倒计时,请求帮助

[复制链接]
跳转到指定楼层
楼主
ID:419073 发表于 2018-11-5 21:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include<reg51.h>
#include<intrins.h>  //其中有nop函数的定义

    /*对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微秒。NOP指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1uS。*/

#define uchar unsigned char
#define uint unsigned int
void set_POS(uchar);
void Lcd1602_WriteData(uchar);


        sbit BUZZER=P2^5;
        sbit key=P1^0;
    sbit RS=P2^6;  //定义数据命令选择端
    sbit RW=P2^5;  //定义读写选择端
    sbit E=P2^7;   //定义使能端
//注意:具体为哪一个IO口由你自己的接线来定,并不是一定要这样写!

    uchar text1[]="nice to meet you";   //第一行要显示的字符

    uchar data BUF1_str[16]={"                "};    //第二行要显示的字符

         uchar text2[]="watch out!";   //第二行要显示的字符
         uint sec,min,rl_sec,rl_min,cnt=0,START=0;


void delay_ms(unsigned int xms)  // xms代表需要延时的毫秒数
{
    unsigned int x,y;
    for(x=xms;x>0;x--)
        for(y=110;y>0;y--);
}
  //显示函数,在LCD上显示字符串
void display_str(uchar* str,uchar lineno)
                                        {
                                           uchar k;
                                           set_POS(lineno);
                                           for(k=0;k<16;k++)
                                          Lcd1602_WriteData(str[k]);
                                        }


    //为什么要判忙?
    /*因为LCD1602控制芯片也是一个CPU,它在处理上位机发来的某些指令的时候,耗时较长。如复位命令,全屏清除命令等。另外,LCD1602的CPU速度较慢,上位机较快时,LCD1602CPU来不及完成上条命令,会对后续命令不予理睬,这样就造成了命令序列不能正确完整地到达LCD1602CPU,以至于显示不正常。*/

uchar Lcd1602_ReadBusy()   //判断lcd1602是否处于忙的状态,即读忙
    {
       uchar temp;
       RS=0;
       RW=1;
       _nop_();
       P0=0xff;     //读某IO口数据前,先将该口置为1            

    /*原因:电路中存在的一个普遍的现象:高电平很容易被低电平拉低,而低电平一般不可能被高电平拉高。所以在读数据之前将单片机IO口拉高才不会影响原来数据线上的数据!*/

       _nop_();
       E=1;
       _nop_();
       temp=P0;   //读取此时lcd1602的状态字
       _nop_();
       E=0;
       return (temp&0x80);  //如果忙

       /*状态字为temp(8位2进制数)的最高位,最高位为1表示禁止读写,为0表示允许读写,即temp&0x80得1表示忙,得0表示不忙*/

    }          /*在lcd1602的资料中,读写操作都有对应的时序图,想要理解lcd1602的具体工作流程还得认真研究时序图!*/



void Lcd1602_Write_Com(uchar com)  //写命令函数
    {
       while(Lcd1602_ReadBusy());  //判忙
       RS=0;   //命令
       RW=0;   //写
       _nop_();
       P0=com;   //准备发送命令
       _nop_();
       E=1;      //由时序图知,使能端为高电平时才允许数据交换
       _nop_();
       _nop_();
       E=0;      //由时序图知,使能端在完成数据交换后要拉低
       _nop_();
       _nop_();   
    }

void Lcd1602_WriteData(uchar dat)  //写数据
    {
       while(Lcd1602_ReadBusy());   //判忙
       RS=1;   //数据
       RW=0;   //写
       _nop_();
       P0=dat;
       _nop_();
       E=1;
       _nop_();
       _nop_();
       E=0;
       _nop_();
       _nop_();   
    }

void Lcd1602_init()   //初始化函数
    {
       delay_ms(15);
       Lcd1602_Write_Com(0x38);   //显示模式设置
       delay_ms(5);
      Lcd1602_Write_Com(0x38);
       delay_ms(5);
       Lcd1602_Write_Com(0x38);
       Lcd1602_Write_Com(0x0c);  //显示开
       Lcd1602_Write_Com(0x01);  //显示清屏
       Lcd1602_Write_Com(0x06);  //显示光标
    }


void set_POS(uchar position)
                                {
                                        Lcd1602_Write_Com(position|0x80);
                                }
                                  //初始化定时器0
                                void inittimer0(void)
                                {
                                  TMOD=0X01;//定时器寄存器配置
                                  TH0=(65535-50000)/256;//定时50000us=50ms
                                  TL0=(65535-50000)%256;
                                  TR0=1;//启动定时器0
                                  ET0=1;
                                  EA=1;//开总中断
                                }



    void main()
    {

                     inittimer0();//初始化定时器0
                delay_ms(10);
                Lcd1602_init();//初始化LCD

                                 BUF1_str[6]='T';
                BUF1_str[7]='I';
                BUF1_str[8]='M';
                BUF1_str[9]='E';

                                min=0;sec=20;rl_min=0;rl_sec=10;
                START=1;
while(1)
{
                                uchar i,j;
                                        P2=0x00;
                                                  Lcd1602_init();
                    
                                                               
                                                 if(key==0)       
                                                 {
                                                  P2=0x01;
                                               
                                                  Lcd1602_Write_Com(0x80);   //0x80是第一行的第一个字符的地址
                               
                                                       for(i=0;i<10;i++)
                                                             
                                                          Lcd1602_WriteData(text1[i]);
                                  
                                                   BUF1_str[11]=min%100/10+'0';
                                BUF1_str[12]=min%10+'0';
                                BUF1_str[13]=':';
                                BUF1_str[14]=sec%100/10+'0';
                                BUF1_str[15]=sec%10+'0';
               
                                  display_str(BUF1_str,0x40);//第二行
                                                                    delay_ms(3000);


                                                                                 P2=0x00;
                                                                                  
                                                         Lcd1602_Write_Com(0x01);
                                                                                  delay_ms(10);
                                                 Lcd1602_Write_Com(0x80+0x40);
                                                                          for(j=0;j<10;j++)
                                                                           Lcd1602_WriteData(text2[j]);
                                                                       delay_ms(9000);                       
                               
                  }
                         
                 }

}
                                                //定时器0中断函数
                                                timer0() interrupt 1
                                                {
                                                  TR0=0;
                                                  TH0=(65535-50000)/256;//50000us=50ms
                                                  TL0=(65535-50000)%256;
                                                        if(START==1)//继电器开启倒计时开始
                                                        {
                                                    cnt++;
                                                    if(cnt>=20)//20*50ms=1s
                                                    {
                                                      cnt=0;
                                                            sec--;
                                                            if(sec==0)
                                                            {
                                                                                sec=59;
                                                                          min--;
                                                                                if(min>250)
                                                                                {
                                                                                        START=2;
                                                                                        sec=0;
                                                                                        min=0;
                                                                                        BUZZER=0;//开启蜂鸣器
                                                                                        cnt=0;
                                                                                }
                                                                  }
                                                                }
                                                  }
                                                  
                                                }




分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2018-11-6 12:03 | 只看该作者
你在加电开机后第一次发生定时器0中断时就把定时器关了,主循环中也没有再次打开定时器,你拿什么来计时?
void timer0() interrupt 1
{
        TR0=0;
        TH0=(65535-50000)/256;//50000us=50ms
        TL0=(65535-50000)%256;
        if(START==1)//继电器开启倒计时开始
        {
回复

使用道具 举报

板凳
ID:419073 发表于 2018-11-6 17:02 | 只看该作者
那我应该怎么改    求指导
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表