微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 时钟显示正常 怎么在1602上显示温度是240 温度也无变化!

时钟显示正常 怎么在1602上显示温度是240 温度也无变化!

时间:10-02 整理:3721RD 点击:

#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
unsigned char code digit[10]={"0123456789"};     //定义字符数组显示数字
void delay_main(uint z);
/*******************************************************************************
以下是对液晶模块的操作程序
*******************************************************************************/
unsigned char time;           //忙碌标志位,,将BF位定义为P0.7引脚
sbit LCD_RS = P1^0;            
sbit LCD_RW = P1^1;
sbit LCD_EN = P1^2;
sbit  BEEP = P1^4;
sbit  DENG = P1^3;
/************************************************************************************
                         使用18B20测温并用液晶1602显示
*************************************************************************************
     
************************************************************************************/

sbit DQ=P3^7;
unsigned char time;           //忙碌标志位,,将BF位定义为P0.7引脚

//sbit lcde=P2^7;
//sbit rs=P2^6;
//sbit rw=P2^5;
sbit  K1 = P3^0;
sbit  K2 = P3^1;
sbit  K3 = P3^2;
sbit  K4 = P3^3;
sbit  B1 = P2^0;
sbit  B2 = P2^1;
sbit  B3 = P2^2;
sbit  B4 = P2^4;
sbit  BEIDENG=P2^3;


sbit reset = P1^7;
sbit sclk  = P1^5;
sbit io    = P1^6;
//sbit SCK=P3^6;        //时钟        
//sbit SDA=P3^4;        //数据        
//sbit RST=P3^5;// DS1302复位

bit flag=1,hour=0,min=0,sec=0;
bit year=0,month=0,day=0,week=0;
bit alarm_flag=0;
uchar  timecount=0,count=0;
uchar str1[]="  -  -   Week:  ";
uchar str2[]="               ";
uchar init [] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00};  //
uchar init1[] ={0x00,0x00};
uchar init2[] ={0x00,0x59,0x23,0x01,0x05,0x01,0x06}; //
               //秒, 分, 时, 日, 月,星期,年
uchar bj_time[] ={0x00,0x57,0x22};
                 //秒, 分, 时
