coolbgo 发表于 2018-8-19 19:59:22

单片机掉电保存数据电路,程序


自学的,电路图不会画,随便看看

电源上电先给外围设备供电,然后通过二极管给电容C1充电,给单片机供电,
电源有电时,中断IO口为高电平,电源掉电触发IO口下降沿中断,执行eeprom保存数据,同时电容代替电源单独给单片机供电220uF存几个字节没问题,存多要加大电容

程序里有个问题搞不明白,求各路大神解惑!
中断程序里调用子程序有时候无法赋值给子程序,不知道什么原因,子程序换名字重写一份了的,不存在重复调用问题。

Write_EEP2(sto1602+num1,0);这个可以正常把值赋给子程序
void Write_EEP2(uint addr,uchar dat)        //地址addr,写入dat
{
        IAP_ADDRH=addr>>8;
        IAP_ADDRL=addr;
        IAP_DATA=dat;
        IAP_CMD=2;
        IAP_TRIG=0X5A;
        IAP_TRIG=0XA5;
}


Read_EEP2(sto1602+num1);这个就不行,我在子程序里读取addr显示在数码管上,数值是4,5之类的,正常应该是1024以上
void Read_EEP2(uint addr)                        //地址addr读取数据
{
        IAP_ADDRH=addr>>8;
        IAP_ADDRL=addr;
        IAP_CMD=1;
        IAP_TRIG=0X5A;
        IAP_TRIG=0XA5;
}

#include<reg51.h>
//#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int

sfr P5=0xc8;                //声明P5端口地址
sfr P2M0=0x96;                //声明P2引脚模式寄存器
sfr P3M0=0xb2;                //声明P3引脚模式寄存器
sfr P3M1=0XB1;                //声明P3引脚模式寄存器

sfr AUXR=0x8e;                //声明辅助寄存器
sfr INT_CLKO=0X8F;        //外部中断与时钟输出控制寄存器

sfr ADC_RES=0xBD;        //声明转换结果寄存器
sfr ADC_RESL=0xBE;        //声明转换结果寄存器低2位

sfr P1ASF=0x9D;    //声明P1口模拟功能寄存器 模拟功能开关
sfr ADC_CONTR=0xBC;//声明数模转换寄存器

sfr T2H=0xd6;                //声明定时器2寄存器
sfr T2L=0xd7;

sfr IAP_CONTR=0xc7;        //定义IAP控制寄存器
//IAPEN(B7)置1时 允许操作eeprom
//CMD_FAIL(B4)错误时系统置1,需软件清零
//WT2 WT1 WT0系统等待设置 ≥12mhz011
sfr IAP_DATA=0XC2;        //ISP/IAP数据寄存器 EEPROM缓存空间
sfr IAP_ADDRH=0XC3;        //地址高8位
sfr IAP_ADDRL=0XC4;        //地址低8位
sfr IAP_CMD=0XC5;        //ISP命令寄存器 01读 10写 11擦除
sfr IAP_TRIG=0XC6;        //ISP命令触发寄存器        先写0x5a 再写0xa5触发

sbit DA=P2^4;                        //数码管位选
sbit DB=P3^2;
sbit DC=P3^6;
sbit DD=P2^0;
sbit DE=P2^1;
sbit DF=P2^3;
sbit DG=P3^5;
sbit DP=P3^7;

sbit B1=P2^5;                        //数码管段选
sbit B2=P2^2;
sbit B3=P3^3;
sbit B4=P3^4;

sbit SCK=P2^7;                                                //串行时钟输出到max6675
sbit CS=P1^0;                                                //片选端,CS为低时启动串行接口
sbit SO=P1^1;                                                //串行数据输入到单片机

sbit keyx1=P2^6;                                        //定义键盘键位
sbit keyx2=P2^7;
sbit keyx3=P1^0;
sbit keyx4=P1^1;
sbit keyy1=P1^2;
sbit keyy2=P1^3;
sbit keyy3=P1^4;
sbit keyy4=P1^5;
sbit keyy5=P1^6;

