模吧

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

3013查看 | 21回复

[DIY交流] 新手diy万年历闹钟

[复制链接]
发表于 2018-8-12 21:31:44 | 显示全部楼层 |阅读模式

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

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

x
新手diy万年历闹钟 DIY 作者:coolbgo 4144 自学单片机一个月
diy一个万年历闹钟
1602 用锁存器74HC595N三根线控制 4位总线驱动
  1. #include<reg51.h>

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

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

  7. sfr AUXR=0x8e;                //声明辅助寄存器

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

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

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

  14. sfr IAP_CONTR=0xc7;        //定义IAP控制寄存器

  15. sbit DA=P2^4;                        //数码管位选
  16. sbit DB=P3^2;
  17. sbit DC=P3^6;
  18. sbit DD=P2^0;
  19. sbit DE=P2^1;
  20. sbit DF=P2^3;
  21. sbit DG=P3^5;
  22. sbit DP=P3^7;

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

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

  30. sbit keyx1=P2^6;                                        //定义键盘键位
  31. sbit keyx2=P2^7;
  32. sbit keyx3=P1^0;
  33. sbit keyx4=P1^1;
  34. sbit keyy1=P1^2;
  35. sbit keyy2=P1^3;
  36. sbit keyy3=P1^4;
  37. sbit keyy4=P1^5;
  38. sbit keyy5=P1^6;

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

  40. sbit SCK1602=P1^4;
  41. sbit RCK1602=P1^5;
  42. sbit SI1602=P1^6;

  43. bit busy,pwmflag;

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

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

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

  48. uchar code zi1602[]=
  49. {
  50.         0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00,                //℃        0x00
  51.         0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x00,                //年        0x01
  52.         0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00,                //月        0x02
  53.         0x1f,0x11,0x11,0x1f,0x11,0x11,0x1f,0x00,                //日        0x03
  54. };
  55. uchar mon,day,hour,min,sec,set;
  56. uint year=2018;

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

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

  60. void disduan(uchar dd)
  61. {
  62.         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;
  63. }

  64. void diswei(uchar dw)
  65. {
  66.         B1=dw>>3&1;B2=dw>>2&1;B3=dw>>1&1;B4=dw&1;
  67. }

  68. void delay(uint n)                //@12.000MHz
  69. {
  70.     uchar i, j;
  71.         while(n--)
  72.         {
  73.                 i = 12;
  74.                 j = 169;
  75.                 do
  76.                 {
  77.                         while (--j);
  78.                 } while (--i);
  79.         }
  80. }

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

  84.        
  85.         for(i=7;i>4;i--)                //发送7-5
  86.         {
  87.                 SI1602=dat1>>i&1;
  88.                 SCK1602=0;
  89.                 SCK1602=1;                        //上升沿移入数据
  90.         }
  91.        
  92.         for(i=1;i<5;i++)                //发送1-4
  93.         {
  94.                 SI1602=dat1>>i&1;
  95.                 SCK1602=0;
  96.                 SCK1602=1;                        //上升沿移入数据
  97.         }
  98.        
  99.         SI1602=dat1&1;                        //发送0
  100.         SCK1602=0;
  101.         SCK1602=1;
  102.        
  103.         RCK1602=0;
  104.         RCK1602=1;                                        //上升沿输出数据
  105. }

  106. void dis1602(uchar a,uchar b)        //a为0发送指令,为1发送数据 7654 3210
  107. {
  108.         a<<=7;
  109.        
  110.         Send1602(b>>3&0x1e|a);                        //1001 1110                高4位
  111.        
  112.         delay(2);
  113.        
  114.         Send1602(b>>3&0x1e|0x20|a);                //1011 1110                e使能信号
  115.        
  116.         delay(2);
  117.        
  118.         Send1602(b>>3&0x1e|a);                        //1001 1110                高4位
  119.        
  120.         delay(10);
  121.        
  122.         Send1602(b<<1&0x1e|a);                        //1001 1110                低4位
  123.        
  124.         delay(2);
  125.        
  126.         Send1602(b<<1&0x1e|0x20|a);                //1011 1110                e使能信号1011 0100
  127.        
  128.         delay(2);
  129.        
  130.         Send1602(b<<1&0x1e|a);                        //1001 1110                低4位
  131.        
  132.         delay(10);
  133. }

  134. void print1602(uchar a1,uchar *b1)
  135. {
  136.         dis1602(0,a1+0x80);                //定位光标地址
  137.        
  138.         while(*b1!='\0')
  139.         {
  140.                 dis1602(1,*b1++);
  141.         }
  142.         *b1=0;
  143. }

  144. void init1602()
  145. {
  146.         uchar i1;
  147.        
  148.         dis1602(0,0x32);
  149.         dis1602(0,0x28);                //4位总线模式
  150.         dis1602(0,0x01);                //清屏
  151.         dis1602(0,0x06);                //写一个字符指针加一,光标加一
  152.         dis1602(0,0x0c);                //开显示 不显示光标
  153.        
  154.         print1602(0,"2018 08 12 31.7 ");
  155.         print1602(0x40,"    10:20:10    ");       
  156.        
  157.         dis1602(0,0x40);
  158.         for(i1=0;i1<32;i1++)
  159.                 dis1602(1,zi1602[i1]);
  160.         dis1602(0,0x84);dis1602(1,1);
  161.         dis1602(0,0x87);dis1602(1,2);
  162.         dis1602(0,0x8a);dis1602(1,3);
  163.         dis1602(0,0x8f);dis1602(1,0);
  164. }

  165. void getkey1602()
  166. {
  167.         keyy1=0;                                                        //keyy1置零
  168.         keynow[0]=keyx1;                                        //keynow状态等于keyx1
  169.         keynow[1]=keyx2;
  170.         keynow[2]=keyx3;
  171.         keynow[3]=keyx4;
  172.         keyy1=1;
  173.         if(keynow[0]==0&&keyold[0]==1)
  174.                 mode=0;
  175.         if(keynow[1]==0&&keyold[1]==1)
  176.                 IAP_CONTR=0x60;                                        //软复位
  177.         if(keynow[2]==0&&keyold[2]==1)
  178.                 if(++set==6)
  179.                         set=0;
  180.         if(keynow[3]==0&&keyold[3]==1)
  181.         {
  182.                 switch(set)
  183.                 {
  184.                         case 0:year++;break;
  185.                         case 1:if(++mon==13)mon=1;break;
  186.                         case 2:if(++day==32)day=1;break;
  187.                         case 3:if(++hour==24)hour=0;break;
  188.                         case 4:if(++min==60)min=0;break;
  189.                         case 5:if(++sec==60)sec=0;break;
  190.                         default:break;
  191.                 }
  192.         }
  193.         keyold[0]=keynow[0];
  194.         keyold[1]=keynow[1];
  195.         keyold[2]=keynow[2];
  196.         keyold[3]=keynow[3];
  197. }

  198. void init()
  199. {
  200.     P2M0=0x1B;                        //P2强推挽0001 1011
  201.     P3M0=0xE4;                        //P3强推挽1110 0100
  202.         P1ASF=0x80;                        //开启P1^7引脚模拟功能
  203.        
  204.         key=255;
  205.         S1=0;                                //pwm引脚置零
  206.        
  207.         EA=1;                                //中断总开关
  208.         ET0=1;                                //定时器0开关
  209.         AUXR |= 0x80;                //定时器时钟1T模式
  210.         TMOD &= 0xF0;                //设置定时器模式
  211.         TL0 = 0x88;                        //设置定时初值                10us
  212.         TH0 = 0xFF;                        //设置定时初值
  213.         TR0 = 1;                        //定时器0开始计时
  214.        
  215.         SCON|=0x40;                        //0100 0000                串口1工作模式1 开启接收
  216.         ES=1;                                //打开串口中断
  217.         PS=1;                                //串口最高中断优先级
  218.        
  219.         AUXR |= 0x05;                //定时器时钟1T模式 定时器2为串口1波特率
  220.         T2L = 0xC8;                        //设置定时初值
  221.         T2H = 0xFE;                        //设置定时初值
  222.         AUXR |= 0x10;                //定时器2开始计时
  223.         REN=1;                                //开始接收串口数据
  224. }

  225. uint MAX6675_ReadReg()                //返回dat 0-65535 包含状态 温度值
  226. {
  227.         uchar i;   
  228.         uint dat; //     1111 1111 1111 1111
  229.          
  230.         i   = 0;   
  231.         dat = 0;   
  232.        
  233.         CS  = 0;                         //片选端,CS为低时、启动串行接口
  234.         SCK = 0;                     //串行时钟置零 准备输出  6675收到上升沿发送数据
  235.        
  236.         for(i=0; i<16; i++)                //get D15-D0 from 6675  从最高位开始接收16位数据
  237.         {      
  238.                 SCK = 1;                                //重置时钟 接收数据
  239.                 dat = dat<<1;                        //dat左移一位,1111 1111 1111 1110
  240.                 if( SO==1 )          
  241.                         dat = dat|0x01;                //收到高电平,个位改为1
  242.                 SCK = 0;                                //发送时钟信号,准备接收下一位数据
  243.         }
  244.         CS = 1;
  245.         SCK=1;
  246.           
  247.         return dat;   //
  248. }

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

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

  266. void getkey()
  267. {
  268.         uchar i;
  269.        
  270.         if(count2%16==0)                                                //16ms检测一次mode键
  271.         {
  272.                 keyy1=0;                                                        //keyy1置零
  273.                 keynow[0]=keyx1;                                        //keynow状态等于keyx1
  274.                 keynow[1]=keyx2;
  275.                 keyy1=1;
  276.                 if(keynow[0]==0&&keyold[0]==1)
  277.                         key=0;
  278.                 if(keynow[1]==0&&keyold[1]==1)
  279.                         IAP_CONTR=0x60;                                        //软复位
  280.                 keyold[0]=keynow[0];
  281.                 keyold[1]=keynow[1];
  282.         }
  283.        
  284.         if(count2%16==0&&mode==1)                        //模式1时,16ms检测一次按键
  285.         {
  286.                 keyy1=0;
  287.                 keynow[0]=keyx1;
  288.                 keynow[1]=keyx2;
  289.                 keynow[2]=keyx3;
  290.                 keynow[3]=keyx4;
  291.                
  292.                 keyy1=1;keyy2=0;
  293.                 keynow[4]=keyx1;
  294.                 keynow[5]=keyx2;
  295.                 keynow[6]=keyx3;
  296.                 keynow[7]=keyx4;

  297.                 keyy2=1;keyy3=0;
  298.                 keynow[8]=keyx1;
  299.                 keynow[9]=keyx2;
  300.                 keynow[10]=keyx3;
  301.                 keynow[11]=keyx4;

  302.                 keyy3=1;keyy4=0;
  303.                 keynow[12]=keyx1;
  304.                 keynow[13]=keyx2;
  305.                 keynow[14]=keyx3;
  306.                 keynow[15]=keyx4;


  307.                 keyy4=1;keyy5=0;
  308.                 keynow[16]=keyx1;
  309.                 keynow[17]=keyx2;
  310.                 keynow[18]=keyx3;
  311.                 keynow[19]=keyx4;
  312.                 keyy5=1;
  313.                
  314.                 for(i=0;i<20;i++)
  315.                 {
  316.                         if(keynow[i]==0&&keyold[i]==1)
  317.                                 key=i;
  318.                        
  319.                         keyold[i]=keynow[i];
  320.                 }
  321.         }
  322. }

  323. void SendData(uchar dat)
  324. {
  325.         while(busy);                        //等待前面数据发送完成
  326.         busy=1;
  327.         SBUF=dat;
  328. }

  329. void SendString(char *s)
  330. {
  331.         while(*s)
  332.         {
  333.                 SendData(*s++);
  334.         }
  335. }

  336. void operation()
  337. {
  338.         if(count2%16==0)
  339.         {
  340.                 switch(key)
  341.                 {
  342.                         case 0:        key=255;mode++;if(mode==5){mode=0;S1=0;}break;//3个模式
  343.                         case 1:                break;
  344.                         case 2:                break;
  345.                         case 3:                break;
  346.                         case 4:        key=255;x=1;        break;
  347.                         case 5:        key=255;x=2;        break;
  348.                         case 6:        key=255;x=3;        break;
  349.                         case 7:        key=255;OP1=1;        break;        // +
  350.                         case 8:        key=255;x=4;        break;
  351.                         case 9:        key=255;x=5;        break;
  352.                         case 10:key=255;x=6;        break;
  353.                         case 11:key=255;OP1=2;        break;        // -
  354.                         case 12:key=255;x=7;        break;
  355.                         case 13:key=255;x=8;        break;
  356.                         case 14:key=255;x=9;        break;
  357.                         case 15:key=255;OP1=3;        break;        // *
  358.                         case 16:key=255;x=0;        break;
  359.                         case 17:key=255;OP2=1;        break;        // =
  360.                         case 18:key=255;OP2=2;        break;        // c
  361.                         case 19:key=255;OP1=4;        break;        // /
  362.                        
  363.                         default:        break;
  364.                 }
  365.                
  366.                 if(mode==1)
  367.                 {
  368.                         if(OP1==0&&x!=255)
  369.                         {
  370.                                 value1=value1*10+x;
  371.                                 x=255;
  372.                                 value=value1;
  373.                         }
  374.                        
  375.                         if(OP1!=0&&x!=255)
  376.                         {
  377.                                 value2=value2*10+x;
  378.                                 x=255;
  379.                                 value=value2;
  380.                         }

  381.                         if(OP2==1)                                                        //输入 =
  382.                         {
  383.                                 OP2=0;
  384.                                
  385.                                 switch(OP1)
  386.                                 {
  387.                                         case 0:        value=value1;SendString("");                        break;
  388.                                         case 1:        value=value1+value2;                break;
  389.                                         case 2:        value=value1-value2;                break;
  390.                                         case 3:        value=value1*value2;                break;
  391.                                         case 4:        value=value1/value2;                break;
  392.                                        
  393.                                         default:        break;
  394.                                 }
  395.                                 OP1=OP2=DOP2=tOP2=value1=value2=0;
  396.                         }
  397.                        
  398.                         if(DOP2==1)
  399.                                 tOP2++;
  400.                         if(tOP2==30)
  401.                                 DOP2=0;
  402.                         if(OP2==2&&DOP2==1)                                                //双击C清空所有数据
  403.                                 OP1=OP2=DOP2=tOP2=value1=value2=value=0;
  404.                        
  405.                         if(OP2==2)                                                                //单击C清除数据
  406.                         {
  407.                                 OP2=0;
  408.                                 DOP2=1;tOP2=0;
  409.                                 if(OP1==0)
  410.                                         value=value1=0;
  411.                                 else
  412.                                         value=value2=0;
  413.                         }
  414.                 }
  415.         }
  416. }

  417. void display()
  418. {
  419.         if(mode==0)
  420.         {
  421.                 gettemp();
  422.                
  423.                 switch(count)                                        //显示温度
  424.                 {
  425.                         case 0:B4=1;if(temp/1000==0)break;                disduan(duan[temp/1000]);        diswei(wei[count]);break;        //显示第1管 为0不显示
  426.                         case 1:B1=1;disduan(duan[temp/100%10]);        diswei(wei[count]);break;                                                                //显示第2管
  427.                         case 2:B2=1;disduan(duan[temp/10%10]);        diswei(wei[count]);DP=1;break;                                                        //显示第3管 带小数点
  428.                         case 3:B3=1;disduan(duan[temp%10]);                diswei(wei[count]);break;                                                                //显示第4管
  429.                        
  430.                         default: break;
  431.                 }
  432.         }
  433.        
  434.         if(mode==1)
  435.         {
  436.                 switch(count)                                        //显示按键 计算器
  437.                 {
  438.                         case 0:B4=1;if(value/1000==0)break;        disduan(duan[value/1000]);                diswei(wei[count]);break;                        //显示第1管
  439.                         case 1:B1=1;if(value/100==0)break;        disduan(duan[value/100%10]);        diswei(wei[count]);break;                        //显示第2管
  440.                         case 2:B2=1;if(value/10==0)break;        disduan(duan[value/10%10]);                diswei(wei[count]);break;                        //显示第3管
  441.                         case 3:B3=1;                                                disduan(duan[value%10]);                diswei(wei[count]);break;                        //显示第4管
  442.                        
  443.                         default: break;
  444.                 }
  445.         }
  446.        
  447.         if(mode==2)
  448.         {
  449.                 if(count==0)
  450.                 {
  451.                         getadc();
  452.                         adc=adc*5000/1023;                        //1000倍电压值 adc*5v/1023*1000
  453.                 }
  454.                
  455.                 switch(count)                                        //显示电压
  456.                 {
  457.                         case 0:B4=1;disduan(duan[adc/1000]);        diswei(wei[count]);DP=1;break;                //显示第1管 带小数点
  458.                         case 1:B1=1;disduan(duan[adc/100%10]);        diswei(wei[count]);break;                        //显示第2管
  459.                         case 2:B2=1;disduan(duan[adc/10%10]);        diswei(wei[count]);break;                        //显示第3管       
  460.                         case 3:B3=1;disduan(duan[adc%10]);                diswei(wei[count]);break;                        //显示第4管       
  461.                        
  462.                         default: break;
  463.                 }
  464.         }
  465.        
  466.         while(mode==3)                                                                //模式3 pwm循环
  467.         {
  468.                 t0=0;
  469.                 pwmflag=!pwmflag;
  470.                
  471.                 if(pwmflag==1) S1=1;                                        //pwm高电平
  472.                 B4=1;disduan(duan[16]);diswei(wei[0]);        //显示数码管1
  473.                 getadc();                                                                //获取adc 0-1023
  474.                 adc=adc/10+100;                                                        //100-202
  475.                 if(adc>200)                                                                //100-200
  476.                         adc=200;
  477.                
  478.                 while(t0!=adc);
  479.                 S1=0;                                                                        //pwm低电平
  480.                
  481.                 while(t0!=250);
  482.                 B1=1;disduan(duan[adc/100%10]);        diswei(wei[1]);//显示数码管2

  483.                
  484.                 while(t0!=500);
  485.                 B2=1;disduan(duan[adc/10%10]);        diswei(wei[2]);//显示数码管3
  486.                
  487.                 while(t0!=750);
  488.                 B3=1;disduan(duan[adc%10]);        diswei(wei[3]);//显示数码管4
  489.                
  490.                                                         //检测mode按键
  491.                 keyy1=0;                                                        //keyy1置零
  492.                 keynow[0]=keyx1;                                        //keynow状态等于keyx1
  493.                 keynow[1]=keyx2;
  494.                 keyy1=1;
  495.                 if(keynow[0]==0&&keyold[0]==1)
  496.                 {
  497.                         mode=4;                                                        //符合条件mode回零,跳出pwm模式循环
  498.                         B4=1;
  499.                 }
  500.                 if(keynow[1]==0&&keyold[1]==1)
  501.                         IAP_CONTR=0x60;                                        //软复位
  502.                 keyold[0]=keynow[0];
  503.                 keyold[1]=keynow[1];
  504.                
  505.                 while(t0!=1000);                                        //10ms一个周期
  506.         }
  507.        
  508.         if(mode==4)
  509.         {
  510.                 TL0 = 0x20;                //设置定时初值                1ms
  511.                 TH0 = 0xD1;                //设置定时初值

  512.                 while(mode==4)
  513.                 {
  514.                         t0=0;
  515.                        
  516.                         getkey1602();
  517.                         while(t0!=100);
  518.                        
  519.                         if(++sec==60)
  520.                         {
  521.                                 sec=0;
  522.                                 min++;
  523.                         }
  524.                         dis1602(0,0xca);dis1602(1,sec/10+0x30);dis1602(1,sec%10+0x30);
  525.                        
  526.                         getkey1602();
  527.                         while(t0!=200);
  528.                        
  529.                         if(min==60)
  530.                         {
  531.                                 min=0;
  532.                                 hour++;
  533.                         }
  534.                         dis1602(0,0xc7);dis1602(1,min/10+0x30);dis1602(1,min%10+0x30);

  535.                         getkey1602();
  536.                         while(t0!=300);
  537.                        
  538.                         if(hour==24)
  539.                         {
  540.                                 hour=0;
  541.                                 day++;
  542.                         }
  543.                         dis1602(0,0xc4);dis1602(1,hour/10+0x30);dis1602(1,hour%10+0x30);
  544.                        
  545.                         getkey1602();
  546.                         while(t0!=400);
  547.                        
  548.                         if((mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)&&day==32)
  549.                         {
  550.                                 day=1;
  551.                                 mon++;
  552.                         }
  553.                         else if((mon==4||mon==6||mon==9||mon==11)&&day==31)
  554.                         {
  555.                                 day=1;
  556.                                 mon++;
  557.                         }
  558.                         else if(((year)%4!=0||((year)%100==0&&(year)%400!=0))&&mon==2&&day==29)
  559.                         {
  560.                                 day=1;
  561.                                 mon++;
  562.                         }
  563.                         else if(((year)%4==0&&(year)%100!=0||(year)%400==0)&&mon==2&&day==30)
  564.                         {
  565.                                 day=1;
  566.                                 mon++;
  567.                         }
  568.                         dis1602(0,0x88);dis1602(1,day/10+0x30);dis1602(1,day%10+0x30);
  569.                        
  570.                         getkey1602();
  571.                         while(t0!=500);
  572.                        
  573.                         if(mon==13)
  574.                         {
  575.                                 mon=1;
  576.                                 year++;
  577.                         }
  578.                         dis1602(0,0x85);dis1602(1,mon/10+0x30);dis1602(1,mon%10+0x30);
  579.                        
  580.                         getkey1602();
  581.                         while(t0!=600);
  582.                        
  583.                         dis1602(0,0x82);dis1602(1,year%100/10+0x30);dis1602(1,year%10+0x30);
  584.                        
  585.                         getkey1602();
  586.                         while(t0!=700);
  587.                        
  588.                         dis1602(0,0x80);dis1602(1,year/1000+0x30);dis1602(1,year%1000/100+0x30);
  589.                        
  590.                         getkey1602();
  591.                         while(t0!=800);
  592.                        
  593.                         temp=MAX6675_ReadReg();                //读取状态数据0-65535     1111 1111 1111 1111 fedc ba98 7654 3210
  594.                         temp=((temp<<1)>>4)*5/2;        //读出来的数据的D3~D14是温度值 左移1位,右移4位 乘5/2 10倍温度值
  595.                        
  596.                         dis1602(0,0x8b);dis1602(1,temp%1000/100+0x30);dis1602(1,temp%100/10+0x30);
  597.                        
  598.                         getkey1602();
  599.                         while(t0!=900);
  600.                        
  601.                         dis1602(0,0x8e);dis1602(1,temp%10+0x30);
  602.                        
  603.                         getkey1602();
  604.                         while(t0!=1000);
  605.                 }
  606.                
  607.                 TL0 = 0x88;                        //设置定时初值                10us
  608.                 TH0 = 0xFF;                        //设置定时初值
  609.         }
  610. }

  611. main()
  612. {
  613.         init();
  614.         init1602();
  615.        
  616.     while(1)//
  617.     {
  618.                 delay(1);                                //系统周期1毫秒

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

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

  621.                 getkey();                                //运行一次80us  16ms运行一次
  622.                
  623.                 operation();

  624.                 display();
  625.     }
  626. }

  627. void Uart1_Routine() interrupt 4 using 2
  628. {
  629.         if(RI)
  630.         {
  631.                 RI=0;                                //清除RI标志
  632.                 value=SBUF;
  633.         }
  634.        
  635.         if(TI)
  636.         {
  637.                 TI=0;                                //清除TI标志
  638.                 busy=0;
  639.         }
  640. }

  641. void Timer0_Routine() interrupt 1 using 1
  642. {
  643.                 t0++;                                //10us
  644. }