uchar code  mytab[8] = {0x00,0x00,0x0E,0x04,0x0A,0xFF,0x00,0x00};//小灯        //显示右下角开灯图标
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
void  Set_W1302(uchar addr);
void  Set_Flash(uchar row,uchar col);
void  Set_place(uchar row,uchar col);
void  Play_nowtime();
void  key_set(uchar num,uchar row,uchar col );
void  alarm_time();
void  Play_alarmtime();
void  Time_compare();
/******************************************************************/
/******************************************************************/
void delay1(int ms)
{
unsigned char y;
  while(ms--)
{
  for(y = 0; y<250; y++)
  {
   
   _nop_();
   _nop_();
   _nop_();
   _nop_();
  }
}
}
/******************************************************************/
/*                                                                */
/*检查LCD忙状态                                                   */
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。     */
/*                                                                */
/******************************************************************/
bit lcd_busy()
{                          
    bit result;
    LCD_RS = 0;
    LCD_RW = 1;
    LCD_EN = 1;
    delayNOP();
    result = (bit)(P0&0x80);
    LCD_EN = 0;
    return(result);
}
/*********************************************************/
/*                                                       */
/*写指令数据到LCD                                        */
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。                   */
/*                                                       */
/*********************************************************/
void lcd_wcmd(uchar cmd)
{                          
   while(lcd_busy());
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_EN = 0;
    _nop_();
    _nop_();
    P0 = cmd;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;  
}
/*********************************************************/
/*                                                       */
/*写显示数据到LCD                                        */
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。                     */
/*                                                       */
/*********************************************************/
void lcd_wdat(uchar dat)
{                          
   while(lcd_busy());
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_EN = 0;
    P0 = dat;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;
}
/*********************************************************/
/*                                                       */
/*  LCD初始化设定                                        */
/*                                                       */
/*********************************************************/
void init_lcd()
{
    delay1(15);   
    lcd_wcmd(0x01);      //清除LCD的显示内容
            
    lcd_wcmd(0x38);      //16*2显示,5*7点阵,8位数据
    delay1(5);
    lcd_wcmd(0x38);         
    delay1(5);
    lcd_wcmd(0x38);         
    delay1(5);
    lcd_wcmd(0x0c);      //显示开,关光标
    delay1(5);
    lcd_wcmd(0x06);      //移动光标
    delay1(5);
    lcd_wcmd(0x01);      //清除LCD的显示内容
    delay1(5);
}
/*********************************************************/
//
/*********************************************************/
void delay()
{
   uchar j;
   for(j=250;j>0;j--);
}
/*********************************************************/
/*                                                       */
/*  写字符串函数                                         */
/*                                                       */
/*********************************************************/
void write_str(uchar addr,uchar *p)
{
   uchar i=0;
   lcd_wcmd(addr);
   while(p!='\0')
   {
    lcd_wdat(p);
    i++;
   }
}
/*********************************************************/
/*                                                       */
/*  设定显示位置                                         */
/*                                                       */
/*********************************************************/
void write_position(uchar row,uchar col)
{
   uchar place;
   if(row==1)
   {
     place=0x80+col-1;
     lcd_wcmd(place);
   }
   else
   {
     place=0xc0+col-1;
     lcd_wcmd(place);
   }
}
/*********************************************************/
/*                                                       */
/*自定义字符写入CGRAM                                    */
/*                                                       */
/*********************************************************/
void  writetab()  
{  
    unsigned char i;
    lcd_wcmd(0x40);            //写CGRAM
    for (i = 0; i< 16; i++)      
    lcd_wdat(mytab);        
}
/**********************************************************/
//
/**********************************************************/
void write_byte(uchar inbyte)
{
   uchar i;
   for(i=0;i<8;i++)
   {
    sclk=0;             //写的时候低电平改变数据
    if(inbyte&0x01)
    io=1;
    else
    io=0;
    sclk=1;            //写的时候高电平,把数据写入ds1302
    _nop_();
    inbyte=inbyte>>1;
   }
}
/**********************************************************/
/**********************************************************/
uchar read_byte()    //sclk的下跳沿读数据
{
   uchar i,temp=0;
   io=1;                //设置为输入口
   for(i=0;i<7;i++)
   {
    sclk=0;
    if(io==1)
    temp=temp|0x80;
    else
    temp=temp&0x7f;
    sclk=1;             //产生下跳沿
   
    temp=temp>>1;
   }
   return (temp);
}
/**********************************************************/
// 往ds1302的某个地址写入数据
/**********************************************************/
void write_ds1302(uchar cmd,uchar indata)
{
   sclk=0;
   reset=1;
   write_byte(cmd);        
   write_byte(indata);
   
   sclk=0;
   reset=0;
}
/**********************************************************/
// 读ds1302某地址的的数据
/**********************************************************/
uchar read_ds1302(uchar addr)
{
   uchar backdata;
   sclk=0;
   reset=1;
   write_byte(addr);      //先写地址
   backdata=read_byte();  //然后读数据
  
   sclk=0;
   reset=0;
   return (backdata);
}
/**********************************************************/
// 设置初始时间
/**********************************************************/
void set_ds1302(uchar addr,uchar *p,uchar n) //写入n个数据
{
   write_ds1302(0x8e,0x00);          //写控制字,允许写操作
   for(;n>0;n--)
   {
   write_ds1302(addr,*p);
   p++;
   addr=addr+2;
   }
   write_ds1302(0x8e,0x80);          //写保护,不允许写
}
/**********************************************************/
// 读取当前时间
/**********************************************************/
void read_nowtime(uchar addr,uchar *p,uchar n)
{
  for(;n>0;n--)
  {
    *p=read_ds1302(addr);
    p++;
    addr=addr+2;
  }
}
/**********************************************************/
// 初始化DS1302
/**********************************************************/
void init_ds1302()
{
   reset=0;
   sclk=0;
   write_ds1302(0x80,0x00);
   write_ds1302(0x90,0xa8); //一个二极管+4K电阻充电
   write_ds1302(0x8e,0x80); //写保护控制字,禁止写
}
/**********************************************************/
/*                                                        */
/* 蜂鸣器响一声                                           */
/*                                                        */
/**********************************************************/

void beep()
  {
}
/*
********************************************************************************
** 函数名称 : delay(uint z)
** 函数功能 : 延时函数
********************************************************************************
*/
void delay_main(uint z)//-----------------主延时函数1毫秒
{ uint x,y; for(x=z;x>0;x--)
   for(y=100;y>0;y--);
  }
  