sbit S1=P5^4;                                                //定义pwm信号接口

sbit SCK1602=P1^4;
sbit RCK1602=P1^5;
sbit SI1602=P1^6;

bit busy,pwmflag;

uchar count,count2,Flag_temp,Flag_key,keynow,keyold,mode,key;                                        //定义计数,热电偶就绪

uint temp,value,t0;                                        //定义温度,按键值,定时器0计数

uchar code duan[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e,0xcf};        //定义常量数组数码管段选 code 0-15 p.
uchar code wei[]={0xf7,0xfb,0xfd,0xfe};                                                                                                                                                //数码管位选

////////1602时钟///////
uchar code zi1602[]=
{
        0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00,                //℃        0x00
        0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x00,                //年        0x01
        0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00,                //月        0x02
        0x1f,0x11,0x11,0x1f,0x11,0x11,0x1f,0x00,                //日        0x03
};
uchar mon,week,day,hour,min,sec,set;
uint num,year=2018,sto1602=0x0400;                //第三扇区

uchar x,OP1,OP2,DOP2;        //定义运算符 + - * / = c
uint tOP2,value1,value2;

long uint adc;                                //定义长整数,不然出错

void disduan(uchar dd)
{
        DA=dd>>7;DB=dd>>6&1;DC=dd>>5&1;DD=dd>>4&1;DE=dd>>3&1;DF=dd>>2&1;DG=dd>>1&1;DP=dd&1;
}

void diswei(uchar dw)
{
        B1=dw>>3&1;B2=dw>>2&1;B3=dw>>1&1;B4=dw&1;
}

void delay(uint n)                //@12.000MHz
{
    uchar ii, j;
        while(n--)
        {
                ii = 12;
                j = 169;
                do
                {
                        while (--j);
                } while (--ii);
        }
}

void Send1602(uchar dat1)        //hgfedcba   rs rw e d4 d5 d6 d7 空
{
        uchar i;

       
        for(i=7;i>4;i--)                //发送7-5
        {
                SI1602=dat1>>i&1;
                SCK1602=0;
                SCK1602=1;                        //上升沿移入数据
        }
       
        for(i=1;i<5;i++)                //发送1-4
        {
                SI1602=dat1>>i&1;
                SCK1602=0;
                SCK1602=1;                        //上升沿移入数据
        }
       
        SI1602=dat1&1;                        //发送0
        SCK1602=0;
        SCK1602=1;
       
        RCK1602=0;
        RCK1602=1;                                        //上升沿输出数据
}

void dis1602(uchar a,uchar b)        //a为0发送指令,为1发送数据 7654 3210
{
        a<<=7;
       
        Send1602(b>>3&0x1e|a);                        //1001 1110                高4位
       
        delay(2);
       
        Send1602(b>>3&0x1e|0x20|a);                //1011 1110                e使能信号
       
        delay(2);
       
        Send1602(b>>3&0x1e|a);                        //1001 1110                高4位
       
        delay(10);
       
        Send1602(b<<1&0x1e|a);                        //1001 1110                低4位
       
        delay(2);
       
        Send1602(b<<1&0x1e|0x20|a);                //1011 1110                e使能信号1011 0100
       
        delay(2);
       
        Send1602(b<<1&0x1e|a);                        //1001 1110                低4位
       
        delay(10);
}

void print1602(uchar a1,uchar *b1)
{
        dis1602(0,a1+0x80);                //定位光标地址
       
        while(*b1!='\0')
        {
                dis1602(1,*b1++);
        }
        *b1=0;
}

void init1602()
{
        uchar i1;
        delay(15);
        dis1602(0,0x33);
        dis1602(0,0x32);
        dis1602(0,0x28);                //4位总线模式
        dis1602(0,0x01);                //清屏
        dis1602(0,0x06);                //写一个字符指针加一,光标加一
        dis1602(0,0x0c);                //开显示 不显示光标
       
        print1602(0x00," 2018 08 12W.1");
        print1602(0x40," 10:20:1031.7 ");       
       
        dis1602(0,0x40);
        for(i1=0;i1<32;i1++)
                dis1602(1,zi1602);
        dis1602(0,0x85);dis1602(1,1);
        dis1602(0,0x88);dis1602(1,2);
        dis1602(0,0x8b);dis1602(1,3);
        dis1602(0,0xcf);dis1602(1,0);
               
        INT_CLKO|=0X40;                        //int4中断开关
//        P3M1=1;                                        //p3.0 高阻输入
}

