找回密码
 立即注册

QQ登录

只需一步,快速开始

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

求大神看一下 自己做的万年历 最高温度显示为16

[复制链接]
跳转到指定楼层
楼主
ID:258570 发表于 2017-12-13 00:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/**
程序功能:显示年月日,时分秒,星期,温度
*/
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit RS=P2^5;//数据命令选择端
sbit RW=P2^6;//读写选择端
sbit E=P2^7;//控制使能端
sbit DQ=P1^0;

sbit RST=P2^4;//片选输入信号端
sbit IO=P2^3;//串行时钟输入端
sbit CLK=P2^2;//串行数据输入输出端

uchar str1[16];
uchar str2[16];
uchar str3[16];
uchar second,minute,hour,day,month,year,week,yearH=20;


sbit select=P3^2;//选择调整部分按钮
sbit up=P3^1;//加按钮
sbit down=P3^0;//减按钮
void jisuan();
void jisuan1();
void display();
void gettemp();
//temp:临时变量,用于保存要写入ds1302的内容
//count:调整部分计数,1:年,2:月,3:日,
//                   4:时,5:分,6:秒,7:星期,8:退出调整
//done:调整标志,1:调整,0:不调整
//flag:时钟停止标志,1:走,0:停
//up_flag:加按键操作标志;down_flag:减按键操作标志
uchar temp=0x00,count=8,flag,done,up_flag,down_flag;
uchar t,flag_t;
void delay(uint x){//毫秒级的延时
    uint i,j;
    for(i=0;i<x;i++)
        for(j=0;j<120;j++);
}
//////////////////1602操作////////////////////////////
uint checkBusy(){//检查忙标志
    uchar temp;
    P0=0xff;//I/O口准备
    RS=0;//选择指令寄存器
    RW=1;//选择读模式
    E=1;//使能LCD
    _nop_();_nop_();_nop_();_nop_();//延时        
    temp=P0&0x80;//取忙标志
    E=0;//禁止LCD
    if(temp!=0x00)return 1;//忙返回1
    else return 0;//不忙返回0
}
void writeIR(uchar cmd){//写指令
    while(checkBusy());//检查忙状态
    RS=0;//选择指令模式
    RW=0;//选择写模式
    E=0;//禁止LCD
    P0=cmd;//写入命令字
    _nop_();_nop_();_nop_();_nop_();//延时       
    E=1;//使能LCD
    _nop_();_nop_();_nop_();_nop_();//延时
    E=0;//禁止LCD
}
void writecom(uchar com)
{
        checkBusy();
       
        RS=0;
        RW=0;
        E=0;
        P0=com;
        delay(3);
        E=1;
        delay(3);
        E=0;
}
void writeDDR(uchar dat){//写数据
    while(checkBusy());//检查忙状态
    RS=1;//选择数据模式
    RW=0;//选择写模式
    E=0;//禁止LCD
    P0=dat;//写入数据
    _nop_();_nop_();_nop_();_nop_();//延时
    E=1;//使能LCD
    _nop_();_nop_();_nop_();_nop_();//延时
    E=0;//禁止LCD
}
void showstr(uchar str[]){
        uint i;
        i=0;
    while(str[i]!='\0'){     
        writeDDR(str[i]);//显示字符
        i++;
    }
}
///////////////////显示子函数//////////////////////
/*void  display(){
        jisuan();
        writeIR(0x80);
        showstr(str1);
        writeIR(0xc0);
        showstr(str2);
}*/