复制代码

评分

参与人数 1牛币 +10 收起 理由
飞来峰 + 10 神马都是浮云

查看全部评分

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

使用道具 举报

发表于 2018-8-21 23:10:45 | 显示全部楼层
只会arduino2333333
回复 支持 0 反对 1

使用道具 举报

 楼主| 发表于 2018-8-14 23:06:52 | 显示全部楼层
新学了i2c总线协议 eeprom操作    i2c总线还没用到
eeprom操作 每分钟记录一次时间数据 在一个扇区里循环记录 断电后重连可以继续计时    再做一个掉电保护电路就可以掉电的时候记录了

  1. #include<reg51.h>

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

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

  7. sfr AUXR=0x8e;                //声明辅助寄存器

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

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

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


  14. //PCON中的LVDF(B5)为低压检测标志位 电压低于门槛时置1,需软件清零  
  15. //可在下载时设置禁止低压操作eeprom

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

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

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

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

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

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

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

  53. bit busy,pwmflag;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  310.                 keyy2=1;keyy3=0;
  311.                 keynow[8]=keyx1;
  312.                 keynow[9]=keyx2;
  313.                 keynow[10]=keyx3;
  314.                 keynow[11]=keyx4;

  315.                 keyy3=1;keyy4=0;
  316.                 keynow[12]=keyx1;
  317.                 keynow[13]=keyx2;
  318.                 keynow[14]=keyx3;
  319.                 keynow[15]=keyx4;


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

  336. void SendData(uchar dat)
  337. {
  338.         while(busy);                        //等待前面数据发送完成
  339.         busy=1;
  340.         SBUF=dat;
  341. }

  342. void SendString(char *s)
  343. {
  344.         while(*s)
  345.         {
  346.                 SendData(*s++);
  347.         }
  348. }

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

  354. void BANEEP()                                        //结束eeprom操作
  355. {
  356.         IAP_CONTR&=0X78;        //0111 1000
  357.         IAP_CMD=0;
  358.         IAP_TRIG=0;
  359. }

  360. void Write_EEP(uint addr,uchar dat)        //地址addr,写入dat
  361. {
  362.         IAP_ADDRH=addr/256;
  363.         IAP_ADDRL=addr%256;
  364.         IAP_DATA=dat;
  365.         IAP_CMD=2;
  366.         IAP_TRIG=0X5A;
  367.         IAP_TRIG=0XA5;
  368. }

  369. uchar Read_EEP(uint addr)                        //地址addr读取数据
  370. {
  371.         IAP_ADDRH=addr>>8;
  372.         IAP_ADDRL=addr;
  373.         IAP_CMD=1;
  374.         IAP_TRIG=0X5A;
  375.         IAP_TRIG=0XA5;
  376.         return IAP_DATA;
  377. }

  378. void EraseSector_EEP(uint addr)        //清空扇区
  379. {
  380.         IAP_ADDRH=addr>>8;
  381.         IAP_ADDRL=addr;
  382.         IAP_CMD=3;
  383.         IAP_TRIG=0X5A;
  384.         IAP_TRIG=0XA5;
  385. }

  386. void RECORD_1602()                                                //记录1602时间
  387. {
  388.         uint i;
  389.        
  390.         INITEEP();
  391.        
  392.         if(Read_EEP(sto1602+0x01f8)!=0xff)
  393.                 EraseSector_EEP(sto1602);
  394.        
  395.         for(i=0;i<512;i+=8)                                        //八字节一组 读第一字节
  396.         {
  397.                 if(Read_EEP(sto1602+i)==0xff)        //读出未写字符跳出
  398.                         break;
  399.         }
  400.        
  401.         Write_EEP(sto1602+i,0);                                //第一字节置零

  402.         Write_EEP(sto1602+i+1,year/100);
  403.         Write_EEP(sto1602+i+2,year%100);
  404.         Write_EEP(sto1602+i+3,mon);
  405.         Write_EEP(sto1602+i+4,day);
  406.         Write_EEP(sto1602+i+5,hour);
  407.         Write_EEP(sto1602+i+6,min);
  408.        
  409.         BANEEP();
  410. }

  411. void READ_1602()
  412. {
  413.         uint i;
  414.        
  415.         INITEEP();
  416.        
  417.         for(i=0;i<512;i+=8)                                        //八字节一组 读第一字节
  418.         {
  419.                 if(Read_EEP(sto1602+i)==0xff)        //读出未写字符跳出
  420.                         break;
  421.         }
  422.        
  423.         if(i==0)
  424.                 return;
  425.        
  426.         i-=8;
  427.         year=Read_EEP(sto1602+i+1)*100;
  428.         year+=Read_EEP(sto1602+i+2);
  429.         mon=Read_EEP(sto1602+i+3);
  430.         day=Read_EEP(sto1602+i+4);
  431.         hour=Read_EEP(sto1602+i+5);
  432.         min=Read_EEP(sto1602+i+6);
  433.        
  434.         week=((year/100/4)-year/100*2+year%100+year%100/4+26*(mon+1)/10+day-1)%7;
  435.        
  436.         BANEEP();
  437. }

  438. void operation()
  439. {
  440.         if(count2%16==0)
  441.         {
  442.                 switch(key)
  443.                 {
  444.                         case 0:        key=255;mode++;if(mode==5){mode=0;S1=0;}break;//3个模式
  445.                         case 1:                break;
  446.                         case 2:                break;
  447.                         case 3:                break;
  448.                         case 4:        key=255;x=1;        break;
  449.                         case 5:        key=255;x=2;        break;
  450.                         case 6:        key=255;x=3;        break;
  451.                         case 7:        key=255;OP1=1;        break;        // +
  452.                         case 8:        key=255;x=4;        break;
  453.                         case 9:        key=255;x=5;        break;
  454.                         case 10:key=255;x=6;        break;
  455.                         case 11:key=255;OP1=2;        break;        // -
  456.                         case 12:key=255;x=7;        break;
  457.                         case 13:key=255;x=8;        break;
  458.                         case 14:key=255;x=9;        break;
  459.                         case 15:key=255;OP1=3;        break;        // *
  460.                         case 16:key=255;x=0;        break;
  461.                         case 17:key=255;OP2=1;        break;        // =
  462.                         case 18:key=255;OP2=2;        break;        // c
  463.                         case 19:key=255;OP1=4;        break;        // /
  464.                        
  465.                         default:        break;
  466.                 }
  467.                
  468.                 if(mode==1)
  469.                 {
  470.                         if(OP1==0&&x!=255)
  471.                         {
  472.                                 value1=value1*10+x;
  473.                                 x=255;
  474.                                 value=value1;
  475.                         }
  476.                        
  477.                         if(OP1!=0&&x!=255)
  478.                         {
  479.                                 value2=value2*10+x;
  480.                                 x=255;
  481.                                 value=value2;
  482.                         }

  483.                         if(OP2==1)                                                        //输入 =
  484.                         {
  485.                                 OP2=0;
  486.                                
  487.                                 switch(OP1)
  488.                                 {
  489.                                         case 0:        value=value1;SendString("");                        break;
  490.                                         case 1:        value=value1+value2;                break;
  491.                                         case 2:        value=value1-value2;                break;
  492.                                         case 3:        value=value1*value2;                break;
  493.                                         case 4:        value=value1/value2;                break;
  494.                                        
  495.                                         default:        break;
  496.                                 }
  497.                                 OP1=OP2=DOP2=tOP2=value1=value2=0;
  498.                         }
  499.                        
  500.                         if(DOP2==1)
  501.                                 tOP2++;
  502.                         if(tOP2==30)
  503.                                 DOP2=0;
  504.                         if(OP2==2&&DOP2==1)                                                //双击C清空所有数据
  505.                                 OP1=OP2=DOP2=tOP2=value1=value2=value=0;
  506.                        
  507.                         if(OP2==2)                                                                //单击C清除数据
  508.                         {
  509.                                 OP2=0;
  510.                                 DOP2=1;tOP2=0;
  511.                                 if(OP1==0)
  512.                                         value=value1=0;
  513.                                 else
  514.                                         value=value2=0;
  515.                         }
  516.                 }
  517.         }
  518. }

  519. void display()
  520. {
  521.         if(mode==0)
  522.         {
  523.                 gettemp();
  524.                
  525.                 switch(count)                                        //显示温度
  526.                 {
  527.                         case 0:B4=1;if(temp/1000==0)break;                disduan(duan[temp/1000]);        diswei(wei[count]);break;        //显示第1管 为0不显示
  528.                         case 1:B1=1;disduan(duan[temp/100%10]);        diswei(wei[count]);break;                                                                //显示第2管
  529.                         case 2:B2=1;disduan(duan[temp/10%10]);        diswei(wei[count]);DP=1;break;                                                        //显示第3管 带小数点
  530.                         case 3:B3=1;disduan(duan[temp%10]);                diswei(wei[count]);break;                                                                //显示第4管
  531.                        
  532.                         default: break;
  533.                 }
  534.         }
  535.        
  536.         if(mode==1)
  537.         {
  538.                 switch(count)                                        //显示按键 计算器
  539.                 {
  540.                         case 0:B4=1;if(value/1000==0)break;        disduan(duan[value/1000]);                diswei(wei[count]);break;                        //显示第1管
  541.                         case 1:B1=1;if(value/100==0)break;        disduan(duan[value/100%10]);        diswei(wei[count]);break;                        //显示第2管
  542.                         case 2:B2=1;if(value/10==0)break;        disduan(duan[value/10%10]);                diswei(wei[count]);break;                        //显示第3管
  543.                         case 3:B3=1;                                                disduan(duan[value%10]);                diswei(wei[count]);break;                        //显示第4管
  544.                        
  545.                         default: break;
  546.                 }
  547.         }
  548.        
  549.         if(mode==2)
  550.         {
  551.                 if(count==0)
  552.                 {
  553.                         getadc();
  554.                         adc=adc*5000/1023;                        //1000倍电压值 adc*5v/1023*1000
  555.                 }
  556.                
  557.                 switch(count)                                        //显示电压
  558.                 {
  559.                         case 0:B4=1;disduan(duan[adc/1000]);        diswei(wei[count]);DP=1;break;                //显示第1管 带小数点
  560.                         case 1:B1=1;disduan(duan[adc/100%10]);        diswei(wei[count]);break;                        //显示第2管
  561.                         case 2:B2=1;disduan(duan[adc/10%10]);        diswei(wei[count]);break;                        //显示第3管       
  562.                         case 3:B3=1;disduan(duan[adc%10]);                diswei(wei[count]);break;                        //显示第4管       
  563.                        
  564.                         default: break;
  565.                 }
  566.         }
  567.        
  568.         while(mode==3)                                                                //模式3 pwm循环
  569.         {
  570.                 t0=0;
  571.                 pwmflag=!pwmflag;
  572.                
  573.                 if(pwmflag==1) S1=1;                                        //pwm高电平
  574.                 B4=1;disduan(duan[16]);diswei(wei[0]);        //显示数码管1
  575.                 getadc();                                                                //获取adc 0-1023
  576.                 adc=adc/10+100;                                                        //100-202
  577.                 if(adc>200)                                                                //100-200
  578.                         adc=200;
  579.                
  580.                 while(t0!=adc);
  581.                 S1=0;                                                                        //pwm低电平
  582.                
  583.                 while(t0!=250);
  584.                 B1=1;disduan(duan[adc/100%10]);        diswei(wei[1]);//显示数码管2

  585.                
  586.                 while(t0!=500);
  587.                 B2=1;disduan(duan[adc/10%10]);        diswei(wei[2]);//显示数码管3
  588.                
  589.                 while(t0!=750);
  590.                 B3=1;disduan(duan[adc%10]);        diswei(wei[3]);//显示数码管4
  591.                
  592.                                                         //检测mode按键
  593.                 keyy1=0;                                                        //keyy1置零
  594.                 keynow[0]=keyx1;                                        //keynow状态等于keyx1
  595.                 keynow[1]=keyx2;
  596.                 keyy1=1;
  597.                 if(keynow[0]==0&&keyold[0]==1)
  598.                 {
  599.                         mode=4;                                                        //符合条件mode回零,跳出pwm模式循环
  600.                         B4=1;
  601.                 }
  602.                 if(keynow[1]==0&&keyold[1]==1)
  603.                         IAP_CONTR=0x60;                                        //软复位
  604.                 keyold[0]=keynow[0];
  605.                 keyold[1]=keynow[1];
  606.                
  607.                 while(t0!=1000);                                        //10ms一个周期
  608.         }
  609.        
  610.         if(mode==4)
  611.         {
  612.                 TL0 = 0x20;                //设置定时初值                1ms
  613.                 TH0 = 0xD1;                //设置定时初值

  614.                 init1602();
  615.                 READ_1602();
  616.                
  617.                 while(mode==4)
  618.                 {
  619.                         t0=0;
  620.                        
  621.                         getkey1602();
  622.                        
  623.                         if(++sec==60)
  624.                         {
  625.                                 sec=0;
  626.                                 min++;
  627.                                 RECORD_1602();
  628.                         }
  629.                         dis1602(0,0xc7);dis1602(1,sec/10+0x30);dis1602(1,sec%10+0x30);
  630.                        
  631.                         while(t0!=100);
  632.                        
  633.                         getkey1602();
  634.                        
  635.                         if(min==60)
  636.                         {
  637.                                 min=0;
  638.                                 hour++;
  639.                         }
  640.                         dis1602(0,0xc4);dis1602(1,min/10+0x30);dis1602(1,min%10+0x30);
  641.                        
  642.                         while(t0!=200);

  643.                         getkey1602();
  644.                        
  645.                         if(hour==24)
  646.                         {
  647.                                 hour=0;
  648.                                 day++;
  649.                                 if(++week==8)
  650.                                         week=1;
  651.                         }
  652.                         dis1602(0,0xc1);dis1602(1,hour/10+0x30);dis1602(1,hour%10+0x30);
  653.                        
  654.                         while(t0!=300);
  655.                        
  656.                         getkey1602();
  657.                        
  658.                         if((mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)&&day==32)
  659.                         {
  660.                                 day=1;
  661.                                 mon++;
  662.                         }
  663.                         else if((mon==4||mon==6||mon==9||mon==11)&&day==31)
  664.                         {
  665.                                 day=1;
  666.                                 mon++;
  667.                         }
  668.                         else if(((year)%4!=0||((year)%100==0&&(year)%400!=0))&&mon==2&&day==29)
  669.                         {
  670.                                 day=1;
  671.                                 mon++;
  672.                         }
  673.                         else if(((year)%4==0&&(year)%100!=0||(year)%400==0)&&mon==2&&day==30)
  674.                         {
  675.                                 day=1;
  676.                                 mon++;
  677.                         }
  678.                         dis1602(0,0x89);dis1602(1,day/10+0x30);dis1602(1,day%10+0x30);
  679.                        
  680.                         while(t0!=400);
  681.                        
  682.                         getkey1602();
  683.                        
  684.                         dis1602(0,0x8f);dis1602(1,week+0x30);
  685.                        
  686.                         while(t0!=500);
  687.                        
  688.                         getkey1602();
  689.                        
  690.                         if(mon==13)
  691.                         {
  692.                                 mon=1;
  693.                                 year++;
  694.                         }
  695.                         dis1602(0,0x86);dis1602(1,mon/10+0x30);dis1602(1,mon%10+0x30);
  696.                        
  697.                         while(t0!=600);
  698.                        
  699.                         getkey1602();
  700.                        
  701.                         dis1602(0,0x83);dis1602(1,year%100/10+0x30);dis1602(1,year%10+0x30);
  702.                        
  703.                         while(t0!=700);
  704.                        
  705.                         getkey1602();
  706.                        
  707.                         dis1602(0,0x81);dis1602(1,year/1000+0x30);dis1602(1,year%1000/100+0x30);
  708.                        
  709.                         while(t0!=800);
  710.                        
  711.                         getkey1602();
  712.                        
  713.                         temp=MAX6675_ReadReg();                //读取状态数据0-65535     1111 1111 1111 1111 fedc ba98 7654 3210
  714.                         temp=((temp<<1)>>4)*5/2;        //读出来的数据的D3~D14是温度值 左移1位,右移4位 乘5/2 10倍温度值
  715.                        
  716.                         dis1602(0,0xcb);dis1602(1,temp%1000/100+0x30);dis1602(1,temp%100/10+0x30);
  717.                        
  718.                         while(t0!=900);
  719.                        
  720.                         getkey1602();
  721.                        
  722.                         dis1602(0,0xce);dis1602(1,temp%10+0x30);
  723.                        
  724.                         while(t0!=1000);
  725.                 }
  726.                
  727.                 TL0 = 0x88;                        //设置定时初值                10us
  728.                 TH0 = 0xFF;                        //设置定时初值
  729.         }
  730. }

  731. main()
  732. {
  733.         init();
  734.        
  735.     while(1)//
  736.     {
  737.                 delay(1);                                //系统周期1毫秒

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

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

  740.                 getkey();                                //运行一次80us  16ms运行一次
  741.                
  742.                 operation();

  743.                 display();
  744.     }
  745. }

  746. void Uart1_Routine() interrupt 4 using 3
  747. {
  748.         if(RI)
  749.         {
  750.                 RI=0;                                //清除RI标志
  751.                 value=SBUF;
  752.         }
  753.        
  754.         if(TI)
  755.         {
  756.                 TI=0;                                //清除TI标志
  757.                 busy=0;
  758.         }
  759. }

  760. void Timer0_Routine() interrupt 1 using 2
  761. {
  762.                 t0++;                                //10us
  763. }