void getkey1602()
{
        keyy1=0;                                                        //keyy1置零
        keynow=keyx1;                                        //keynow状态等于keyx1
        keynow=keyx2;
        keynow=keyx3;
        keynow=keyx4;
        keyy1=1;
        if(keynow==0&&keyold==1)
                mode=0;
        if(keynow==0&&keyold==1)
                IAP_CONTR=0x60;                                        //软复位
        if(keynow==0&&keyold==1)
                if(++set==6)
                        set=0;
        if(keynow==0&&keyold==1)
        {
                switch(set)
                {
                        case 0:year++;break;
                        case 1:if(++mon==13)mon=1;break;
                        case 2:if(++day==32)day=1;break;
                        case 3:if(++hour==24)hour=0;break;
                        case 4:if(++min==60)min=0;break;
                        case 5:if(++sec==60)sec=0;break;
                        default:break;
                }
                week=((year/100/4)-year/100*2+year%100+year%100/4+26*(mon+1)/10+day-1)%7;
                if(week==0)
                        week=7;
        }
        keyold=keynow;
        keyold=keynow;
        keyold=keynow;
        keyold=keynow;
}

void init()
{
    P2M0=0x1B;                        //P2强推挽0001 1011
    P3M0=0xE4;                        //P3强推挽1110 0100
        P1ASF=0x80;                        //开启P1^7引脚模拟功能
       
        key=255;
        S1=0;                                //pwm引脚置零
       
        EA=1;                                //中断总开关
        ET0=1;                                //定时器0开关
        AUXR |= 0x80;                //定时器时钟1T模式
        TMOD &= 0xF0;                //设置定时器模式
        TL0 = 0x88;                        //设置定时初值                10us
        TH0 = 0xFF;                        //设置定时初值
        TR0 = 1;                        //定时器0开始计时
       
        SCON|=0x40;                        //0100 0000                串口1工作模式1 开启接收
        ES=1;                                //打开串口中断
        PS=1;                                //串口最高中断优先级
       
        AUXR |= 0x05;                //定时器时钟1T模式 定时器2为串口1波特率
        T2L = 0xC8;                        //设置定时初值
        T2H = 0xFE;                        //设置定时初值
        AUXR |= 0x10;                //定时器2开始计时
}

uint MAX6675_ReadReg()                //返回dat 0-65535 包含状态 温度值
{
        uchar i;   
        uint dat; //   1111 1111 1111 1111
       
        i   = 0;   
        dat = 0;   
       
        CS= 0;                         //片选端,CS为低时、启动串行接口
        SCK = 0;                   //串行时钟置零 准备输出6675收到上升沿发送数据
       
        for(i=0; i<16; i++)                //get D15-D0 from 6675从最高位开始接收16位数据
        {      
                SCK = 1;                                //重置时钟 接收数据
                dat = dat<<1;                        //dat左移一位,1111 1111 1111 1110
                if( SO==1 )          
                        dat = dat|0x01;                //收到高电平,个位改为1
                SCK = 0;                                //发送时钟信号,准备接收下一位数据
        }
        CS = 1;
        SCK=1;
          
        return dat;   //
}

void gettemp()
{
        if(count2==8)                                        //256周期测一次温度,电压
        {
                temp=MAX6675_ReadReg();                //读取状态数据0-65535   1111 1111 1111 1111 fedc ba98 7654 3210
                Flag_temp=(temp&4)>>2;                //读出数据的D2位是热电偶掉线标志位,该位为1表示掉线,该位为0表示连接 0000 0000 0000 0100
               
                temp=((temp<<1)>>4)*5/2;        //读出来的数据的D3~D14是温度值 左移1位,右移4位 乘5/2 10倍温度值
        }
}

