
#include<graphics.h>
#include<stdio.h>
#include<math.h>
#include<dos.h>
#define PI 3.1415926 /*定义常量*/
#define UP 0x4800 /*上移↑键:修改时间*/
#define DOWN 0x5000 /*下移↓键:修改时间*/
#define ESC 0x11b /*ESC键 : 退出系统*/
#define TAB 0xf09 /*TAB键 : 移动光标*/
/*函数声明*/
int keyhandle(int,int)/*键盘按键判断,并调用相关函数处理*/
int timeupchange(int) /*处理上移按键*/
int timedownchange(int)/*处理下移按键*/
int digithour(double)/*将double型的小时数转换成int型*/
int digitmin(double) /*将double型的分钟数转换成int型*/
int digitsec(double) /*将double型的秒钟数转换成int型*/
void digitclock(int,int,int )/*在指定位置显示时钟或分钟或秒钟数*/
void drawcursor(int)/*绘制一个光标*/
void clearcursor(int)/*消除前一个光标*/
void clockhandle()/*时钟处理*/
double h,m,s/*全局变量:小时,分,秒*/
double x,x1,x2,y,y1,y2/*全局变量:坐标值*/
struct time t[1]/*定义一个time结构类型的数组*/
main()
{
int driver, mode=0,i,j
driver=DETECT/*自动检测显示设备*/
initgraph(&driver, &mode, "")/*初始化图形系统*/
setlinestyle(0,0,3)/*设置当前画线宽度和类型:设置三点宽实线*/
setbkcolor(0)/*用调色板设置当前背景颜色*/
setcolor(9)/*设置当前画线颜色*/
line(82,430,558,430)
line(70,62,70,418)
line(82,50,558,50)
line(570,62,570,418)
line(70,62,570,62)
line(76,56,297,56)
line(340,56,564,56) /*画主体框架的边直线*/
/*arc(int x, int y, int stangle, int endangle, int radius)*/
arc(82,62,90,180,12)
arc(558,62,0,90,12)
setlinestyle(0,0,3)
arc(82,418,180,279,12)
setlinestyle(0,0,3)
arc(558,418,270,360,12) /*画主体框架的边角弧线*/
setcolor(15)
outtextxy(300,53,"CLOCK")/*显示标题*/
setcolor(7)
rectangle(342,72,560,360)/*画一个矩形,作为时钟的框架*/
setwritemode(0)/*规定画线的方式。mode=0, 则表示画线时将所画位置的原来信息覆盖*/
setcolor(15)
outtextxy(433,75,"CLOCK")/*时钟的标题*/
setcolor(7)
line(392,310,510,310)
line(392,330,510,330)
arc(392,320,90,270,10)
arc(510,320,270,90,10)/*绘制电子动画时钟下的数字时钟的边框架*/
/*绘制数字时钟的时分秒的分隔符*/
setcolor(5)
for(i=431i<=470i+=39)
for(j=317j<=324j+=7){
setlinestyle(0,0,3)
circle(i,j,1)/*以(i, y)为圆心,1为半径画圆*/
}
setcolor(15)
line(424,315,424,325)/*在运行电子时钟前先画一个光标*/
/*绘制表示小时的圆点*/
for(i=0,m=0,h=0i<=11i++,h++){
x=100*sin((h*60+m)/360*PI)+451
y=200-100*cos((h*60+m)/360*PI)
setlinestyle(0,0,3)
circle(x,y,1)
}
/*绘制表示分钟或秒钟的圆点*/
for(i=0,m=0i<=59m++,i++){
x=100*sin(m/30*PI)+451
y=200-100*cos(m/30*PI)
setlinestyle(0,0,1)
circle(x,y,1)
}
/*在电子表的左边打印帮助提示信息*/
setcolor(4)
outtextxy(184,125,"HELP")
setcolor(15)
outtextxy(182,125,"HELP")
setcolor(5)
outtextxy(140,185,"TAB : Cursor move")
outtextxy(140,225,"UP : Time ++")
outtextxy(140,265,"DOWN: Time --")
outtextxy(140,305,"ESC : Quit system!")
outtextxy(140,345,"Version : 2.0")
setcolor(12)
outtextxy(150,400,"Nothing is more important than time!")
clockhandle()/*开始调用时钟处理程序*/
closegraph()/*关闭图形系统*/
return 0/*表示程序正常结束,向 *** 作系统返回一个0值*/
}
void clockhandle()
{
int k=0,count
setcolor(15)
gettime(t)/*取得系统时间,保存在time结构类型的数组变量中*/
h=t[0].ti_hour
m=t[0].ti_min
x=50*sin((h*60+m)/360*PI)+451/*时针的x坐标值*/
y=200-50*cos((h*60+m)/360*PI)/*时针的y坐标值*/
line(451,200,x,y)/*在电子表中绘制时针*/
x1=80*sin(m/30*PI)+451/*分针的x坐标值*/
y1=200-80*cos(m/30*PI)/*分针的y坐标值*/
line(451,200,x1,y1)/*在电子表中绘制分针*/
digitclock(408,318,digithour(h))/*在数字时钟中,显示当前的小时值*/
digitclock(446,318,digitmin(m))/*在数字时钟中,显示当前的分钟值*/
setwritemode(1)
/*规定画线的方式,如果mode=1,则表示画线时用现在特性的线
与所画之处原有的线进行异或(XOR) *** 作,实际上画出的线是原有线与现在规定
的线进行异或后的结果。因此, 当线的特性不变, 进行两次画线 *** 作相当于没有
画线,即在当前位置处清除了原来的画线*/
for(count=2k!=ESC){ /*开始循环,直至用户按下ESC键结束循环*/
setcolor(12)/*淡红色*/
sound(500)/*以指定频率打开PC扬声器,这里频率为500Hz*/
delay(700)/*发一个频率为500Hz的音调,维持700毫秒*/
sound(200)/*以指定频率打开PC扬声器,这里频率为200Hz*/
delay(300)
/*以上两种不同频率的音调,可仿真钟表转动时的嘀哒声*/
nosound()/*关闭PC扬声器*/
s=t[0].ti_sec
m=t[0].ti_min
h=t[0].ti_hour
x2=98*sin(s/30*PI)+451/*秒针的x坐标值*/
y2=200-98*cos(s/30*PI)/*秒针的y坐标值*/
line(451,200,x2,y2)
/*绘制秒针*/
/*利用此循环,延时一秒*/
while(t[0].ti_sec==s&&t[0].ti_min==m&&t[0].ti_hour==h)
{ gettime(t)/*取得系统时间*/
if(bioskey(1)!=0){
k=bioskey(0)
count=keyhandle(k,count)
if(count==5) count=1
}
}
setcolor(15)
digitclock(485,318,digitsec(s)+1)/*数字时钟增加1秒*/
setcolor(12)/*淡红色*/
x2=98*sin(s/30*PI)+451
y2=200-98*cos(s/30*PI)
line(451,200,x2,y2)
/*用原来的颜色在原来位置处再绘制秒针,以达到清除当前秒针的目的*/
/*分钟处理*/
if(t[0].ti_min!=m){ /*若分钟有变化*/
/*消除当前分针*/
setcolor(15)/*白色*/
x1=80*sin(m/30*PI)+451
y1=200-80*cos(m/30*PI)
line(451,200,x1,y1)
/*绘制新的分针*/
m=t[0].ti_min
digitclock(446,318,digitmin(m))/*在数字时钟中显示新的分钟值*/
x1=80*sin(m/30*PI)+451
y1=200-80*cos(m/30*PI)
line(451,200,x1,y1)
}
/*小时处理*/
if((t[0].ti_hour*60+t[0].ti_min)!=(h*60+m)){ /*若小时数有变化*/
/*消除当前时针*/
setcolor(15)/*白色*/
x=50*sin((h*60+m)/360*PI)+451/*50:时钟的长度(单位:像素),451:圆心的x坐标值*/
y=200-50*cos((h*60+m)/360*PI)
line(451,200,x,y)
/*绘制新的时针*/
h=t[0].ti_hour
digitclock(408,318,digithour(h))
x=50*sin((h*60+m)/360*PI)+451
y=200-50*cos((h*60+m)/360*PI)
line(451,200,x,y)
}
}
}
int keyhandle(int key,int count) /*键盘控制 */
{ switch(key)
{case UP: timeupchange(count-1)/*因为count的初始值为2,所以此处减1*/<br> break<br> case DOWN:timedownchange(count-1)/*因为count的初始值为2,所以此处减1*/<br>break<br> case TAB:setcolor(15)<br> clearcursor(count)/*清除原来的光标*/<br> drawcursor(count) /*显示一个新的光标*/<br> count++<br> break<br> }
return count
}
int timeupchange(int count) /*处理光标上移的按键*/
{
if(count==1){
t[0].ti_hour++
if(t[0].ti_hour==24) t[0].ti_hour=0
settime(t)/*设置新的系统时间*/
}
if(count==2){
t[0].ti_min++
if(t[0].ti_min==60) t[0].ti_min=0
settime(t)/*设置新的系统时间*/
}
if(count==3){
t[0].ti_sec++
if(t[0].ti_sec==60) t[0].ti_sec=0
settime(t)/*设置新的系统时间*/
}
}
int timedownchange(int count) /*处理光标下移的按键*/
{
if(count==1) {
t[0].ti_hour--
if(t[0].ti_hour==0) t[0].ti_hour=23
settime(t)/*设置新的系统时间*/
}
if(count==2) {
t[0].ti_min--
if(t[0].ti_min==0) t[0].ti_min=59
settime(t)/*设置新的系统时间*/
}
if(count==3) {
t[0].ti_sec--
if(t[0].ti_sec==0) t[0].ti_sec=59
settime(t)/*设置新的系统时间*/
}
}
int digithour(double h)/*将double型的小时数转换成int型*/
{int i<br>for(i=0i<=23i++)<br> {if(h==i) return i}
}
int digitmin(double m)/*将double型的分钟数转换成int型*/
{int i<br>for(i=0i<=59i++)<br> {if(m==i) return i}
}
int digitsec(double s) /*将double型的秒钟数转换成int型*/
{int i<br>for(i=0i<=59i++)<br> {if(s==i) return i}
}
void digitclock(int x,int y,int clock)/*在指定位置显示数字时钟:时\分\秒*/
{char buffer1[10]<br>setfillstyle(0,2)<br>bar(x,y,x+15,328)<br>if(clock==60) clock=0<br>sprintf(buffer1,"%d",clock)<br>outtextxy(x,y,buffer1)<br>}
void drawcursor(int count)/*根据count的值,画一个光标*/
{switch(count)<br>{<br> case 1:line(424,315,424,325)break<br> case 2:line(465,315,465,325)break<br> case 3:line(505,315,505,325)break<br> }
}
void clearcursor(int count)/*根据count的值,清除前一个光标*/
{switch(count)<br>{<br> case 2:line(424,315,424,325)break<br> case 3:line(465,315,465,325)break<br> case 1:line(505,315,505,325)break<br> }
}
/***********ds18b20子程序*************************//***********ds18b20延迟子函数(晶振12MHz )*******/
#include<reg51.h>
sbit DQ=P1^2
#define uchar unsigned char
void delay_18B20(unsigned int i)
{
while(i--)
}
/**********ds18b20初始化函数**********************/
void Init_DS18B20(void)
{
unsigned char x=0
DQ = 1 //DQ复位
delay_18B20(8) //稍做延时
DQ = 0 //单片机将DQ拉低
delay_18B20(80)//精确延时 大于 480us
DQ = 1 //拉高总线
delay_18B20(4)
x=DQ //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay_18B20(20)
}
/***********ds18b20读一个字节**************/
unsigned char ReadOneChar(void)
{
uchar i=0
uchar dat = 0
for (i=8i>0i--)
{
DQ = 0// 给脉冲信号
dat>>=1
DQ = 1// 给脉冲信号
if(DQ)
dat|=0x80
delay_18B20(4)
}
return(dat)
}
/*************ds18b20写一个字节****************/
void WriteOneChar(uchar dat)
{
unsigned char i=0
for (i=8i>0i--)
{
DQ = 0
DQ = dat&0x01
delay_18B20(5)
DQ = 1
dat>>=1
}
}
/**************读取ds18b20当前温度************/
ReadTemp(void)
{ float val
uchar temp_value,value
unsigned char a=0
unsigned char b=0
unsigned char t=0
Init_DS18B20()
WriteOneChar(0xCC) // 跳过读序号列号的 *** 作
WriteOneChar(0x44) // 启动温度转换
delay_18B20(100) // this message is wery important
Init_DS18B20()
WriteOneChar(0xCC) //跳过读序号列号的 *** 作
WriteOneChar(0xBE) //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
delay_18B20(100)
a=ReadOneChar() //读取温度值低位
b=ReadOneChar() //读取温度值高位
temp_value=b<<4
temp_value+=(a&0xf0)>>4
value=a&0x0f
val=temp_value+value
return(val)
}
以上是DS18B20的驱动程序。然后在主程序中直接调用函数就可以了。
以上是在主程序中的调用,你看关于温度的那个就可以。
#include "reg51.h"
#include "18b20.h"
#define uchar unsigned char
#define uint unsigned int
uchar code table[]="Welcome To" //初始化日期和星期
uchar code table1[]="Our System!"//初始化时间
uchar code table2[]="Temperature is:"//初始化时间
//以下三个是定义LCD的引脚
sbit lcden=P2^2
sbit lcdwrite=P2^1
sbit lcdrs=P2^0
char wendu
//延时程序
void delay(uint z)
{ uint x,y
for(x=zx>0x--)
for(y=110y>0y--)
}
//lcd的写指令
void write_com(uchar com)
{
lcdrs=0
lcden=0
P0=com
delay(5)
lcden=1
delay(5)
lcden=0
}
//lcd的写数据
void write_data(uchar da)
{ lcdrs=1
lcden=0
P0=da
delay(5)
lcden=1
delay(5)
lcden=0
}
//初始化
void init()
{
uchar num
lcdwrite=0
lcden=0
write_com(0x38)//16*2显示,5*7点阵,8位数据
write_com(0x0c)//显示开,关光标
write_com(0x06)//移动光标
write_com(0x01)//清除LCD的显示内容
write_com(0x80)
for (num=0num<10num++)
{
write_data(table[num])
delay(5)
}
write_com(0x80+0x40)
for (num=0num<11num++)
{
write_data(table1[num])
delay(5)
}
}
void write_wendu(uchar add, char da)
{
uchar shi,ge
shi=da/10
ge=da%10
write_com(0x80+0x40+add)
write_data(0x30+shi)
write_data(0x30+ge)
}
//主函数
void main ()
{
uchar num
init()
delay(2000)
delay(2000)
delay(2000)
write_com(0x01)//清除LCD的显示内容
while(1)
{
write_com(0x80)
for (num=0num<15num++)
{
write_data(table2[num])
delay(5)
}
wendu = ReadTemp( )
write_wendu(2,wendu)
}
}
//------------------------------------------------------------------//DS18B20温度传感器输出显示,运行本例时,外界温度将显示在1602LCD上
//------------------------------------------------------------------
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP() {_nop_()_nop_()_nop_()_nop_()}
sbit DQ=P2^2
sbit dula=P2^6//定义锁存器锁存端
sbit wela=P2^7
sbit rs=P3^5 //定义1602液晶RS端
sbit lcden=P3^4//定义1602液晶LCDEN端
sbit s1=P3^0 //定义按键--功能键
sbit s2=P3^1//定义按键--增加键
sbit s3=P3^2//定义按键--减小键
sbit s4=P3^6//闹钟查看键
sbit rd=P3^7
sbit beep=P2^3//定义蜂鸣器端
uchar code Temp_Disp_Title[]={" Current Temp : "}
uchar Current_Temp_Display_Buffer[]={" TEMP: "}
uchar code Alarm_Temp[]={"ALARM TEMP Hi Lo"}
uchar Alarm_HI_LO_STR[]={"Hi:Lo:"}
uchar temp_data[2]={0x00,0x00}
uchar temp_alarm[2]={0x00,0x00}
uchar display[5]={0x00,0x00,0x00,0x00,0x00}
uchar display1[3]={0x00,0x00,0x00}
uchar code df_Table[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9}
uchar CurrentT=0//当前读取的温度整数部分
uchar Temp_Value[]={0x00,0x00}//从DS18B20读取的温度值
uchar Display_Digit[]={0,0,0,0} //待显示的各温度数位
bit DS18B20_IS_OK=1//传感器正常标志
//-------------------------------------
//延时1
//-------------------------------------
void delay1(uint x)
{
uchar i
while(x--) for(i=0i<200i++)
}
//-------------------------------------
//延时2
//-------------------------------------
void Delay(uint x)
{
while(x--)
}
//------------------------------------
//忙检查
//------------------------------------
void write_com(uchar com)//液晶写命令函数
{
rs=0
lcden=0
P0=com
delay1(5)
lcden=1
delay1(5)
lcden=0
}
void Write_LCD_Data(uchar date)//液晶写数据函数
{
rs=1
lcden=0
P0=date
delay1(5)
lcden=1
delay1(5)
lcden=0
}
//-----------------------------
//设置LCD显示位置
//---------------------------------
void Set_Disp_Pos(uchar Pos)
{
write_com(Pos|0x80)
}
//-----------------------------
//LCD初始化
//---------------------------------
void Initialize_LCD()
{
uchar num
rd=0 //软件将矩阵按键第4列一端置低用以分解出独立按键
dula=0//关闭两锁存器锁存端,防止 *** 作液晶时数码管会出乱码
wela=0
lcden=0
write_com(0x38)//初始化1602液晶
write_com(0x0c)
write_com(0x06)
write_com(0x01)
write_com(0x80)//设置显示初始坐标
for(num=0num<14num++)//显示年月日星期
{
Write_LCD_Data(Temp_Disp_Title[num])
delay1(5)
}
}
//-------------------------------------
//函数功能:初始化DS18B20
//出口参数:status---DS18B20是否复位成功的标志
//-------------------------------------
uchar Init_DS18B20()
{
uchar status //储存DS18B20是否存在的标志,status=0,表示存在;status=1,表示不存在
DQ=1Delay(8) //先将数据线拉高 //略微延时约6微秒
DQ=0Delay(90) //再将数据线从高拉低,要求保持480~960us
//略微延时约600微秒 以向DS18B20发出一持续480~960us的低电平复位脉冲
DQ=1Delay(8) //释放数据线(将数据线拉高) //延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)
status=DQDelay(100) //让单片机检测是否输出了存在脉冲(DQ=0表示存在) //延时足够长时间,等待存在脉冲输出完毕
DQ=1 // 将数据线拉高
return status//返回检测成功标志
}
//-------------------------------------
//函数功能:读一字节
//出口参数:dat---读出的数据
//-------------------------------------
uchar ReadOneByte()
{
uchar i,dat=0
DQ=1_nop_() // 先将数据线拉高 //等待一个机器周期
for (i=0i<8i++)
{
DQ=0 //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序
dat>>=1
_nop_()//等待一个机器周期
DQ=1 //将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备
_nop_()_nop_()//延时约6us,使主机在15us内采样
if (DQ) dat|=0x80 //如果读到的数据是1,则将1存入dat,如果是0则保持原值不变
Delay(30)//延时3us,两个读时序之间必须有大于1us的恢复期
DQ=1 // 将数据线拉高,为读下一位数据做准备
}
return dat
}
//-------------------------------------
//函数功能:写一字节
//入口参数:dat---待写入的数据
//-------------------------------------
void WriteOneByte(uchar dat)
{
uchar i
for (i=0i<8i++)
{
DQ=0 //将数据线从高拉低时即启动写时序
DQ=dat &0x01//利用与运算取出要写的某位二进制数据,
//并将其送到数据线上等待DS18B20采样
Delay(5) //延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样
DQ=1 //释放数据线
dat>>=1//将dat中的各二进制位数据右移1位
}
}
//-------------------------------------
//函数功能:读取温度值
//出入口参数:无
//-------------------------------------
void Read_Temperature()
{
if(Init_DS18B20() == 1) //DS18B20故障
DS18B20_IS_OK=0
else
{
WriteOneByte(0xCC) // 跳过读序号列号的 *** 作
WriteOneByte(0x44) // 启动温度转换
Init_DS18B20() //将DS18B20初始化
WriteOneByte(0xCC) //跳过读序号列号的 *** 作
WriteOneByte(0xBE) //读取温度寄存器,前两个分别是温度的低位和高位
Temp_Value[0]=ReadOneByte() //温度低8位
Temp_Value[1]=ReadOneByte() //温度高8位
DS18B20_IS_OK=1
}
}
//-------------------------------------
//函数功能:在LCD上显示当前温度
//入口参数:
//-------------------------------------
void Display_Temperature()
{
uchar i
//延时值与负数标识
uchar t=150,ng=0
//高5位全为1(0xF8)则为负数,为负数时取反加1,并设置负数标示
if ((Temp_Value[1] &0xF8)==0xF8)
{
Temp_Value[1]=~Temp_Value[1]
Temp_Value[0]=~Temp_Value[0]+1
if(Temp_Value[0]==0x00) Temp_Value[1]++ //加1后如果低字节为00表示有进位,进位位再加到高字节上
ng=1 //负数标示置1
}
Display_Digit[0]=df_Table[Temp_Value[0] &0x0F]//查表得到温度小数部分
//获取温度整数部分(高字节的低3位与低字节中的高4位,无符号)
CurrentT=((Temp_Value[0] &0xF0)>>4)|((Temp_Value[1] &0x07)<<4)
//将整数部分分解为3位待显示数字
Display_Digit[3]=CurrentT/100//百位 digit[CurrentT/100]
Display_Digit[2]=CurrentT%100/10//十位
Display_Digit[1]=CurrentT%10//个位
//刷新LCD显示缓冲
Current_Temp_Display_Buffer[11]=Display_Digit[0]+'0'//先将'0'转换成整数48,然后与前面数字相加,得到相应数字的ASCII字符
Current_Temp_Display_Buffer[10]='.'
Current_Temp_Display_Buffer[9]=Display_Digit[1]+'0' //个位
Current_Temp_Display_Buffer[8]=Display_Digit[2]+'0' //十位
Current_Temp_Display_Buffer[7]=Display_Digit[3]+'0' //百位
//高位为0时不显示
if(Display_Digit[3]==0) Current_Temp_Display_Buffer[7]=' '
//高位为0且次高位为0时,次高位不显示
if(Display_Digit[2]==0 &&Display_Digit[3]==0)
Current_Temp_Display_Buffer[8]=' '
//负数符号显示在恰当位置
if(ng)
{
if (Current_Temp_Display_Buffer[8]==' ')
Current_Temp_Display_Buffer[8]='-'
else if(Current_Temp_Display_Buffer[7]==' ')
Current_Temp_Display_Buffer[7]='-'
else
Current_Temp_Display_Buffer[6]='-'
}
//在第一行显示标题
Set_Disp_Pos(0x00)
for(i=0i<16i++)
{
Write_LCD_Data(Temp_Disp_Title[i])
}
Set_Disp_Pos(0x40) //在第二行显示当前温度
for(i=0i<16i++)
{
Write_LCD_Data(Current_Temp_Display_Buffer[i])
}
//显示温度符号
//Set_Disp_Pos(0x4D)Write_LCD_Data(0x00)
Set_Disp_Pos(0x4D)Write_LCD_Data(0xdf)
Set_Disp_Pos(0x4E)Write_LCD_Data('C')
}
//-------------------------------------
//函数功能:主函数
//入口参数:
//-------------------------------------
void main()
{
Initialize_LCD()
Read_Temperature()
Delay(50000)
Delay(50000)
while (1)
{
Read_Temperature()
if (DS18B20_IS_OK) Display_Temperature()
delay1(100)
}
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)