/**********************************************************/
/*                                                        */
/* :闪动函数                                          */
/*                                                        */
/**********************************************************/
void  flash()
{
   if(flag)
    {
      write_position(2,3);
      lcd_wdat(':');
      write_position(2,6);
      lcd_wdat(':');     
    }
    else
    {
      write_position(2,3);
      lcd_wdat(0x20);
      write_position(2,6);
      lcd_wdat(0x20);     
    }
}

/**********************************************************/
// Time0中断函数
/**********************************************************/
void Time0(void) interrupt 1 using 0
{
  TH0=0x4c; //50ms定时
  TL0=0x00;
  timecount++;
  if(timecount>9)
   {
    timecount=0;   
    flag=~flag;            
   }  
}
/**********************************************************/
// 设定值写入DS1302
/**********************************************************/
void  Set_W1302(uchar addr)
{
   uchar  temp;
   write_ds1302(0x8e,0x00);
   temp=(init1[0]<<4)+init1[1];
   write_ds1302(addr,temp);
   write_ds1302(0x8e,0x80);
   beep();
}

/**********************************************************/
// 指定位置显示
/**********************************************************/
void  Set_place(uchar row,uchar col)
{
    write_position(row,col);
    lcd_wdat(init1[0]+0x30);
    write_position(row,col+1);
    lcd_wdat(init1[1]+0x30);
}
/**********************************************************/
// 显示当前时间
/**********************************************************/
void  Play_nowtime()
{
    read_nowtime(0x81,init,7);   //读出当前时间,读出7个字节
    write_position(2,1);
    lcd_wdat(((init[2]&0xf0)>>4)+0x30);
    write_position(2,2);
    lcd_wdat('0'+(init[2]&0x0f)); //读小时
   // write_position(2,3);
   // lcd_wdat(':');
    write_position(2,4);
    lcd_wdat('0'+((init[1]&0xf0)>>4));
    write_position(2,5);
    lcd_wdat('0'+(init[1]&0x0f)); //读分钟
//    write_position(2,6);
//    lcd_wdat(':');
    write_position(2,7);
    lcd_wdat('0'+((init[0]&0xf0)>>4));
    write_position(2,8);
    lcd_wdat('0'+(init[0]&0x0f)); //读秒
    write_position(1,1);
    lcd_wdat('0'+((init[6]&0xf0)>>4));
    write_position(1,2);
    lcd_wdat('0'+(init[6]&0x0f)); //读年
//    write_position(1,3);
//    lcd_wdat('/');
    write_position(1,4);
    lcd_wdat('0'+((init[4]&0xf0)>>4));
    write_position(1,5);
    lcd_wdat('0'+(init[4]&0x0f)); //读月
//    write_position(1,6);
//    lcd_wdat('/');
    write_position(1,7);
    lcd_wdat('0'+((init[3]&0xf0)>>4));
    write_position(1,8);
    lcd_wdat('0'+(init[3]&0x0f)); //读日
    write_position(1,15);
    lcd_wdat('0'+(init[5]&0x0f)); //读周
    flash();
}

/*********************************************************/
// 时间比较
/*********************************************************/
void  Time_compare()
{
//第一次喂食时间
    if(init[2]==0x06)          //如果时间是 06点
                   {
                           if(init[1]==0x10)      // 如果时间是 10分
                                    {
                                        if (init[0]==0x00)    // 如果时间是 00秒
                                                {
                                                         BEEP=0;                      // 开启电机喂食
                                                         BEIDENG=0;
                                                
                                                
                                                }
                                   }
                 }
   
        if(init[2]==0x06)          // 如果时间是 06点
                   {
                           if(init[1]==0x10)          // 如果时间是 10分
                            {
                                        if (init[0]==0x10)          // 如果时间是 10秒
                                                {
                                                     BEEP=1;                      //关闭电机停止喂食
                                                  BEIDENG=1;
                                                
                                                }
                                   }
                   }
//第二次喂食时间
//开始喂食
    if(init[2]==0x17)          //如果时间是 17点
                   {        
                           if(init[1]==0x00)      // 如果时间是 26分
                            {
                                        if (init[0]==0x00)    // 如果时间是 00秒
                                                {
                                                         BEEP=0;                      // 开启电机喂食
                                                         BEIDENG=0;
                                                
                                                }
                               }
                 }
//停止喂食         
         if(init[2]==0x17)          // 如果时间是 17点
                   {
                           if(init[1]==0x00)          // 如果时间是 26分
                            {
                                        if (init[0]==0x10)          // 如果时间是 10秒
                                                {
                                                     BEEP=1;                      //关闭电机停止喂食
                                                  BEIDENG=1;
                                                }
                                   }
                 }

//开鱼缸灯时间
//开灯
    if(init[2]==0x17)          //如果时间是 17点
                   {
                           if(init[1]==0x30)      // 如果时间是 30分
                                   {
                                        if (init[0]==0x00)    // 如果时间是 00秒
                                                {
                                                         DENG=0;                      // 开灯
                                                        BEIDENG=0;
                                                        write_position(2,16); lcd_wdat(0x20);
                                                }
                                }
                 }
    if(init[2]==0x22)          // 如果时间是 22点
                   {
                           if(init[1]==0x30)          // 如果时间是 30分
                            {
                                        if (init[0]==0x00)          // 如果时间是 00秒
                                                {
                                                     DENG=1;                      //关灯
                                                        BEIDENG=1;
                                                        write_position(2,16); lcd_wdat(0x00);
                                         
                                                }
                                   }
           }
   }


