voidgetadc()
{
        ADC_CONTR=0xef;                                //开始ad转换 1110 1111
        while(ADC_CONTR==0xef);                //跳过转换时间
        ADC_CONTR&=0xe7;                        //1110 0111        清除adc中断标志
        adc=ADC_RES*4+ADC_RESL;                //读取转换结果 10位精度 0-1023
}

void getkey()
{
        uchar i;
       
        if(count2%16==0)                                                //16ms检测一次mode键
        {
                keyy1=0;                                                        //keyy1置零
                keynow=keyx1;                                        //keynow状态等于keyx1
                keynow=keyx2;
                keyy1=1;
                if(keynow==0&&keyold==1)
                        key=0;
                if(keynow==0&&keyold==1)
                        IAP_CONTR=0x60;                                        //软复位
                keyold=keynow;
                keyold=keynow;
        }
       
        if(count2%16==0&&mode==1)                        //模式1时,16ms检测一次按键
        {
                keyy1=0;
                keynow=keyx1;
                keynow=keyx2;
                keynow=keyx3;
                keynow=keyx4;
               
                keyy1=1;keyy2=0;
                keynow=keyx1;
                keynow=keyx2;
                keynow=keyx3;
                keynow=keyx4;

                keyy2=1;keyy3=0;
                keynow=keyx1;
                keynow=keyx2;
                keynow=keyx3;
                keynow=keyx4;

                keyy3=1;keyy4=0;
                keynow=keyx1;
                keynow=keyx2;
                keynow=keyx3;
                keynow=keyx4;


                keyy4=1;keyy5=0;
                keynow=keyx1;
                keynow=keyx2;
                keynow=keyx3;
                keynow=keyx4;
                keyy5=1;
               
                for(i=0;i<20;i++)
                {
                        if(keynow==0&&keyold==1)
                                key=i;
                       
                        keyold=keynow;
                }
        }
}

void SendData(uchar dat)
{
        while(busy);                        //等待前面数据发送完成
        busy=1;
        SBUF=dat;
}

void SendString(char *s)
{
        while(*s)
        {
                SendData(*s++);
        }
}

void INITEEP()                                        //开始eeprom操作
{
        IAP_CONTR|=0X83;        //1000 0011        允许eeprom操作 延时设置为011
        IAP_CONTR&=0XFB;        //1111 1011
}

void BANEEP()                                        //结束eeprom操作
{
        IAP_CONTR&=0X78;        //0111 1000
        IAP_CMD=0;
        IAP_TRIG=0;
}

void Write_EEP(uint addr,uchar dat)        //地址addr,写入dat
{
        IAP_ADDRH=addr>>8;
        IAP_ADDRL=addr;
        IAP_DATA=dat;
        IAP_CMD=2;
        IAP_TRIG=0X5A;
        IAP_TRIG=0XA5;
}

uchar Read_EEP(uint addr)                        //地址addr读取数据
{
        IAP_ADDRH=addr>>8;
        IAP_ADDRL=addr;
        IAP_CMD=1;
        IAP_TRIG=0X5A;
        IAP_TRIG=0XA5;
        return IAP_DATA;
}
///////////////////////////////
//void Read_EEP2(uint addr)                        //地址addr读取数据
//{
//        IAP_ADDRH=addr>>8;
//        IAP_ADDRL=addr;
//        IAP_CMD=1;
//        IAP_TRIG=0X5A;
//        IAP_TRIG=0XA5;
//}

void Write_EEP2(uint addr,uchar dat)        //地址addr,写入dat
{
        IAP_ADDRH=addr>>8;
        IAP_ADDRL=addr;
        IAP_DATA=dat;
        IAP_CMD=2;
        IAP_TRIG=0X5A;
        IAP_TRIG=0XA5;
}

/////////////////////////////////////
void EraseSector_EEP(uint addr)        //清空扇区
{
        IAP_ADDRH=addr>>8;
        IAP_ADDRL=addr;
        IAP_CMD=3;
        IAP_TRIG=0X5A;
        IAP_TRIG=0XA5;
}