复制代码
回复 支持 1 反对 0

使用道具 举报

发表于 2018-8-12 21:38:28 | 显示全部楼层
     可以            
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-12 21:42:34 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2018-8-12 21:47:46 | 显示全部楼层
厉害厉害厉害厉害
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-12 21:52:39 | 显示全部楼层
昶春斋 发表于 2018-8-12 21:47
厉害厉害厉害厉害

谢谢支持 看萝丽教程学的
回复 支持 反对

使用道具 举报

发表于 2018-8-12 22:09:44 | 显示全部楼层
不用时钟模块吗?
回复 支持 反对

使用道具 举报

发表于 2018-8-12 22:28:25 | 显示全部楼层
高级啊                    
回复 支持 反对

使用道具 举报

发表于 2018-8-12 22:44:09 | 显示全部楼层
看着这么长的代码一脸懵逼 - -
回复 支持 反对

使用道具 举报

发表于 2018-8-12 22:48:33 | 显示全部楼层
厉害厉害,佩服
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-12 23:18:51 | 显示全部楼层
sc19 发表于 2018-8-12 22:44
看着这么长的代码一脸懵逼 - -

有些是别的功能 比如 计算器 电压计 数码管显示 舵机测试 温度计新手diy万年历闹钟 DIY 作者:coolbgo 9122
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-12 23:21:32 | 显示全部楼层

