您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > DS18B20万年历温度时间按键控制1602显示51单片机程序
/*******************************************************************描述:*LCD1602可以分为8位和4位控制方式,8位控制方式是用D0-D7数据线*来传送控制命令及数据。4位控制方式是用D4-D7数据线来传送控制命令*及数据。使用4位数据线做控制时,需要分两次来传送,先送出高4位数*据,再送出低4位数据。可以节省单片机的4根端口线。*******************************************************************/#includereg52.h#includeintrins.h//用到nop()时使用#defineucharunsignedchar#defineuintunsignedintsbitK5=P1^4;//调节数位切换键sbitK6=P1^5;//数值增加键sbitK7=P1^6;//数值减小键sbitK8=P1^7;//确认键ucharK5flag=0;sbitLCD_RS=P2^0;//LCD1602数据/命令选择端sbitLCD_RW=P2^1;//LCD1602读/写选择端sbitLCD_EN=P2^2;//LCD1602使能端sbitDQ=P3^3;//DS18B20信号端uintyear=2015;ucharmonth=2;ucharday=27,daytemp;ucharweekdayflag=5;charH=12;charM=0;charS=0;uchardisplaybuf[9];ucharcodecdis1[20]={0123456789:.C-};ucharcodecdis2[7][5]={Mon,Tue,Wed,Thu,Fir,Sat,Sun};/**********************************************************5us延时子程序ms延时函数**********************************************************/voiddelayNOP(){_nop_();//一个机器周期1us延时_nop_();_nop_();_nop_();_nop_();}voiddelay(uintms){uintt;while(ms--){for(t=0;t100;t++);}}/**********************************************************1602液晶操作**********************************************************///忙碌状态判断bitlcd_busy()//RS/RW/EN=0/1/1为读状态{bitresult;LCD_RS=0;//RS为1选择数据,RS为0选择命令LCD_RW=1;//RW为1选择读操作,RW为0选择写操作LCD_EN=1;//EN等于1可以读取信息,等于0可以执行命令delayNOP();//5us延时result=(bit)(P0&0x80);//确保STA7为0,说明为“闲”状态,为1位“忙”操作;(bit)(P0&0x80)为强制类型转换LCD_EN=0;//读取数据结束之后,复位执行使能操作return(result);}//写命令voidwrite_control(ucharcontrol)//RS/RW/EN=0/0/高脉冲为写指令状态{while(lcd_busy());LCD_RS=0;//选择命令操作LCD_RW=0;//RW为0时写数据;LCD_EN=0;//1602执行命令delayNOP();P0=control;//发送高四位给1602数据P0口LCD_EN=1;//EN高脉冲delayNOP();LCD_EN=0;//高脉冲之后恢复EN=0delayNOP();}//写地址voidwrite_address(ucharpos)//写入显示地址命令{pos=(pos|0x80);//数据指针=80+地址变量write_control(pos);}//写数据voidwrite_data(uchartemp)//RS/RW/EN=1/0/高脉冲为写数据状态{while(lcd_busy());LCD_RS=1;//选择命令操作LCD_RW=0;//RW为0时写数据;LCD_EN=0;//1602执行命令delayNOP();P0=temp;//发送数据给1602数据P0口LCD_EN=1;//EN高脉冲delayNOP();LCD_EN=0;//高脉冲之后恢复EN=0delayNOP();}//液晶初始化voidlcd_init()//1602液晶初始化函数{delay(5);write_control(0x38);//16*2显示,5*7点阵,8位数据delay(1);write_control(0x38);//重复写入,确保成功delay(1);write_control(0x38);//重复写入,确保成功delay(1);write_control(0x0f);//光标移动delay(1);write_control(0x04);//光标移动delay(1);write_control(0x01);//清除LCD的显示内容delay(5);//延时}//万年历时间判断显示函数voiddate_display(){while(lcd_busy());write_address(0x00);write_data(cdis1[year/1000%10]);write_data(cdis1[year/100%10]);write_data(cdis1[year/10%10]);write_data(cdis1[year%10]);write_data(cdis1[13]);write_data(cdis1[month/10]);write_data(cdis1[month%10]);write_data(cdis1[13]);write_data(cdis1[day/10]);write_data(cdis1[day%10]);}//weekday显示函数voidweekday_display(){inti=3;while(lcd_busy());write_address(0x0c);write_control(0x0c);for(i=0;i3;i++){write_data(cdis2[weekdayflag-1][i]);}}//时间程序显示函数voidTimeDisplay(jj)//时间程序显示子函数{uchartemp;displaybuf[0]=jj%10;displaybuf[1]=jj/10;displaybuf[3]=M%10;displaybuf[4]=M/10;displaybuf[6]=H%10;displaybuf[7]=H/10;while(lcd_busy());write_address(0x48);//写入时十位temp=displaybuf[7];write_data(cdis1[temp]);temp=displaybuf[6];//写入时个位write_data(cdis1[temp]);write_data(cdis1[10]);//写入:temp=displaybuf[4];//写入分十位write_data(cdis1[temp]);temp=displaybuf[3];//写入分个位write_data(cdis1[temp]);write_data(cdis1[10]);//:temp=displaybuf[1];//写入秒十位write_data(cdis1[temp]);temp=displaybuf[0];//写入秒个位write_data(cdis1[temp]);}//DS18B20操作函数//初始化函数读取应答信号unsignedchartime;//设置全局变量,专门用于严格延时bitInit_DS18B20(void){bitflag;//储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在DQ=1;//先将数据线拉高for(time=0;time2;time++)//略微延时约6微秒;DQ=0;//再将数据线从高拉低,要求保持480~960usfor(time=0;time200;time++)//略微延时约600微秒;DQ=1;//释放数据线(将数据线拉高)for(time=0;time10;time++);//延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)flag=DQ;//让单片机检测是否输出了存在脉冲(DQ=0表示存在)for(time=0;time200;time++)//延时足够长时间,等待存在脉冲输出完毕;return(flag);//返回检测成功标志,返回1表示存在,返回0表示不存在}//从DS18B20中读取数据,读取的数据从最低位开始unsignedcharReadOneChar(void){unsignedchari=0;unsignedchardat;//储存读出的一个字节数据for(i=0;i8;i++){DQ=1;//先将数据线拉高_nop_();//等待一个机器周期DQ=0;//单片机从DS18B20读书据时,将数据线从高拉低即启动读时序dat=1;//复合运算符,等于:dat=dat1;_nop_();//等待一个机器周期DQ=1;//将数据线人为拉高,为单片机检测DS18B20的输出电平作准备for(time=0;time2;time++);//延时约6us,使主机在15us内采样if(DQ==1)dat|=0x80;//如果读到的数据是1,则将1存入datelsedat|=0x00;//如果读到的数据是0,则将0存入dat//将单片机检测到的电平信号DQ存入r[i]for(time=0;time8;time++);//延时3us,两个读时序之间必须有大于1us的恢复期}return(dat);//返回读出的十进制数据}//向DS18B20中写入数据voidWriteOneChar(unsignedchardat){unsignedchari=0;for(i=0;i8;i++){DQ=1;//先将数据线拉高_nop_();//等待一个机器周期DQ=0;//将数据线从高拉低时即启动写时序DQ=dat&0x01;//利用与运算取出要写的某位二进制数据,并将其送到数据线上等待DS18B20采样for(time=0;time10;time++);//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样DQ=1;//释放数据线for(time=0;time1;time++);//延时3us,两个写时序间至少需要1us的恢复期dat=1;//将dat中的各二进制位数据右移1位}for(time=0;time4;time++);//写完数据之后稍作延时,给硬件一点反应时间}//温度值计算及显示函数voidTdisplay(){ucharTL;//储存暂存器的温度低位ucharTH;//储存暂存器的温度高位ucharTN;//储存温度的整数部分ucharTD;//储存温度的小数部分uchari,j,k;//计算温度整数部分的个位,十位,百位Init_DS18B20();WriteOneChar(0xCC);//单线单DS18B20可以跳过读序号列号的操作,节省时间WriteOneChar(0x44);//启动温度转换命令for(time=0;time100;time++);//温度转换需要一点时间Init_DS18B20();//将DS18B20初始化WriteOneChar(0xCC);//跳过读序号列号的操
本文标题:DS18B20万年历温度时间按键控制1602显示51单片机程序
链接地址:https://www.777doc.com/doc-6037822 .html