void RECORD_1602()                                                //记录1602时间
{
        INITEEP();
       
        for(num=0;num<512;num+=8)                                        //八字节一组 读第一字节
        {
                if(Read_EEP(sto1602+num)==0xff)        //读出未写字符跳出
                        break;
        }
       
        value=num;
        Write_EEP(sto1602+num,0);                                //第一字节置零
        Write_EEP(sto1602+num+1,year/100);
        Write_EEP(sto1602+num+2,year%100);
        Write_EEP(sto1602+num+3,mon);
        Write_EEP(sto1602+num+4,day);
        Write_EEP(sto1602+num+5,hour);
        Write_EEP(sto1602+num+6,min);
        Write_EEP(sto1602+num+7,0);                        //最后字节置零
       
        BANEEP();
}


void READ_1602()
{
        uchar temp;
        INITEEP();
       
        for(num=0;num<512;num+=8)                                        //八字节一组 读第一字节
        {
                temp=Read_EEP(sto1602+num);
                if(temp==0xff)        //读出未写字符跳出
                        break;
        }                                                                        //如扇区满,num=512跳出循环
       
        if(num==0)                                                        //无数据返回
                return;
       
        while(Read_EEP(sto1602+num-1)!=0)                //如果前一组不完整,前跳一组
        {
                num-=8;
                if(num==0)                                                //无数据返回
                        return;
        }
       
        num-=8;                                                                //读取空白前一组
       
        value=num;
       
        year=Read_EEP(sto1602+num+1)*100;
        year+=Read_EEP(sto1602+num+2);
        mon=Read_EEP(sto1602+num+3);
        day=Read_EEP(sto1602+num+4);
        hour=Read_EEP(sto1602+num+5);
        min=Read_EEP(sto1602+num+6);
        week=((year/100/4)-year/100*2+year%100+year%100/4+26*(mon+1)/10+day-1)%7;
        if(week==0)
                week=7;
       
        if(num==504)                                                        //扇区满清空
        {
                EraseSector_EEP(sto1602);                //清空扇区
                RECORD_1602();                                        //记录当前数据
        }
               
        BANEEP();
}

void operation()
{
        if(count2%16==0)
        {
                switch(key)
                {
                        case 0:        key=255;mode++;if(mode==5){mode=0;S1=0;}break;//3个模式
                        case 1:                break;
                        case 2:                break;
                        case 3:                break;
                        case 4:        key=255;x=1;        break;
                        case 5:        key=255;x=2;        break;
                        case 6:        key=255;x=3;        break;
                        case 7:        key=255;OP1=1;        break;        // +
                        case 8:        key=255;x=4;        break;
                        case 9:        key=255;x=5;        break;
                        case 10:key=255;x=6;        break;
                        case 11:key=255;OP1=2;        break;        // -
                        case 12:key=255;x=7;        break;
                        case 13:key=255;x=8;        break;
                        case 14:key=255;x=9;        break;
                        case 15:key=255;OP1=3;        break;        // *
                        case 16:key=255;x=0;        break;
                        case 17:key=255;OP2=1;        break;        // =
                        case 18:key=255;OP2=2;        break;        // c
                        case 19:key=255;OP1=4;        break;        // /
                       
                        default:        break;
                }
               
                if(mode==1)
                {
                        if(OP1==0&&x!=255)
                        {
                                value1=value1*10+x;
                                x=255;
                                value=value1;
                        }
                       
                        if(OP1!=0&&x!=255)
                        {
                                value2=value2*10+x;
                                x=255;
                                value=value2;
                        }

                        if(OP2==1)                                                        //输入 =
                        {
                                OP2=0;
                               
                                switch(OP1)
                                {
                                        case 0:        value=value1;SendString("");                        break;
                                        case 1:        value=value1+value2;                break;
                                        case 2:        value=value1-value2;                break;
                                        case 3:        value=value1*value2;                break;
                                        case 4:        value=value1/value2;                break;
                                       
                                        default:        break;
                                }
                                OP1=OP2=DOP2=tOP2=value1=value2=0;
                        }
                       
                        if(DOP2==1)
                                tOP2++;
                        if(tOP2==30)
                                DOP2=0;
                        if(OP2==2&&DOP2==1)                                                //双击C清空所有数据
                                OP1=OP2=DOP2=tOP2=value1=value2=value=0;
                       
                        if(OP2==2)                                                                //单击C清除数据
                        {
                                OP2=0;
                                DOP2=1;tOP2=0;
                                if(OP1==0)
                                        value=value1=0;
                                else
                                        value=value2=0;
                        }
                }
        }
}