用单片机内部定时器功能计时的 精度低点 但无所谓,主要是要学习怎么弄,又不用这个看时间新手diy万年历闹钟 DIY 作者:coolbgo 1885
回复 支持 反对

使用道具 举报

发表于 2018-8-13 01:57:18 | 显示全部楼层
coolbgo 发表于 2018-8-12 23:18 新手diy万年历闹钟 DIY 作者:sc19 1111
有些是别的功能 比如 计算器 电压计 数码管显示 舵机测试 温度计

之前想学单片机的,弄了一套基础板,然后就放那睡大觉了新手diy万年历闹钟 DIY 作者:sc19 1087
回复 支持 反对

使用道具 举报

发表于 2018-8-13 09:08:59 | 显示全部楼层
新手diy万年历闹钟 DIY 作者:youngchun 2587
回复 支持 反对

使用道具 举报

发表于 2018-8-13 09:53:16 | 显示全部楼层
屏幕可以换oled吗
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-13 10:18:44 | 显示全部楼层
xljie_10 发表于 2018-8-13 09:53
屏幕可以换oled吗

还没学oled 12864的控制 弄明白怎么控制就好说了
之前学1602控制的时候 被使能信号卡了好久 以为上升沿就行了  结果怎么都不显示 以为锁存器没设置好   然后仔细看别人的代码 原来正脉冲 电平拉高后还要再拉低的 新手diy万年历闹钟 DIY 作者:coolbgo 4986
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-13 10:25:34 | 显示全部楼层
sc19 发表于 2018-8-13 01:57
之前想学单片机的,弄了一套基础板,然后就放那睡大觉了

我没买实验板  都自己焊接的 就热电偶是模块 新手diy万年历闹钟 DIY 作者:coolbgo 1152 新手diy万年历闹钟 DIY 作者:coolbgo 2929
回复 支持 反对

使用道具 举报

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

使用道具 举报

发表于 2018-8-13 20:34:25 | 显示全部楼层
新手diy万年历闹钟 DIY 作者:咕噜咕噜 1994 帮顶
回复 支持 反对

使用道具 举报

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

本版积分规则

关闭

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

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

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