/////////////////DS1302操作//////////////////////////
//DS1302:写入操作(写一个字节,上升沿操作)
void write_byte(uchar da){
        uchar i,temp;
        temp=da;//要写的数据送入临时变量temp
        for(i=8;i>0;i--){//将一个字节的数据分8次,一位一位送数据线         
                IO=temp&0x01;//将临时变量temp的最低位送入IO数据线
                CLK=0; //时钟信号拉低   
            CLK=1;//时钟信号拉高
              temp=temp>>1;//将下次要送的那位数据送到临时变量temp最低位
        }
        CLK=0;//写完一字节数据后,拉低时钟信号
}
//DS1302:读取操作(读一个字节,下降沿)
uchar read_byte()
{
        uchar i,a;
        a=0x00;//a清0,这步也可不做
        for(i=0;i<8;i++){//一个字节的数据分8次读,一位一位从数据线读
       
             a=a>>1;//空出临时变量a的最高位
                if(IO)a=a|0x80;//从数据线上读位数据到临时变量a的最高位
                else a=a|0x00;
                  CLK=1;        //时钟信号拉高
                  CLK=0;        //时钟信号拉低  
        }
        CLK=0;//读完一字节数据后,拉低时钟信号
        return a;//将临时变量a内的值返回
}
//DS1302:写入数据(先送地址,再写数据)
void write_1302(uchar addr,uchar da){
           RST=0;    //停止工作
           CLK=0;    //时钟信号拉低                             
           RST=1;   //重新工作
           write_byte(addr);    //写入地址
          write_byte(da);//写入数据(da是十六进制数据,BCD码)
           CLK=0;//时钟信号拉低
           RST=0;//停止工作
}
//DS1302:读取数据(先送地址,再读数据),读出的数据是BCD码
uchar read_1302(uchar addr)
{
           uchar temp;
           RST=0;   //停止工作
           CLK=0; //时钟信号拉低
          RST=1;//重新工作
           write_byte(addr);   //写入地址
           temp=read_byte();//读取数据(16进制,BCD码)
           CLK=0;//时钟信号拉低
           RST=0;//停止工作  
        return temp;
}
uchar toDEC(uchar da){
        uchar temp,dat1,dat2;
        temp=da;
        dat1=temp/16;     //提取BCD码的十位和个位
          dat2=temp%16;
          temp=dat1*10+dat2;     //转换成10进制数
           return temp;
}
uchar toBCD(uchar da){
        uchar temp;
        temp=(da/10)<<4|(da%10);//转换成BCD码
        return temp;
}
void setProtect(bit flag){
        if(flag)
                write_1302(0x8e,0x80);//打开写保护
        else
                write_1302(0x8e,0x00);//关闭写保护
}
//设置时间函数提供参数:控制字,要写入的10进制数据
void setTime(uchar addr,uchar da){
        setProtect(0);//关闭写保护
          write_1302(addr,toBCD(da));//写入BCD码到指定寄存器
}
void getTime(){//获取时钟芯片的时钟数据
        second=read_1302(0x81);//读秒(BCD码)
        second=toDEC(second&0x7f);//BCD码转十进制
        minute=read_1302(0x83);//读分(BCD码)
        minute=toDEC(minute);//BCD码转十进制
        hour=read_1302(0x85);//读时(BCD码)
        hour=toDEC(hour);//BCD码转十进制
        day=read_1302(0x87);//读日(BCD码)]
        day=toDEC(day);//BCD码转十进制
        month=read_1302(0x89);//读月(BCD码)
        month=toDEC(month);//BCD码转十进制
        year=read_1302(0x8d);//读年(BCD码)
        year=toDEC(year);//BCD码转十进制
        week=read_1302(0x8b);//读星期(BCD码)
        week=toDEC(week);//BCD码转十进制       
}

void jisuan(){//计算子程序,计算时间各位的值
        uint i;
        i=week-1;
        if(i==0)i=7;         
        str1[0]=yearH/10+'0';//提取年的千位
        str1[1]=yearH%10+'0';//提取年的百位
        str1[2]=year/10+'0';//提取年的十位
        str1[3]=year%10+'0';//提取年的个位
        str1[4]='-';
        str1[5]=month/10+'0';//提取月的十位
        str1[6]=month%10+'0';//提取月的个位
        str1[7]='-';
        str1[8]=day/10+'0';//提取日的十位
        str1[9]=day%10+'0';//提取日的个位
        str1[10]=' ';
        str1[11]=' ';
        str1[12]=i+'0';//星期
        str2[0]=hour/10+'0';//提取小时的十位
        str2[1]=hour%10+'0';//提取小时的个位
        str2[2]=':';
        str2[3]=minute/10+'0';//提取分钟的十位
        str2[4]=minute%10+'0';//提取分钟的个位
        str2[5]=':';
        str2[6]=second/10+'0';//提取秒钟的十位
        str2[7]=second%10+'0';//提取秒钟的个位
        str2[8]=' ';

         
}
void initial(){//初始化函数
        uchar second=read_1302(0x81);
        if(second&0x80){//时钟停止,则初始化
                setTime(0x80,0);
                setTime(0x82,20);
                setTime(0x84,8);
                setTime(0x86,1);
                setTime(0x88,6);
                setTime(0x8a,5);
                setTime(0x8c,12);
        }
}

//按键部分程序

