模吧

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

1040查看 | 12回复

[DIY交流] 单片机掉电保存数据电路,程序

[复制链接]
发表于 2018-8-19 19:59:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
单片机掉电保存数据电路,程序 电容 作者:coolbgo 7279
自学的,电路图不会画,随便看看

电源上电先给外围设备供电,然后通过二极管给电容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;
}

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

  3. #define uchar unsigned char
  4. #define uint unsigned int

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

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

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

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

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

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

  26. sbit DA=P2^4;                        //数码管位选
  27. sbit DB=P3^2;
  28. sbit DC=P3^6;
  29. sbit DD=P2^0;
  30. sbit DE=P2^1;
  31. sbit DF=P2^3;
  32. sbit DG=P3^5;
  33. sbit DP=P3^7;

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

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

  41. sbit keyx1=P2^6;                                        //定义键盘键位
  42. sbit keyx2=P2^7;
  43. sbit keyx3=P1^0;
  44. sbit keyx4=P1^1;
  45. sbit keyy1=P1^2;
  46. sbit keyy2=P1^3;
  47. sbit keyy3=P1^4;
  48. sbit keyy4=P1^5;
  49. sbit keyy5=P1^6;

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

  51. sbit SCK1602=P1^4;
  52. sbit RCK1602=P1^5;
  53. sbit SI1602=P1^6;

  54. bit busy,pwmflag;

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

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

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

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

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

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

  72. void disduan(uchar dd)
  73. {
  74.         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;
  75. }

  76. void diswei(uchar dw)
  77. {
  78.         B1=dw>>3&1;B2=dw>>2&1;B3=dw>>1&1;B4=dw&1;
  79. }

  80. void delay(uint n)                //@12.000MHz
  81. {
  82.     uchar ii, j;
  83.         while(n--)
  84.         {
  85.                 ii = 12;
  86.                 j = 169;
  87.                 do
  88.                 {
  89.                         while (--j);
  90.                 } while (--ii);
  91.         }
  92. }

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

  96.        
  97.         for(i=7;i>4;i--)                //发送7-5
  98.         {
  99.                 SI1602=dat1>>i&1;
  100.                 SCK1602=0;
  101.                 SCK1602=1;                        //上升沿移入数据
  102.         }
  103.        
  104.         for(i=1;i<5;i++)                //发送1-4
  105.         {
  106.                 SI1602=dat1>>i&1;
  107.                 SCK1602=0;
  108.                 SCK1602=1;                        //上升沿移入数据
  109.         }
  110.        
  111.         SI1602=dat1&1;                        //发送0
  112.         SCK1602=0;
  113.         SCK1602=1;
  114.        
  115.         RCK1602=0;
  116.         RCK1602=1;                                        //上升沿输出数据
  117. }

  118. void dis1602(uchar a,uchar b)        //a为0发送指令,为1发送数据 7654 3210
  119. {
  120.         a<<=7;
  121.        
  122.         Send1602(b>>3&0x1e|a);                        //1001 1110                高4位
  123.        
  124.         delay(2);
  125.        
  126.         Send1602(b>>3&0x1e|0x20|a);                //1011 1110                e使能信号
  127.        
  128.         delay(2);
  129.        
  130.         Send1602(b>>3&0x1e|a);                        //1001 1110                高4位
  131.        
  132.         delay(10);
  133.        
  134.         Send1602(b<<1&0x1e|a);                        //1001 1110                低4位
  135.        
  136.         delay(2);
  137.        
  138.         Send1602(b<<1&0x1e|0x20|a);                //1011 1110                e使能信号1011 0100
  139.        
  140.         delay(2);
  141.        
  142.         Send1602(b<<1&0x1e|a);                        //1001 1110                低4位
  143.        
  144.         delay(10);
  145. }

  146. void print1602(uchar a1,uchar *b1)
  147. {
  148.         dis1602(0,a1+0x80);                //定位光标地址
  149.        
  150.         while(*b1!='\0')
  151.         {
  152.                 dis1602(1,*b1++);
  153.         }
  154.         *b1=0;
  155. }

  156. void init1602()
  157. {
  158.         uchar i1;
  159.         delay(15);
  160.         dis1602(0,0x33);
  161.         dis1602(0,0x32);
  162.         dis1602(0,0x28);                //4位总线模式
  163.         dis1602(0,0x01);                //清屏
  164.         dis1602(0,0x06);                //写一个字符指针加一,光标加一
  165.         dis1602(0,0x0c);                //开显示 不显示光标
  166.        
  167.         print1602(0x00," 2018 08 12  W.1");
  168.         print1602(0x40," 10:20:10  31.7 ");       
  169.        
  170.         dis1602(0,0x40);
  171.         for(i1=0;i1<32;i1++)
  172.                 dis1602(1,zi1602[i1]);
  173.         dis1602(0,0x85);dis1602(1,1);
  174.         dis1602(0,0x88);dis1602(1,2);
  175.         dis1602(0,0x8b);dis1602(1,3);
  176.         dis1602(0,0xcf);dis1602(1,0);
  177.                
  178.         INT_CLKO|=0X40;                        //int4中断开关
  179. //        P3M1=1;                                        //p3.0 高阻输入
  180. }

  181. void getkey1602()
  182. {
  183.         keyy1=0;                                                        //keyy1置零
  184.         keynow[0]=keyx1;                                        //keynow状态等于keyx1
  185.         keynow[1]=keyx2;
  186.         keynow[2]=keyx3;
  187.         keynow[3]=keyx4;
  188.         keyy1=1;
  189.         if(keynow[0]==0&&keyold[0]==1)
  190.                 mode=0;
  191.         if(keynow[1]==0&&keyold[1]==1)
  192.                 IAP_CONTR=0x60;                                        //软复位
  193.         if(keynow[2]==0&&keyold[2]==1)
  194.                 if(++set==6)
  195.                         set=0;
  196.         if(keynow[3]==0&&keyold[3]==1)
  197.         {
  198.                 switch(set)
  199.                 {
  200.                         case 0:year++;break;
  201.                         case 1:if(++mon==13)mon=1;break;
  202.                         case 2:if(++day==32)day=1;break;
  203.                         case 3:if(++hour==24)hour=0;break;
  204.                         case 4:if(++min==60)min=0;break;
  205.                         case 5:if(++sec==60)sec=0;break;
  206.                         default:break;
  207.                 }
  208.                 week=((year/100/4)-year/100*2+year%100+year%100/4+26*(mon+1)/10+day-1)%7;
  209.                 if(week==0)
  210.                         week=7;
  211.         }
  212.         keyold[0]=keynow[0];
  213.         keyold[1]=keynow[1];
  214.         keyold[2]=keynow[2];
  215.         keyold[3]=keynow[3];
  216. }

  217. void init()
  218. {
  219.     P2M0=0x1B;                        //P2强推挽0001 1011
  220.     P3M0=0xE4;                        //P3强推挽1110 0100
  221.         P1ASF=0x80;                        //开启P1^7引脚模拟功能
  222.        
  223.         key=255;
  224.         S1=0;                                //pwm引脚置零
  225.        
  226.         EA=1;                                //中断总开关
  227.         ET0=1;                                //定时器0开关
  228.         AUXR |= 0x80;                //定时器时钟1T模式
  229.         TMOD &= 0xF0;                //设置定时器模式
  230.         TL0 = 0x88;                        //设置定时初值                10us
  231.         TH0 = 0xFF;                        //设置定时初值
  232.         TR0 = 1;                        //定时器0开始计时
  233.        
  234.         SCON|=0x40;                        //0100 0000                串口1工作模式1 开启接收
  235.         ES=1;                                //打开串口中断
  236.         PS=1;                                //串口最高中断优先级
  237.        
  238.         AUXR |= 0x05;                //定时器时钟1T模式 定时器2为串口1波特率
  239.         T2L = 0xC8;                        //设置定时初值
  240.         T2H = 0xFE;                        //设置定时初值
  241.         AUXR |= 0x10;                //定时器2开始计时
  242. }

  243. uint MAX6675_ReadReg()                //返回dat 0-65535 包含状态 温度值
  244. {
  245.         uchar i;   
  246.         uint dat; //     1111 1111 1111 1111
  247.          
  248.         i   = 0;   
  249.         dat = 0;   
  250.        
  251.         CS  = 0;                         //片选端,CS为低时、启动串行接口
  252.         SCK = 0;                     //串行时钟置零 准备输出  6675收到上升沿发送数据
  253.        
  254.         for(i=0; i<16; i++)                //get D15-D0 from 6675  从最高位开始接收16位数据
  255.         {      
  256.                 SCK = 1;                                //重置时钟 接收数据
  257.                 dat = dat<<1;                        //dat左移一位,1111 1111 1111 1110
  258.                 if( SO==1 )          
  259.                         dat = dat|0x01;                //收到高电平,个位改为1
  260.                 SCK = 0;                                //发送时钟信号,准备接收下一位数据
  261.         }
  262.         CS = 1;
  263.         SCK=1;
  264.           
  265.         return dat;   //
  266. }

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

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

  284. void getkey()
  285. {
  286.         uchar i;
  287.        
  288.         if(count2%16==0)                                                //16ms检测一次mode键
  289.         {
  290.                 keyy1=0;                                                        //keyy1置零
  291.                 keynow[0]=keyx1;                                        //keynow状态等于keyx1
  292.                 keynow[1]=keyx2;
  293.                 keyy1=1;
  294.                 if(keynow[0]==0&&keyold[0]==1)
  295.                         key=0;
  296.                 if(keynow[1]==0&&keyold[1]==1)
  297.                         IAP_CONTR=0x60;                                        //软复位
  298.                 keyold[0]=keynow[0];
  299.                 keyold[1]=keynow[1];
  300.         }
  301.        
  302.         if(count2%16==0&&mode==1)                        //模式1时,16ms检测一次按键
  303.         {
  304.                 keyy1=0;
  305.                 keynow[0]=keyx1;
  306.                 keynow[1]=keyx2;
  307.                 keynow[2]=keyx3;
  308.                 keynow[3]=keyx4;
  309.                
  310.                 keyy1=1;keyy2=0;
  311.                 keynow[4]=keyx1;
  312.                 keynow[5]=keyx2;
  313.                 keynow[6]=keyx3;
  314.                 keynow[7]=keyx4;

  315.                 keyy2=1;keyy3=0;
  316.                 keynow[8]=keyx1;
  317.                 keynow[9]=keyx2;
  318.                 keynow[10]=keyx3;
  319.                 keynow[11]=keyx4;

  320.                 keyy3=1;keyy4=0;
  321.                 keynow[12]=keyx1;
  322.                 keynow[13]=keyx2;
  323.                 keynow[14]=keyx3;
  324.                 keynow[15]=keyx4;


  325.                 keyy4=1;keyy5=0;
  326.                 keynow[16]=keyx1;
  327.                 keynow[17]=keyx2;
  328.                 keynow[18]=keyx3;
  329.                 keynow[19]=keyx4;
  330.                 keyy5=1;
  331.                
  332.                 for(i=0;i<20;i++)
  333.                 {
  334.                         if(keynow[i]==0&&keyold[i]==1)
  335.                                 key=i;
  336.                        
  337.                         keyold[i]=keynow[i];
  338.                 }
  339.         }
  340. }

  341. void SendData(uchar dat)
  342. {
  343.         while(busy);                        //等待前面数据发送完成
  344.         busy=1;
  345.         SBUF=dat;
  346. }

  347. void SendString(char *s)
  348. {
  349.         while(*s)
  350.         {
  351.                 SendData(*s++);
  352.         }
  353. }

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

  359. void BANEEP()                                        //结束eeprom操作
  360. {
  361.         IAP_CONTR&=0X78;        //0111 1000
  362.         IAP_CMD=0;
  363.         IAP_TRIG=0;
  364. }

  365. void Write_EEP(uint addr,uchar dat)        //地址addr,写入dat
  366. {
  367.         IAP_ADDRH=addr>>8;
  368.         IAP_ADDRL=addr;
  369.         IAP_DATA=dat;
  370.         IAP_CMD=2;
  371.         IAP_TRIG=0X5A;
  372.         IAP_TRIG=0XA5;
  373. }

  374. uchar Read_EEP(uint addr)                        //地址addr读取数据
  375. {
  376.         IAP_ADDRH=addr>>8;
  377.         IAP_ADDRL=addr;
  378.         IAP_CMD=1;
  379.         IAP_TRIG=0X5A;
  380.         IAP_TRIG=0XA5;
  381.         return IAP_DATA;
  382. }
  383. ///////////////////////////////
  384. //void Read_EEP2(uint addr)                        //地址addr读取数据
  385. //{
  386. //        IAP_ADDRH=addr>>8;
  387. //        IAP_ADDRL=addr;
  388. //        IAP_CMD=1;
  389. //        IAP_TRIG=0X5A;
  390. //        IAP_TRIG=0XA5;
  391. //}

  392. void Write_EEP2(uint addr,uchar dat)        //地址addr,写入dat
  393. {
  394.         IAP_ADDRH=addr>>8;
  395.         IAP_ADDRL=addr;
  396.         IAP_DATA=dat;
  397.         IAP_CMD=2;
  398.         IAP_TRIG=0X5A;
  399.         IAP_TRIG=0XA5;
  400. }

  401. /////////////////////////////////////
  402. void EraseSector_EEP(uint addr)        //清空扇区
  403. {
  404.         IAP_ADDRH=addr>>8;
  405.         IAP_ADDRL=addr;
  406.         IAP_CMD=3;
  407.         IAP_TRIG=0X5A;
  408.         IAP_TRIG=0XA5;
  409. }

  410. void RECORD_1602()                                                //记录1602时间
  411. {
  412.         INITEEP();
  413.        
  414.         for(num=0;num<512;num+=8)                                        //八字节一组 读第一字节
  415.         {
  416.                 if(Read_EEP(sto1602+num)==0xff)        //读出未写字符跳出
  417.                         break;
  418.         }
  419.        
  420.         value=num;
  421.         Write_EEP(sto1602+num,0);                                //第一字节置零
  422.         Write_EEP(sto1602+num+1,year/100);
  423.         Write_EEP(sto1602+num+2,year%100);
  424.         Write_EEP(sto1602+num+3,mon);
  425.         Write_EEP(sto1602+num+4,day);
  426.         Write_EEP(sto1602+num+5,hour);
  427.         Write_EEP(sto1602+num+6,min);
  428.         Write_EEP(sto1602+num+7,0);                        //最后字节置零
  429.        
  430.         BANEEP();
  431. }


  432. void READ_1602()
  433. {
  434.         uchar temp;
  435.         INITEEP();
  436.        
  437.         for(num=0;num<512;num+=8)                                        //八字节一组 读第一字节
  438.         {
  439.                 temp=Read_EEP(sto1602+num);
  440.                 if(temp==0xff)        //读出未写字符跳出
  441.                         break;
  442.         }                                                                        //如扇区满,num=512跳出循环
  443.        
  444.         if(num==0)                                                        //无数据返回
  445.                 return;
  446.        
  447.         while(Read_EEP(sto1602+num-1)!=0)                //如果前一组不完整,前跳一组
  448.         {
  449.                 num-=8;
  450.                 if(num==0)                                                //无数据返回
  451.                         return;
  452.         }
  453.        
  454.         num-=8;                                                                //读取空白前一组
  455.        
  456.         value=num;
  457.        
  458.         year=Read_EEP(sto1602+num+1)*100;
  459.         year+=Read_EEP(sto1602+num+2);
  460.         mon=Read_EEP(sto1602+num+3);
  461.         day=Read_EEP(sto1602+num+4);
  462.         hour=Read_EEP(sto1602+num+5);
  463.         min=Read_EEP(sto1602+num+6);
  464.         week=((year/100/4)-year/100*2+year%100+year%100/4+26*(mon+1)/10+day-1)%7;
  465.         if(week==0)
  466.                 week=7;
  467.        
  468.         if(num==504)                                                        //扇区满清空
  469.         {
  470.                 EraseSector_EEP(sto1602);                //清空扇区
  471.                 RECORD_1602();                                        //记录当前数据
  472.         }
  473.                
  474.         BANEEP();
  475. }

  476. void operation()
  477. {
  478.         if(count2%16==0)
  479.         {
  480.                 switch(key)
  481.                 {
  482.                         case 0:        key=255;mode++;if(mode==5){mode=0;S1=0;}break;//3个模式
  483.                         case 1:                break;
  484.                         case 2:                break;
  485.                         case 3:                break;
  486.                         case 4:        key=255;x=1;        break;
  487.                         case 5:        key=255;x=2;        break;
  488.                         case 6:        key=255;x=3;        break;
  489.                         case 7:        key=255;OP1=1;        break;        // +
  490.                         case 8:        key=255;x=4;        break;
  491.                         case 9:        key=255;x=5;        break;
  492.                         case 10:key=255;x=6;        break;
  493.                         case 11:key=255;OP1=2;        break;        // -
  494.                         case 12:key=255;x=7;        break;
  495.                         case 13:key=255;x=8;        break;
  496.                         case 14:key=255;x=9;        break;
  497.                         case 15:key=255;OP1=3;        break;        // *
  498.                         case 16:key=255;x=0;        break;
  499.                         case 17:key=255;OP2=1;        break;        // =
  500.                         case 18:key=255;OP2=2;        break;        // c
  501.                         case 19:key=255;OP1=4;        break;        // /
  502.                        
  503.                         default:        break;
  504.                 }
  505.                
  506.                 if(mode==1)
  507.                 {
  508.                         if(OP1==0&&x!=255)
  509.                         {
  510.                                 value1=value1*10+x;
  511.                                 x=255;
  512.                                 value=value1;
  513.                         }
  514.                        
  515.                         if(OP1!=0&&x!=255)
  516.                         {
  517.                                 value2=value2*10+x;
  518.                                 x=255;
  519.                                 value=value2;
  520.                         }

  521.                         if(OP2==1)                                                        //输入 =
  522.                         {
  523.                                 OP2=0;
  524.                                
  525.                                 switch(OP1)
  526.                                 {
  527.                                         case 0:        value=value1;SendString("");                        break;
  528.                                         case 1:        value=value1+value2;                break;
  529.                                         case 2:        value=value1-value2;                break;
  530.                                         case 3:        value=value1*value2;                break;
  531.                                         case 4:        value=value1/value2;                break;
  532.                                        
  533.                                         default:        break;
  534.                                 }
  535.                                 OP1=OP2=DOP2=tOP2=value1=value2=0;
  536.                         }
  537.                        
  538.                         if(DOP2==1)
  539.                                 tOP2++;
  540.                         if(tOP2==30)
  541.                                 DOP2=0;
  542.                         if(OP2==2&&DOP2==1)                                                //双击C清空所有数据
  543.                                 OP1=OP2=DOP2=tOP2=value1=value2=value=0;
  544.                        
  545.                         if(OP2==2)                                                                //单击C清除数据
  546.                         {
  547.                                 OP2=0;
  548.                                 DOP2=1;tOP2=0;
  549.                                 if(OP1==0)
  550.                                         value=value1=0;
  551.                                 else
  552.                                         value=value2=0;
  553.                         }
  554.                 }
  555.         }
  556. }

  557. void display()
  558. {
  559.         if(mode==0)
  560.         {
  561.                 gettemp();
  562.                
  563.                 switch(count)                                        //显示温度
  564.                 {
  565.                         case 0:B4=1;if(temp/1000==0)break;                disduan(duan[temp/1000]);        diswei(wei[count]);break;        //显示第1管 为0不显示
  566.                         case 1:B1=1;disduan(duan[temp/100%10]);        diswei(wei[count]);break;                                                                //显示第2管
  567.                         case 2:B2=1;disduan(duan[temp/10%10]);        diswei(wei[count]);DP=1;break;                                                        //显示第3管 带小数点
  568.                         case 3:B3=1;disduan(duan[temp%10]);                diswei(wei[count]);break;                                                                //显示第4管
  569.                        
  570.                         default: break;
  571.                 }
  572.         }
  573.        
  574.         if(mode==1)
  575.         {
  576.                 switch(count)                                        //显示按键 计算器
  577.                 {
  578.                         case 0:B4=1;if(value/1000==0)break;        disduan(duan[value/1000]);                diswei(wei[count]);break;                        //显示第1管
  579.                         case 1:B1=1;if(value/100==0)break;        disduan(duan[value/100%10]);        diswei(wei[count]);break;                        //显示第2管
  580.                         case 2:B2=1;if(value/10==0)break;        disduan(duan[value/10%10]);                diswei(wei[count]);break;                        //显示第3管
  581.                         case 3:B3=1;                                                disduan(duan[value%10]);                diswei(wei[count]);break;                        //显示第4管
  582.                        
  583.                         default: break;
  584.                 }
  585.         }
  586.        
  587.         if(mode==2)
  588.         {
  589.                 if(count==0)
  590.                 {
  591.                         getadc();
  592.                         adc=adc*5000/1023;                        //1000倍电压值 adc*5v/1023*1000
  593.                 }
  594.                
  595.                 switch(count)                                        //显示电压
  596.                 {
  597.                         case 0:B4=1;disduan(duan[adc/1000]);        diswei(wei[count]);DP=1;break;                //显示第1管 带小数点
  598.                         case 1:B1=1;disduan(duan[adc/100%10]);        diswei(wei[count]);break;                        //显示第2管
  599.                         case 2:B2=1;disduan(duan[adc/10%10]);        diswei(wei[count]);break;                        //显示第3管       
  600.                         case 3:B3=1;disduan(duan[adc%10]);                diswei(wei[count]);break;                        //显示第4管       
  601.                        
  602.                         default: break;
  603.                 }
  604.         }
  605.        
  606.         while(mode==3)                                                                //模式3 pwm循环
  607.         {
  608.                 t0=0;
  609.                 pwmflag=!pwmflag;
  610.                
  611.                 if(pwmflag==1) S1=1;                                        //pwm高电平
  612.                 B4=1;disduan(duan[16]);diswei(wei[0]);        //显示数码管1
  613.                 getadc();                                                                //获取adc 0-1023
  614.                 adc=adc/10+100;                                                        //100-202
  615.                 if(adc>200)                                                                //100-200
  616.                         adc=200;
  617.                
  618.                 while(t0!=adc);
  619.                 S1=0;                                                                        //pwm低电平
  620.                
  621.                 while(t0!=250);
  622.                 B1=1;disduan(duan[adc/100%10]);        diswei(wei[1]);//显示数码管2

  623.                
  624.                 while(t0!=500);
  625.                 B2=1;disduan(duan[adc/10%10]);        diswei(wei[2]);//显示数码管3
  626.                
  627.                 while(t0!=750);
  628.                 B3=1;disduan(duan[adc%10]);        diswei(wei[3]);//显示数码管4
  629.                
  630.                                                         //检测mode按键
  631.                 keyy1=0;                                                        //keyy1置零
  632.                 keynow[0]=keyx1;                                        //keynow状态等于keyx1
  633.                 keynow[1]=keyx2;
  634.                 keyy1=1;
  635.                 if(keynow[0]==0&&keyold[0]==1)
  636.                 {
  637.                         mode=4;                                                        //符合条件mode回零,跳出pwm模式循环
  638.                         B4=1;
  639.                 }
  640.                 if(keynow[1]==0&&keyold[1]==1)
  641.                         IAP_CONTR=0x60;                                        //软复位
  642.                 keyold[0]=keynow[0];
  643.                 keyold[1]=keynow[1];
  644.                
  645.                 while(t0!=1000);                                        //10ms一个周期
  646.         }
  647.        
  648.         if(mode==4)
  649.         {
  650.                 TL0 = 0x20;                //设置定时初值                1ms
  651.                 TH0 = 0xD1;                //设置定时初值

  652.                 init1602();
  653.                 READ_1602();
  654.                
  655.                 while(mode==4)
  656.                 {
  657.                         t0=0;
  658.                         getkey1602();
  659.                        
  660.                         if(++sec==60)
  661.                         {
  662.                                 sec=0;
  663.                                 min++;
  664. //                                RECORD_1602();
  665.                         }
  666.                         dis1602(0,0xc7);dis1602(1,sec/10+0x30);dis1602(1,sec%10+0x30);
  667.                         B4=1;disduan(duan[value/1000]);diswei(wei[0]);        //显示数码管1
  668.                         while(t0!=100);
  669.                        
  670.                         getkey1602();
  671.                        
  672.                         if(min==60)
  673.                         {
  674.                                 min=0;
  675.                                 hour++;
  676.                         }
  677.                         dis1602(0,0xc4);dis1602(1,min/10+0x30);dis1602(1,min%10+0x30);
  678.                        
  679.                         while(t0!=200);

  680.                         getkey1602();
  681.                        
  682.                         if(hour==24)
  683.                         {
  684.                                 hour=0;
  685.                                 day++;
  686.                                 if(++week==8)
  687.                                         week=1;
  688.                         }
  689.                         dis1602(0,0xc1);dis1602(1,hour/10+0x30);dis1602(1,hour%10+0x30);
  690.                         B1=1;disduan(duan[value/100%10]);        diswei(wei[1]);//显示数码管2
  691.                         while(t0!=300);
  692.                        
  693.                         getkey1602();
  694.                        
  695.                         if((mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)&&day==32)
  696.                         {
  697.                                 day=1;
  698.                                 mon++;
  699.                         }
  700.                         else if((mon==4||mon==6||mon==9||mon==11)&&day==31)
  701.                         {
  702.                                 day=1;
  703.                                 mon++;
  704.                         }
  705.                         else if(((year)%4!=0||((year)%100==0&&(year)%400!=0))&&mon==2&&day==29)
  706.                         {
  707.                                 day=1;
  708.                                 mon++;
  709.                         }
  710.                         else if(((year)%4==0&&(year)%100!=0||(year)%400==0)&&mon==2&&day==30)
  711.                         {
  712.                                 day=1;
  713.                                 mon++;
  714.                         }
  715.                         dis1602(0,0x89);dis1602(1,day/10+0x30);dis1602(1,day%10+0x30);
  716.                        
  717.                         while(t0!=400);
  718.                        
  719.                         getkey1602();
  720.                        
  721.                         dis1602(0,0x8f);dis1602(1,week+0x30);
  722.                        
  723.                         while(t0!=500);
  724.                        
  725.                         getkey1602();
  726.                        
  727.                         if(mon==13)
  728.                         {
  729.                                 mon=1;
  730.                                 year++;
  731.                         }
  732.                         dis1602(0,0x86);dis1602(1,mon/10+0x30);dis1602(1,mon%10+0x30);
  733.                         B2=1;disduan(duan[value/10%10]);        diswei(wei[2]);//显示数码管3
  734.                         while(t0!=600);
  735.                        
  736.                         getkey1602();
  737.                        
  738.                         dis1602(0,0x83);dis1602(1,year%100/10+0x30);dis1602(1,year%10+0x30);
  739.                        
  740.                         while(t0!=700);
  741.                        
  742.                         getkey1602();
  743.                        
  744.                         dis1602(0,0x81);dis1602(1,year/1000+0x30);dis1602(1,year%1000/100+0x30);
  745.                        
  746.                         while(t0!=800);
  747.                        
  748.                         getkey1602();
  749.                        
  750.                         temp=MAX6675_ReadReg();                //读取状态数据0-65535     1111 1111 1111 1111 fedc ba98 7654 3210
  751.                         temp=((temp<<1)>>4)*5/2;        //读出来的数据的D3~D14是温度值 左移1位,右移4位 乘5/2 10倍温度值
  752.                        
  753.                         dis1602(0,0xcb);dis1602(1,temp%1000/100+0x30);dis1602(1,temp%100/10+0x30);
  754.                        
  755.                         while(t0!=900);
  756.                        
  757.                         getkey1602();
  758.                        
  759.                         dis1602(0,0xce);dis1602(1,temp%10+0x30);
  760.                         B3=1;disduan(duan[value%10]);        diswei(wei[3]);//显示数码管4
  761.                         while(t0!=1000);
  762.                 }
  763.                
  764.                 TL0 = 0x88;                        //设置定时初值                10us
  765.                 TH0 = 0xFF;                        //设置定时初值
  766.         }
  767. }

  768. main()
  769. {
  770.         init();
  771.        
  772.     while(1)//
  773.     {
  774.                 delay(1);                                //系统周期1毫秒

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

  776.                 count2++;                                //0-255循环

  777.                 getkey();                                //运行一次80us  16ms运行一次
  778.                
  779.                 operation();

  780.                 display();
  781.     }
  782. }

  783. void Uart1_Routine() interrupt 4 using 3
  784. {
  785.         if(RI)
  786.         {
  787.                 RI=0;                                //清除RI标志
  788.                 value=SBUF;
  789.         }
  790.        
  791.         if(TI)
  792.         {
  793.                 TI=0;                                //清除TI标志
  794.                 busy=0;
  795.         }
  796. }

  797. void Int4_Routine() interrupt 16 using 3
  798. {       
  799.         uint num1;
  800.        
  801.         IE=0;
  802.         TCON=0;
  803.         AUXR=0;
  804.         SCON=0;
  805.         P2M0=0;
  806.         P3M0=0;
  807.         B1=B2=B3=B4=1;

  808.         INITEEP();

  809.         for(num1=0;num1<512;num1+=8)                                        //八字节一组 读第一字节
  810.         {               
  811.                 IAP_ADDRH=(sto1602+num1)>>8;
  812.                 IAP_ADDRL=(sto1602+num1);
  813.                 IAP_CMD=1;
  814.                 IAP_TRIG=0X5A;
  815.                 IAP_TRIG=0XA5;
  816.        
  817.                 if(IAP_DATA==0xff)        //读出未写字符跳出
  818.                         break;
  819.         }


  820.         value=num1;
  821.         Write_EEP2(sto1602+num1,0);                                //第一字节置零
  822.         Write_EEP2(sto1602+num1+1,year/100);
  823.         Write_EEP2(sto1602+num1+2,year%100);
  824.         Write_EEP2(sto1602+num1+3,mon);
  825.         Write_EEP2(sto1602+num1+4,day);
  826.         Write_EEP2(sto1602+num1+5,hour);
  827.         Write_EEP2(sto1602+num1+6,min);
  828.         Write_EEP2(sto1602+num1+7,0);                        //最后字节置零
  829.        
  830.         BANEEP();
  831.        
  832. //        while(1)
  833. //        {
  834. //                B4=1;disduan(duan[value/1000]);diswei(wei[0]);        //显示数码管1
  835. //                B1=1;disduan(duan[value/100%10]);        diswei(wei[1]);//显示数码管2
  836. //                B2=1;disduan(duan[value/10%10]);        diswei(wei[2]);//显示数码管3
  837. //                B3=1;disduan(duan[value%10]);        diswei(wei[3]);//显示数码管4
  838. //        }
  839. }

  840. void Timer0_Routine() interrupt 1 using 2
  841. {
  842.         t0++;                                //10us
  843. }