/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒
***************************************************/
void delay1ms()
{
   unsigned char i,j;
for(i=0;i<4;i++)
   for(j=0;j<33;j++)
    ;   
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
void delaynms(unsigned char n)
{
   unsigned char i;
for(i=0;i<n;i++)
    delay1ms();
}
/************************************************************************
以下是DS18B20的操作程序
************************************************************************/
//设置全局变量,专门用于严格延时
/*****************************************************
函数功能:将DS18B20传感器初始化,读取应答信号
出口参数:flag
***************************************************/
bit Init_DS18B20(void)
{
bit flag;         //储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在
DQ = 1;           //先将数据线拉高
for(time=0;time<2;time++) //略微延时约6微秒
     ;
DQ = 0;           //再将数据线从高拉低,要求保持480~960us
for(time=0;time<200;time++) //略微延时约600微秒
     ;         //以向DS18B20发出一持续480~960us的低电平复位脉冲
DQ = 1;           //释放数据线(将数据线拉高)
for(time=0;time<10;time++)
     ; //延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)
flag=DQ;          //让单片机检测是否输出了存在脉冲(DQ=0表示存在)      
for(time=0;time<200;time++) //延时足够长时间,等待存在脉冲输出完毕
      ;
return (flag);    //返回检测成功标志
}
/*****************************************************
函数功能:从DS18B20读取一个字节数据
出口参数:dat
***************************************************/
unsigned char ReadOneChar(void)
{
   unsigned char i=0;
   unsigned char dat; //储存读出的一个字节数据
   for (i=0;i<8;i++)
   {
     
     DQ =1;       // 先将数据线拉高
     _nop_();     //等待一个机器周期
     DQ = 0;      //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序
    dat>>=1;
     _nop_();     //等待一个机器周期     
     DQ = 1;     //将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备
     for(time=0;time<2;time++)
             ;      //延时约6us,使主机在15us内采样
     if(DQ==1)
        dat|=0x80; //如果读到的数据是1,则将1存入dat
    else
     dat|=0x00;//如果读到的数据是0,则将0存入dat
       //将单片机检测到的电平信号DQ存入r
     for(time=0;time<8;time++)
        ;              //延时3us,两个读时序之间必须有大于1us的恢复期
     }                     
return(dat);    //返回读出的十进制数据
}
/*****************************************************
函数功能:向DS18B20写入一个字节数据
入口参数:dat
***************************************************/
WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=0; i<8; i++)
   {
    DQ =1;         // 先将数据线拉高
    _nop_();      //等待一个机器周期
    DQ=0;          //将数据线从高拉低时即启动写时序      
    DQ=dat&0x01;   //利用与运算取出要写的某位二进制数据,
                       //并将其送到数据线上等待DS18B20采样
   for(time=0;time<10;time++)
       ;//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样
    DQ=1;          //释放数据线      
    for(time=0;time<1;time++)
     ;//延时3us,两个写时序间至少需要1us的恢复期
    dat>>=1;       //将dat中的各二进制位数据右移1位
   }
   for(time=0;time<4;time++)
               ; //稍作延时,给硬件一点反应时间
}
/*****************************************************
函数功能:显示温度的整数部分
入口参数:x
***************************************************/
void display_temp1(unsigned char x)
{
unsigned char j,k,l;     //j,k,l分别储存温度的百位、十位和个位
j=x/100;              //取百位
k=(x%100)/10;    //取十位
l=x%10;             //取个位
//写显示地址,将在第2行第7列开始显示
write_position(2,12); lcd_wdat(digit[j]);
write_position(2,13); lcd_wdat(digit[k]);
write_position(2,14); lcd_wdat(digit[l]);
delay1(50);           //延时1ms给硬件一点反应时间     
}