void Upkey(){//加按钮
        up=1;
        if(up==0){ //加按键按下
                delay(10);
                if(up==0){//加按键确实按下
                        switch(count){//根据选择的模块进行调整
                                case 7://调整星期
                                                temp=week+1;//秒数加1
                                                if(week==7) temp=1;//越界处理
                                                up_flag=1;//数据调整后更新标志
                                                break;
                                case 6://调整秒
                                                temp=second+1;//秒数加1
                                                if(second==59) temp=0;//越界处理
                                                up_flag=1;//数据调整后更新标志
                                                break;
                                case 5://调整分
                                                temp=minute+1;//分数加1
                                                if(minute==59) temp=0;//越界处理
                                                up_flag=1;//数据调整后更新标志
                                                break;
                                case 4://调整时
                                                temp=hour+1;//小时数加1
                                                if(hour==23) temp=0;//越界处理
                                                up_flag=1;//数据调整后更新标志
                                                break;
                                case 3://调整日
                                                temp=day+1;//日数加1
                                                if(day==31) temp=1;//越界处理
                                                up_flag=1;//数据调整后更新标志
                                                break;
                                case 2://调整月
                                                temp=month+1;//月数加1
                                                if(month==12) temp=1;//越界处理
                                                up_flag=1;//数据调整后更新标志
                                                break;
                                case 1://调整年
                                                temp=year+1;//年数加1
                                                if(year==99){ temp=0;yearH=yearH+1;}//越界处理
                                                up_flag=1;//数据调整后更新标志
                                                break;
                                default:break;
                        }
                        while(up==0)display();
                }
        }
}
void Downkey(){//减按钮
        down=1;
        if(down==0){
                delay(10);
                if(down==0){
                        switch(count){
                                case 7://调整星期
                                        temp=week-1;
                                        if(week==0) temp=7;
                                        down_flag=1;
                                        break;
                                case 6://调整秒
                                        temp=second-1;
                                        if(second==0) temp=59;
                                        down_flag=1;
                                        break;
                                case 5://调整分
                                        temp=minute-1;
                                        if(minute==0) temp=59;
                                        down_flag=1;
                                        break;
                                case 4://调整时
                                        temp=hour-1;
                                        if(hour==0) temp=23;
                                        down_flag=1;
                                        break;
                                case 3://调整日
                                        temp=day-1;
                                        if(day==1) temp=31;
                                        down_flag=1;
                                        break;
                                case 2://调整月
                                        temp=month-1;
                                        if(month==1) temp=12;
                                        down_flag=1;
                                        break;
                                case 1://调整年
                                        temp=year-1;
                                        if(year==0){ temp=99;yearH=yearH-1;}
                                        down_flag=1;
                                        break;
                                default:break;
                        }
                        while(down==0)display();
                }
        }
}
void Selkey(){//调整部分选择按键
        select=1;
        if(select==0){
                delay(10);
                if(select==0){
                        count=count+1;
                        if(count==9) count=1;//调整部分计数加1
                        done=1;//进入调整模式
                }
        }
        while(select==0)display();
}
void keydone(){//按键功能执行       
        if(flag==0){//关闭时钟,停止计时
                setProtect(0);//写入允许
                temp=read_1302(0x81);
                write_1302(0x80,temp|0x80);
                setProtect(1);//禁止写入
                flag=1;
        }
        Selkey();//扫描调整部分选择按键
        switch(count){
                case 1:do{
                                        Upkey();//扫描加按钮
                                        Downkey();//扫描减按钮
                                        if(up_flag==1||down_flag==1){//数据更新,重新写入新的数据
                                                setProtect(0);//写入允许
                                                write_1302(0x8c,toBCD(temp));//写入新的年数
                                                setProtect(1);//禁止写入
                                                up_flag=0;
                                                down_flag=0;
                                        }
                                        getTime();
                                        display();
                                }while(count==2);
                                break;
                case 2:do{
                                        Upkey();//扫描加按钮
                                        Downkey();//扫描减按钮
                                        if(up_flag==1||down_flag==1){//数据更新,重新写入新的数据
                                                setProtect(0);//写入允许
                                                write_1302(0x88,toBCD(temp));//写入新的月数
                                                setProtect(1);//禁止写入
                                                up_flag=0;
                                                down_flag=0;
                                        }
                                        getTime();
                                        display();
                                }while(count==3);
                                break;
                case 3:do{
                                        Upkey();//扫描加按钮
                                        Downkey();//扫描减按钮
                                        if(up_flag==1||down_flag==1){//数据更新,重新写入新的数据
                                                setProtect(0);//写入允许
                                                write_1302(0x86,toBCD(temp));//写入新的日数
                                                setProtect(1);//禁止写入
                                                up_flag=0;
                                                down_flag=0;
                                        }
                                        getTime();
                                        display();
                                }while(count==4);
                                break;
                case 4:do{//调整时
                                        Upkey();//扫描加按钮
                                        Downkey();//扫描减按钮
                                        if(up_flag==1||down_flag==1){//数据更新,重新写入新的数据
                                                setProtect(0);//写入允许
                                                write_1302(0x84,toBCD(temp));//写入新的小时数
                                                setProtect(1);//禁止写入
                                                up_flag=0;
                                                down_flag=0;
                                        }
                                        getTime();
                                        display();
                                }while(count==5);
                                break;
                case 5:do{//调整分
                                        Upkey();//扫描加按钮
                                        Downkey();//扫描减按钮
                                        if(up_flag==1||down_flag==1){//数据更新,重新写入新的数据
                                                setProtect(0);//写入允许
                                                write_1302(0x82,toBCD(temp));//写入新的分数
                                                setProtect(1);//禁止写入
                                                up_flag=0;
                                                down_flag=0;
                                        }
                                        getTime();
                                        display();
                                }while(count==6);
                                break;
                case 6:do{//调整秒
                                        Upkey();//扫描加按钮
                                        Downkey();//扫描减按钮
                                        if(up_flag==1||down_flag==1){//数据更新,重新写入新的数据
                                                setProtect(0);//写入允许
                                                write_1302(0x80,toBCD(temp)|0x80);//写入新的秒数
                                                setProtect(1);//禁止写入
                                                up_flag=0;
                                                down_flag=0;
                                        }
                                        getTime();
                                        display();
                                }while(count==7);
                                break;
                case 7:do{//调整星期
                                        Upkey();//扫描加按钮
                                        Downkey();//扫描减按钮
                                        if(up_flag==1||down_flag==1){//数据更新,重新写入新的数据
                                                setProtect(0);//写入允许
                                                write_1302(0x8a,toBCD(temp));//写入新的星期数
                                                setProtect(1);//禁止写入
                                                up_flag=0;
                                                down_flag=0;
                                        }
                                        getTime();
                                        display();
                                }while(count==8);
                                break;
                case 8:do{
                                                count=0;
                                                second=read_1302(0x81);
                                                setProtect(0);//写入允许
                                                write_1302(0x80,second&0x7f);
                                                setProtect(1);//禁止写入
                                                done=0;
                                                display();
                                        }while(count==9);
                                        break;
                default:break;
        }
}