复制代码


评分

参与人数 1牛币 +10 收起 理由
飞来峰 + 10 写的不错!

查看全部评分

发表于 2018-8-19 21:38:32 | 显示全部楼层
进来围观单片机掉电保存数据电路,程序 电容 作者:1121454314 2407 单片机掉电保存数据电路,程序 电容 作者:1121454314 7324
回复 支持 反对

使用道具 举报

发表于 2018-8-19 21:47:29 | 显示全部楼层
read函数里面都没有读寄存器操作,怎么可能正常呢
回复 支持 反对

使用道具 举报

发表于 2018-8-19 22:24:58 | 显示全部楼层
路过帮顶
回复 支持 反对

使用道具 举报

发表于 2018-8-20 13:21:14 | 显示全部楼层
看来是个很重要的应用。
回复 支持 反对

使用道具 举报

发表于 2018-8-20 14:13:40 | 显示全部楼层
路过看看
回复 支持 反对

使用道具 举报

发表于 2018-8-20 18:57:55 | 显示全部楼层
路过帮顶
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-20 20:18:03 | 显示全部楼层
我爱萝丽爱萝丽 发表于 2018-8-19 21:47
read函数里面都没有读寄存器操作,怎么可能正常呢

萝丽大神好单片机掉电保存数据电路,程序 电容 作者:coolbgo 2616

如果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;
}
这样也试过,返回的值不对。
回复 支持 反对

使用道具 举报

发表于 2018-8-23 14:06:08 | 显示全部楼层
受教了  虽然还是不懂
回复 支持 反对

使用道具 举报

发表于 2018-8-23 19:57:01 | 显示全部楼层
受教了  虽然还是不懂
发电子论坛吧
回复 支持 反对

使用道具 举报

发表于 2019-3-30 23:26:24 | 显示全部楼层
我新手,感觉单片机语言和我学的java差好多,直接看不懂
回复 支持 反对

使用道具 举报

发表于 2019-4-9 06:19:08 | 显示全部楼层
看不懂
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-4-13 11:47:03 | 显示全部楼层

半年没看单片机了,我自己也看不懂了  哈哈单片机掉电保存数据电路,程序 电容 作者:coolbgo 4451
回复 支持 反对

使用道具 举报

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

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|关于模吧|APP下载|广告报价|手机版|企业会员|商城入驻|联系我们|模吧 ( 黔ICP备2022002348号-1 )

© 2013-2020 Moz8.com 模吧,玩出精彩!