/*****************************************************
函数功能:显示温度的小数点
***************************************************/   
void display_dot(void)
{         
write_position(2,15); lcd_wdat('.');
delaynms(50);         //延时1ms给硬件一点反应时间  
}
/*****************************************************
函数功能:显示温度的小数数部分
入口参数:x
***************************************************/
void display_temP3(unsigned char x)
{
   write_position(2,16); lcd_wdat(digit[x]);
delay1(50);          //延时1ms给硬件一点反应时间
}
/*****************************************************
函数功能:做好读温度的准备
***************************************************/
void ReadyReadTemp(void)
{
      Init_DS18B20();     //将DS18B20初始化
   WriteOneChar(0xCC); // 跳过读序号列号的操作
   WriteOneChar(0x44); // 启动温度转换   
    for(time=0;time<100;time++)
             ; //温度转换需要一点时间
   Init_DS18B20();     //将DS18B20初始化
   WriteOneChar(0xCC); //跳过读序号列号的操作
   WriteOneChar(0xBE); //读取温度寄存器,前两个分别是温度的低位和高位
}

  /**********************************************************/
// 主函数
/**********************************************************/
void main()
{
    unsigned char TL11;     //储存暂存器的温度低位
     unsigned char TH11;    //储存暂存器的温度高位
     unsigned char TN11;      //储存温度的整数部分
   unsigned char TD11;       //储存温度的小数部分
   
   
   
   
   BEEP=1;
   DENG=1;
   BEIDENG=0;
   TMOD=0x01;
   TH0=0x4c;          //50ms定时
   TL0=0x00;
   EA=1;
   ET0=1;  
   TR0=1;
   init_lcd();                 //初始化LCD
   write_str(0x80,str1);       //液晶显示提示信息
   write_str(0xc0,str2);       //液晶显示提示信息
   init_ds1302();              //初始化ds1302
   writetab();               //自定义字符写入CGRAM
//   delay1(5);
//   write_position(2,16);
//   lcd_wdat(0x00);           //显示自定义字符小喇叭
   
   while(1)
   {
//---------------------------------------------------------
    if(B1==0&BEEP==1)  //手动喂食
        {  
                BEEP=0;
                BEIDENG=0;
                delay1(3000);
                BEEP=1;
                BEIDENG=1;
        
        }
   if(B2==0&DENG==1)  //手动开灯
   
   {DENG=0;BEIDENG=0;write_position(2,16); lcd_wdat(0x00);delay1(200);}
           
   if(B2==0&DENG==0)  //手动关灯
   
   {DENG=1;BEIDENG=0;write_position(2,16); lcd_wdat(0x20); delay1(200);}      
   
   kll:
   if(B3==0&BEIDENG==1)  //手动开背灯
   
   {BEIDENG=0;delay1(200);}
           
   if(B3==0&BEIDENG==0)  //手动关背灯
   
   {BEIDENG=1;delay1(200);}      
   
   klle:
        
        Play_nowtime();
           ReadyReadTemp();     //读温度准备
         if(Init_DS18B20()==1)
   //  display_error();
   //display_explain();
   //display_symbol();    //显示温度说明
        //显示温度的小数点
   //   display_cent();      //显示温度的单位
   
    TL11=ReadOneChar();    //先读的是温度值低位
   TH11=ReadOneChar();    //接着读的是温度值高位
   TN11=TH11*16+TL11/16;      //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16
                     //这样得出的是温度的整数部分,小数部分被丢弃了
   TD11=(TL11%16)*10/16;    //计算温度的小数部分,将余数乘以10再除以16取整,
                            //这样得到的是温度小数部分的第一位数字(保留1位小数)
  
      delaynms(10);               
          display_temp1(TN11);    //显示温度的整数部分
    display_dot();   
        display_temP3(TD11);    //显示温度的小数部分
        Time_compare();
   }
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top