void display()
{
        if(mode==0)
        {
                gettemp();
               
                switch(count)                                        //显示温度
                {
                        case 0:B4=1;if(temp/1000==0)break;                disduan(duan);        diswei(wei);break;        //显示第1管 为0不显示
                        case 1:B1=1;disduan(duan);        diswei(wei);break;                                                                //显示第2管
                        case 2:B2=1;disduan(duan);        diswei(wei);DP=1;break;                                                        //显示第3管 带小数点
                        case 3:B3=1;disduan(duan);                diswei(wei);break;                                                                //显示第4管
                       
                        default: break;
                }
        }
       
        if(mode==1)
        {
                switch(count)                                        //显示按键 计算器
                {
                        case 0:B4=1;if(value/1000==0)break;        disduan(duan);                diswei(wei);break;                        //显示第1管
                        case 1:B1=1;if(value/100==0)break;        disduan(duan);        diswei(wei);break;                        //显示第2管
                        case 2:B2=1;if(value/10==0)break;        disduan(duan);                diswei(wei);break;                        //显示第3管
                        case 3:B3=1;                                                disduan(duan);                diswei(wei);break;                        //显示第4管
                       
                        default: break;
                }
        }
       
        if(mode==2)
        {
                if(count==0)
                {
                        getadc();
                        adc=adc*5000/1023;                        //1000倍电压值 adc*5v/1023*1000
                }
               
                switch(count)                                        //显示电压
                {
                        case 0:B4=1;disduan(duan);        diswei(wei);DP=1;break;                //显示第1管 带小数点
                        case 1:B1=1;disduan(duan);        diswei(wei);break;                        //显示第2管
                        case 2:B2=1;disduan(duan);        diswei(wei);break;                        //显示第3管       
                        case 3:B3=1;disduan(duan);                diswei(wei);break;                        //显示第4管       
                       
                        default: break;
                }
        }
       
        while(mode==3)                                                                //模式3 pwm循环
        {
                t0=0;
                pwmflag=!pwmflag;
               
                if(pwmflag==1) S1=1;                                        //pwm高电平
                B4=1;disduan(duan);diswei(wei);        //显示数码管1
                getadc();                                                                //获取adc 0-1023
                adc=adc/10+100;                                                        //100-202
                if(adc>200)                                                                //100-200
                        adc=200;
               
                while(t0!=adc);
                S1=0;                                                                        //pwm低电平
               
                while(t0!=250);
                B1=1;disduan(duan);        diswei(wei);//显示数码管2

               
                while(t0!=500);
                B2=1;disduan(duan);        diswei(wei);//显示数码管3
               
                while(t0!=750);
                B3=1;disduan(duan);        diswei(wei);//显示数码管4
               
                                                        //检测mode按键
                keyy1=0;                                                        //keyy1置零
                keynow=keyx1;                                        //keynow状态等于keyx1
                keynow=keyx2;
                keyy1=1;
                if(keynow==0&&keyold==1)
                {
                        mode=4;                                                        //符合条件mode回零,跳出pwm模式循环
                        B4=1;
                }
                if(keynow==0&&keyold==1)
                        IAP_CONTR=0x60;                                        //软复位
                keyold=keynow;
                keyold=keynow;
               
                while(t0!=1000);                                        //10ms一个周期
        }
       
        if(mode==4)
        {
                TL0 = 0x20;                //设置定时初值                1ms
                TH0 = 0xD1;                //设置定时初值

                init1602();
                READ_1602();
               
                while(mode==4)
                {
                        t0=0;
                        getkey1602();
                       
                        if(++sec==60)
                        {
                                sec=0;
                                min++;
//                                RECORD_1602();
                        }
                        dis1602(0,0xc7);dis1602(1,sec/10+0x30);dis1602(1,sec%10+0x30);
                        B4=1;disduan(duan);diswei(wei);        //显示数码管1
                        while(t0!=100);
                       
                        getkey1602();
                       
                        if(min==60)
                        {
                                min=0;
                                hour++;
                        }
                        dis1602(0,0xc4);dis1602(1,min/10+0x30);dis1602(1,min%10+0x30);
                       
                        while(t0!=200);

                        getkey1602();
                       
                        if(hour==24)
                        {
                                hour=0;
                                day++;
                                if(++week==8)
                                        week=1;
                        }
                        dis1602(0,0xc1);dis1602(1,hour/10+0x30);dis1602(1,hour%10+0x30);
                        B1=1;disduan(duan);        diswei(wei);//显示数码管2
                        while(t0!=300);
                       
                        getkey1602();
                       
                        if((mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)&&day==32)
                        {
                                day=1;
                                mon++;
                        }
                        else if((mon==4||mon==6||mon==9||mon==11)&&day==31)
                        {
                                day=1;
                                mon++;
                        }
                        else if(((year)%4!=0||((year)%100==0&&(year)%400!=0))&&mon==2&&day==29)
                        {
                                day=1;
                                mon++;
                        }
                        else if(((year)%4==0&&(year)%100!=0||(year)%400==0)&&mon==2&&day==30)
                        {
                                day=1;
                                mon++;
                        }
                        dis1602(0,0x89);dis1602(1,day/10+0x30);dis1602(1,day%10+0x30);
                       
                        while(t0!=400);
                       
                        getkey1602();
                       
                        dis1602(0,0x8f);dis1602(1,week+0x30);
                       
                        while(t0!=500);
                       
                        getkey1602();
                       
                        if(mon==13)
                        {
                                mon=1;
                                year++;
                        }
                        dis1602(0,0x86);dis1602(1,mon/10+0x30);dis1602(1,mon%10+0x30);
                        B2=1;disduan(duan);        diswei(wei);//显示数码管3
                        while(t0!=600);
                       
                        getkey1602();
                       
                        dis1602(0,0x83);dis1602(1,year%100/10+0x30);dis1602(1,year%10+0x30);
                       
                        while(t0!=700);
                       
                        getkey1602();
                       
                        dis1602(0,0x81);dis1602(1,year/1000+0x30);dis1602(1,year%1000/100+0x30);
                       
                        while(t0!=800);
                       
                        getkey1602();
                       
                        temp=MAX6675_ReadReg();                //读取状态数据0-65535   1111 1111 1111 1111 fedc ba98 7654 3210
                        temp=((temp<<1)>>4)*5/2;        //读出来的数据的D3~D14是温度值 左移1位,右移4位 乘5/2 10倍温度值
                       
                        dis1602(0,0xcb);dis1602(1,temp%1000/100+0x30);dis1602(1,temp%100/10+0x30);
                       
                        while(t0!=900);
                       
                        getkey1602();
                       
                        dis1602(0,0xce);dis1602(1,temp%10+0x30);
                        B3=1;disduan(duan);        diswei(wei);//显示数码管4
                        while(t0!=1000);
                }
               
                TL0 = 0x88;                        //设置定时初值                10us
                TH0 = 0xFF;                        //设置定时初值
        }
}