////////////////////主函数////////////////////////
/*void main(){
    //1602初始化工作
    writeIR(0x01);//清屏,同时光标移到左上角  
    writeIR(0x38);//功能设置:8位接口,2行,5*7字符  
    writeIR(0x0c);//控制字符、光标及闪烁:显示器开,光标关,光标不闪烁
    writeIR(0x06);//输入方式设置指令:光标不动,字符自动右移一格  
    //writeIR(0x80);//送DDRAM地址设置指令80H,从第1行第1列开始显示
    //DS1302初始化工作
        flag=1;
        initial();
        up_flag=0;
        down_flag=0;
        done=0;
        while(1){
        while(done==1)keydone();
                while(done==0){
                        getTime();
                        display();
                        flag=0;
                        Selkey();
                }
    }
}*/
/////////////////////////////////////////////////////////////////
void  display(){
        jisuan();
        writeIR(0x80);
        showstr(str1);
        writeIR(0xc0);
        showstr(str2);
        writecom(0x80);
        showstr(str1);
        writecom(0xc0);
        showstr(str2);
                jisuan1();
        writecom(0x00);
        showstr(str3);
}
void jisuan1(){//计算子程序,计算时间各位的值
        //uint i;
        if(flag_t)str3[0]='-';
        else str3[0]='+';
        str3[1]=t%1000/100+'0';
        str3[2]=t%100/10+'0';
        str3[3]='.';
        str3[4]=t%10+'0';
        str3[5]=223;
        str3[6]='C';
}

///////////////////DS18B20操作//////////////////////
//延时us级
void delay_us(uchar us){
        while(us--);
}

