时钟显示正常 怎么在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();
}
}