main()
{
        init();
       
    while(1)//
    {
                delay(1);                                //系统周期1毫秒

      if(++count>3) count=0;        //0-3循环

                count2++;                                //0-255循环

                getkey();                                //运行一次80us16ms运行一次
               
                operation();

                display();
    }
}

void Uart1_Routine() interrupt 4 using 3
{
        if(RI)
        {
                RI=0;                                //清除RI标志
                value=SBUF;
        }
       
        if(TI)
        {
                TI=0;                                //清除TI标志
                busy=0;
        }
}

void Int4_Routine() interrupt 16 using 3
{       
        uint num1;
       
        IE=0;
        TCON=0;
        AUXR=0;
        SCON=0;
        P2M0=0;
        P3M0=0;
        B1=B2=B3=B4=1;

        INITEEP();

        for(num1=0;num1<512;num1+=8)                                        //八字节一组 读第一字节
        {               
                IAP_ADDRH=(sto1602+num1)>>8;
                IAP_ADDRL=(sto1602+num1);
                IAP_CMD=1;
                IAP_TRIG=0X5A;
                IAP_TRIG=0XA5;
       
                if(IAP_DATA==0xff)        //读出未写字符跳出
                        break;
        }


        value=num1;
        Write_EEP2(sto1602+num1,0);                                //第一字节置零
        Write_EEP2(sto1602+num1+1,year/100);
        Write_EEP2(sto1602+num1+2,year%100);
        Write_EEP2(sto1602+num1+3,mon);
        Write_EEP2(sto1602+num1+4,day);
        Write_EEP2(sto1602+num1+5,hour);
        Write_EEP2(sto1602+num1+6,min);
        Write_EEP2(sto1602+num1+7,0);                        //最后字节置零
       
        BANEEP();
       
//        while(1)
//        {
//                B4=1;disduan(duan);diswei(wei);        //显示数码管1
//                B1=1;disduan(duan);        diswei(wei);//显示数码管2
//                B2=1;disduan(duan);        diswei(wei);//显示数码管3
//                B3=1;disduan(duan);        diswei(wei);//显示数码管4
//        }
}