//初始化DS18B20
bit reset(){
        bit flag;//初始化标志位
        DQ=1;//dq复位,也可以不要
        delay_us(1);//稍做延时
        DQ=0;//单片机将dq拉低
        delay_us(80);//精确延时大于480us
        DQ=1;//拉高总线
        delay_us(8);//延时
        flag=DQ;//flag=0初始化成功,flag=1则初始化失败
        delay_us(20);
        return flag;
}
//DS18B20写一个字节
void write_tbyte(uchar dat){
        uchar i;
        bit onebit;
        for(i=0;i<8;i++){//一位一位写数据
                onebit=dat&0x01;//提取要写数据的最低位
                dat=dat>>1;//数据右移,准备下一次数据的提取
                if(onebit){//要写位为1时
                        DQ=0;//dq拉低时,空操作
                        _nop_();
                        _nop_();
                        DQ=1;//dq拉高时,延时
                        delay_us(5);
                }
                else{//要写位为0时
                        DQ=0;//dq拉低时,延时
                        delay_us(8);
                        DQ=1;//dq拉高时,空操作
                        _nop_();
                        _nop_();
                }
        }
}
//DS18B20读一个位
bit read_tbit(){
        bit dat;
        DQ=0;//dq拉低,1us之后释放总线(即拉高dq)
        _nop_();
        DQ=1;//dq拉高
        _nop_();
        _nop_();
        dat=DQ;//从总线dq上读位数据
        delay_us(10);//延时,确保读时序的长度60us
        return dat;
}
//DS18B20读一个字节
uchar read_tbyte(){
        uchar value,i,j;
        value=0;//value初始化清0,用于保存每次读取
           //1位后的字节数据
        for(i=0;i<8;i++){//一位一位读数据(从最低位开始)
                j=read_tbit();//读位数据到j的最低位
                value=(j<<7)|(value>>1);//构造读取的数据
//构造原理:第一步,将刚读到的位数据移到j的最高位
//第二步,将前一次读取的数据值右移一位
//第三步,将新的j与新的value进行或操作,
//得到当前新的读取数据
        }
        return value;
}
uint getTemp(){
        uchar a,b;
        float f_temp;//定义浮点型温度数据
       
        if(!reset()){//如果初始化成功
                write_tbyte(0xcc);//跳过ROM
                write_tbyte(0x44);//温度转换
        }
        if(!reset()){//如果初始化成功
                write_tbyte(0xcc);//跳过ROM
                write_tbyte(0xbe);//读暂存器
                a=read_tbyte();//读取温度低8位
                b=read_tbyte();//读取温度高8位
        }
        flag_t=0;
        t=b;//把温度数据的高8位赋给整型温度数据temp的低8位
        t<<=8;//把以上8位数据从temp的低8位移到高8位
        t=t|a;//两字节合并得到整型变量
        if(t>0x0fff){
                flag_t=1;       
                t=~t+1;
        }
        f_temp=t*0.0625;//得到真实的浮点型温度数据
        t=f_temp*10+0.5;//将浮点型温度数据放大十倍,并加0.5(加0.5是用于四舍五入)
                                                        //然后将处理后的浮点型温度数据强制取整,赋给整型温度数据
                                                        //这个赋值语句的目的将小数点后第一位也转换为可显示数字
        return t;
}
void main(){

    //1602初始化工作
    writeIR(0x01);//清屏,同时光标移到左上角  
    writeIR(0x38);//功能设置:8位接口,2行,5*7字符  
    writeIR(0x0c);//控制字符、光标及闪烁:显示器开,光标关,光标不闪烁
    writeIR(0x06);//输入方式设置指令:光标不动,字符自动右移一格  
    //writeIR(0x80);//送DDRAM地址设置指令80H,从第1行第1列开始显示
    //DS1302初始化工作
        flag=1;

        initial();
        up_flag=0;
        down_flag=0;
        done=0;
        while(1){
        while(done==1)keydone();
                while(done==0){
                        getTime();
                        gettemp();
                        display();
                        flag=0;
                        Selkey();
                }
    }
}
这是我的程序   但是最高的温度就是16°  超过16的部分都重新来

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

使用道具 举报

沙发
ID:260964 发表于 2017-12-13 09:44 | 只看该作者
666666.做的可以 太长了吧
回复

使用道具 举报

板凳
ID:260584 发表于 2017-12-13 11:09 | 只看该作者
看了看,还可以
回复

使用道具 举报

地板
ID:255579 发表于 2017-12-14 09:15 | 只看该作者
自我感觉你缺少的是温度检测那一部分的代码设计和实体部件的设置
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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