void Timer0_Routine() interrupt 1 using 2
{
        t0++;                                //10us
}

1121454314 发表于 2018-8-19 21:38:32

进来围观{:1_1:}{:1_1:}

我爱萝丽爱萝丽 发表于 2018-8-19 21:47:29

read函数里面都没有读寄存器操作,怎么可能正常呢

随心,随性 发表于 2018-8-19 22:24:58

路过帮顶

17620462 发表于 2018-8-20 13:21:14

看来是个很重要的应用。

飞将军 发表于 2018-8-20 14:13:40

路过看看

leigongdianmu 发表于 2018-8-20 18:57:55

路过帮顶

coolbgo 发表于 2018-8-20 20:18:03

我爱萝丽爱萝丽 发表于 2018-8-19 21:47
read函数里面都没有读寄存器操作,怎么可能正常呢

萝丽大神好{:1_12:}

如果read函数能正确读到中断里赋的值,这个子程序执行完,我只要在中断里读取IAP_DATA的值应该也是可以的。
主要的问题是中断程序里Read_EEP2(sto1602+num1);中的“sto1602+num1” 赋值给子程序void Read_EEP2(uint addr) 中的“addr”出错
sto1602的值是0x0400,也就是1024   但是读取子程序中的addr显示在数码管上才4,5之类的数

uchar Read_EEP2(uint addr)                        //从地址addr读取数据
{
        IAP_ADDRH=addr>>8;
        IAP_ADDRL=addr;
        IAP_CMD=1;
        IAP_TRIG=0X5A;
        IAP_TRIG=0XA5;
        return IAP_DATA;
}
这样也试过,返回的值不对。

1150323439 发表于 2018-8-23 14:06:08

受教了虽然还是不懂

玩飞机的小宁宁 发表于 2018-8-23 19:57:01

受教了虽然还是不懂
发电子论坛吧

rg0014 发表于 2019-3-30 23:26:24

我新手,感觉单片机语言和我学的java差好多,直接看不懂

yxs88q 发表于 2019-4-9 06:19:08

看不懂

coolbgo 发表于 2019-4-13 11:47:03

yxs88q 发表于 2019-4-9 06:19
看不懂

半年没看单片机了,我自己也看不懂了哈哈{:1_9:}
页: [1]
查看完整版本: 单片机掉电保存数据电路,程序