找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1947|回复: 1
收起左侧

单片机隔离下载器+时钟制作 DS12C887+CH340G+89C52+OLED显示程序

[复制链接]
ID:320097 发表于 2022-4-30 21:59 | 显示全部楼层 |阅读模式
自己制作的一个隔离下载器,顺便做了一个时钟显示,分享出来 大家一起来研究学习,由于我的DS12C887内部电池坏了,所以不得以拆开做了一个外科手术,换了一个电池,内部原来的晶振就是这种,其实也是挺简单的,外壳使用的是8838壳子,T12电烙铁专用的,看这个盒子挺漂亮的就配套做了一个,用光耦隔离了TXD和RXD,输出的时候就不用调换线了,光耦已经转换过来了.两个拨码器是用来转换外部下载和板子自身的89C52下载程序调试用的,后面的琴键开关是切换电源用的,可以使用USB的5V输出,也可以从后面的两个DC座子给需要下载的板子芯片供电.带冷启动功能,原理是串口下载时CH340G的RTS引脚会变低电平,单片机只需要检测这个引脚的电平变化就可以了,缺点是使用串口调试时也回触发一次冷启动
另外提示一下,有些人搞不明白列地址的高位和低位,低位地址是00H~0FH,也就是1-16,最多也就只能定位到16列,而一块屏幕有128列,而高位地址是10H~1FH,高位地址+低位地址就能准确定位到128列了,当然SSD1306不只应用在12864上,(0~127)/16就是高位地址,(0~127)%16就是低位地址,和定时器的初值一个意思,我是这么理解的,如有不对,欢迎指正

截图20220430211502.jpg 51hei图片_20220430212309.jpg 51hei图片_20220430212330.jpg 51hei图片_20220430212356.jpg 51hei图片_20220430212408.jpg 51hei图片_20220430212421.jpg
电路原理图如下:
51hei.png

单片机源程序如下:
  1. #include<STC89C5xRC.H>
  2. #include<intrins.h>
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. sbit SDA=P1^1;
  6. sbit SCL=P1^0;
  7. sbit RW=P2^5;
  8. sbit AS=P2^3;
  9. sbit CS=P2^4;
  10. sbit DS=P2^6;
  11. sbit km=P2^2;
  12. sbit jia=P2^1;
  13. sbit qh=P2^0;
  14. sbit k=P1^4;
  15. sbit RTS=P3^6;
  16. sbit j1=P1^7;
  17. sbit j2=P1^5;
  18. sbit led=P1^3;
  19. uchar t,tt;
  20. uchar smiao;
  21. bit ts;
  22. uchar code num[10][48]={
  23.                                          {0x00,0x00,0x00,0x80,0xE0,0xF0,0x78,0x38,0x18,0x38,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x07,0x0E,0x0C,0x0E,0x07,0x07,0x03,0x00,0x00,0x00},/*"0",0*/
  24.                                                     {0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*"1",0*/
  25.                                                     {0x00,0x00,0x00,0xC0,0xF0,0xF0,0x38,0x18,0x18,0x38,0xF8,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0x7C,0x1F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x07,0x07,0x07,0x05,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00},/*"2",0*/
  26.                                                      {0x00,0x00,0x00,0xC0,0xE0,0xF0,0x38,0x18,0x18,0x18,0xF8,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x0C,0x0C,0x1C,0x3F,0xFF,0xF3,0xC0,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0E,0x0C,0x0C,0x0E,0x07,0x07,0x03,0x00,0x00,0x00},/*"3",0*/
  27.                                                     {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF8,0xFC,0xDF,0xC7,0xC3,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00},/*"4",0*/
  28.                                                      {0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x80,0x8E,0x8F,0x0F,0x06,0x02,0x06,0x06,0x9E,0xFE,0xFC,0x60,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x07,0x0C,0x0C,0x0C,0x0E,0x07,0x07,0x03,0x00,0x00,0x00},/*"5",0*/
  29.                                                     {0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0x78,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFC,0xFF,0x0F,0x07,0x06,0x06,0x0E,0xFC,0xFC,0xF8,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0E,0x0C,0x0C,0x0C,0x0E,0x07,0x07,0x01,0x00,0x00},/*"6",0*/
  30.                                                     {0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xD0,0xF0,0xF0,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xFC,0x7F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x07,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"7",0*/
  31.                                                     {0x00,0x00,0x00,0xC0,0xF0,0xF0,0x38,0x18,0x18,0x18,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0xF1,0xFF,0xFF,0x1E,0x0C,0x0C,0x1E,0x1F,0xFF,0xF3,0xE0,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x07,0x0E,0x0C,0x0C,0x0C,0x0E,0x07,0x03,0x01,0x00,0x00},/*"8",0*/
  32.                                                     {0x00,0x00,0x00,0xE0,0xF0,0xF0,0x38,0x18,0x18,0x38,0xF0,0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0x01,0x0F,0x1F,0x1E,0x38,0xB0,0xF0,0xF8,0xFF,0x3F,0x0F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x0E,0x0F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"9",0*/
  33.                                                  };
  34. uchar code mao[ ]={0x00,0x00,0x60,0xF0,0xF0,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0F,0x0F,0x06,0x00,0x00};//"::::"
  35. uchar code tuo[ ]={0x10,0x10,0x10,0x10,0x38,0x38,0x38,0x38,0x7C,0x7C,0x7C,0x7C,0xFE,0xFE,0xFE,0xFE,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x7F,0x7F,0x7F,0x7F,0x3E,0x3E,0x3E,0x3E,0x1C,0x1C,0x1C,0x1C,0x08,0x08,0x08,0x08};/*"<-->",0*/
  36. uchar code zi[3][88]={
  37.                                        {0xFF,0x01,0x01,0xF9,0xF9,0x19,0xD9,0x99,0x19,0x99,0xD9,0x19,0x81,0xE1,0xF9,0xDD,0xC1,0xC1,0xC1,0xC1,0xC1,0x01,0x01,0x01,0x01,0xF9,0xF9,0x19,0x99,0xD9,0x79,0x09,0x01,0xF1,0xF1,0x31,0x31,0x31,0x31,0xF1,0xF1,0x11,0x01,0x01,0x01,0x01,0x01,0x01,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x31,0x31,0x31,0x31,0x31,0x31,0xF1,0xF1,0x31,0x31,0x31,0x31,0x39,0x39,0x01,0x01,0x01,0x01,0x01,0xFF},
  38.                                           {0xFF,0x00,0x00,0xFF,0xFF,0x00,0xE1,0x79,0x1F,0x1F,0xF1,0x60,0x01,0x81,0xE0,0x7C,0x7E,0xC6,0x80,0x03,0x01,0x00,0x00,0x00,0x00,0xFF,0xFF,0x82,0x83,0xCE,0xFE,0x60,0x00,0xFF,0xFF,0x18,0x18,0x18,0x18,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x86,0xC6,0xE6,0x76,0x1E,0x06,0x06,0x06,0x46,0xC6,0x86,0x06,0x07,0x07,0x07,0x00,0x00,0x00,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0x6C,0x3F,0x0F,0x1C,0x6C,0xCC,0x8C,0x0C,0x0C,0x0E,0x0C,0x00,0x00,0x00,0xFF},
  39.                                           {0xFF,0x80,0x80,0x8F,0x8F,0x8C,0x8C,0x8C,0x8C,0x8C,0x80,0x8C,0x8E,0x83,0x81,0x80,0x80,0x81,0x83,0x86,0x8C,0x88,0x80,0x80,0x80,0xBF,0xBF,0x81,0x81,0x80,0x80,0x80,0x80,0x8F,0x87,0x86,0x86,0x86,0x86,0x87,0x8F,0x80,0x80,0x80,0x80,0x90,0x98,0x8C,0x8F,0x8F,0x8D,0x8C,0x8C,0x8C,0x8C,0x8C,0x8C,0x8C,0x8C,0x8D,0x8F,0x9C,0x98,0x90,0x80,0x80,0x90,0x98,0x98,0x8C,0x86,0x83,0x81,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x87,0x84,0x8C,0x9C,0x98,0x90,0x80,0xFF},
  40.                                           };
  41. uchar code zizuo[2 ][32]={
  42.                                            {0x00,0x60,0x78,0x58,0x50,0xFC,0xFC,0x50,0x50,0x40,0xF0,0xF0,0x00,0xFC,0xFC,0x00,0x00,0x80,0xC0,0xF0,0xFC,0x4C,0x60,0x38,0x1C,0xF4,0xF0,0x10,0x90,0x90,0x90,0x10},
  43.                                           {0x00,0x00,0x1F,0x1F,0x01,0x3F,0x3F,0x19,0x1F,0x07,0x07,0x07,0x20,0x3F,0x3F,0x00,0x00,0x00,0x00,0x3F,0x3F,0x00,0x00,0x00,0x00,0x3F,0x3F,0x09,0x09,0x0C,0x04,0x00},
  44.                                           };
  45. void delay(uint z)
  46.         {
  47.          uint x,y;
  48.          for(x=z;x>0;x--)
  49.          for(y=115;y>0;y--);
  50.         }
  51. void start( )
  52.         {
  53.          SCL = 1;               
  54.             SDA = 1;
  55.             SDA = 0;
  56.          _nop_( );
  57.          _nop_( );

  58.             SCL = 0;
  59.          _nop_( );
  60.          _nop_( );
  61.         }
  62. void stop( )
  63.         {
  64.          SCL=0;
  65.          SDA=0;
  66.          _nop_( );
  67.          SCL=1;
  68.          _nop_( );
  69.          SDA=1;
  70.          _nop_( );
  71.         }
  72. void writebyte(uchar date)
  73.         {
  74.          uchar i;
  75.          for(i=8;i>0;i--)
  76.                  {
  77.                  date<<=1;
  78.                  SDA=CY;
  79.                  SCL=1;
  80.                  _nop_( );
  81.                  _nop_( );
  82.                  SCL=0;
  83.                  _nop_( );
  84.                  _nop_( );
  85.                 }
  86.            SDA=1;
  87.        SCL=1;
  88.            _nop_( );
  89.        SCL=0;
  90.         }
  91. void  writedat(uchar date1)
  92.         {
  93.       start();
  94.       writebyte(0x78);
  95.       writebyte(0x40);                        //write data
  96.       writebyte(date1);
  97.       stop();
  98.         }
  99. void writecomd(uchar comd)
  100.         {
  101.      start();
  102.      writebyte(0x78);         
  103.      writebyte(0x00);                //写指令            
  104.      writebyte(comd);
  105.      stop();
  106.          //led=~led;
  107.         }
  108. void initoled( )
  109.         {
  110.      uchar x,y;      
  111.      writecomd(0xae);  //--关闭oled面板
  112.      writecomd(0x00);  //---设置低列地址
  113.      writecomd(0x10);  //---设置高列地址
  114.      writecomd(0x40);  //--设置起始行地址设置映射RAM显示起始行 (0x00~0x3F)
  115.      writecomd(0x81);  //--设置对比度控制寄存器
  116.      writecomd(0xFF); // 设置SEG输出电流亮度
  117.      writecomd(0xa1);  //--设置SEG/列映射     0xa0左右反置 0xa1正常
  118.      writecomd(0xc8);  //设置COM/行扫描方向   0xc0上下反置 0xc8正常
  119.      writecomd(0xa6);  //--设置正常显示
  120.      writecomd(0xa8);  //--设置多路复用率(1 to 64)
  121.      writecomd(0x3f);  //--1/64 duty
  122.      writecomd(0xd3);  //-设置显示偏移        移位映射RAM计数器 (0x00~0x3F)
  123.      writecomd(0x00);  //-不抵消
  124.      writecomd(0xd5);  //--设置显示时钟分频比/振荡器频率
  125.      writecomd(0x80);  //--设置分频比,将时钟设置为100帧/秒
  126.      writecomd(0xd9);  //--设定预充电时间
  127.      writecomd(0xf1);  //将预充电设置为15个时钟,放电设置为1个时钟
  128.      writecomd(0xda);  //--设置com引脚硬件配置
  129.      writecomd(0x12);
  130.      writecomd(0xdb);  //--set vcomh
  131.      writecomd(0x30);  //设置VCOM取消选择级别
  132.      writecomd(0x20);  //-设置页面寻址模式 (0x00/0x01/0x02)
  133.      writecomd(0x02);  //
  134.      writecomd(0x8d);  //--设置电荷泵启用/禁用
  135.      writecomd(0x14);  //--set(0x10) 使能
  136.      writecomd(0xa4);  // 在屏幕上禁用整个显示 (0xa4/0xa5)
  137.      writecomd(0xa6);  // 禁用反转显示打开 (0xa6/a7)
  138.          for(x=0;x<8;x++)
  139.                  {
  140.                  writecomd(0xb0+x);
  141.          writecomd(0x00);
  142.          writecomd(0x10);
  143.                  for(y=0;y<128;y++)
  144.                          {
  145.                          writedat(0x00);                           //清屏
  146.                         }
  147.                 }
  148.          writecomd(0xaf);  //--打开oled面板  //先清屏再开显示,否则容易显示断电前上一次的图像
  149.         }
  150. void display( )
  151.         {
  152.         uchar x1,y1;
  153.         for(y1=0;y1<8;y1++)
  154.         {
  155.          writecomd(0xb0+y1);
  156.          writecomd(0x00);
  157.          writecomd(0x10);
  158.                  for(x1=0;x1<128;x1++)
  159.                         {
  160.                          if(y1==0)
  161.                                  {
  162.                                  if(x1<2||x1>125)
  163.                                          writedat(0xff);
  164.                                  else
  165.                                     writedat(0x03);
  166.                                 }
  167.                          if(y1>0&&y1<7)
  168.                                  {
  169.                                  if(x1<2||x1>125)
  170.                                          writedat(0xff);
  171.                                  else
  172.                                     writedat(0x00);        
  173.                                 }
  174.                          if(y1==7)
  175.                                  {
  176.                                  if(x1<2||x1>125)
  177.                                          writedat(0xff);
  178.                                  else
  179.                                     writedat(0xc0);
  180.                                 }
  181.                         }
  182.         }
  183.         }
  184. void writezi(bit s,uchar addrs,uchar nu)         //写入一个数字24*16   正常/反白显示 列地址(0~127)  数据
  185.         {
  186.          uchar i,j;
  187.          uchar n=0;
  188.          for(j=0;j<3;j++)
  189.                  {
  190.                   writecomd(0xb2+j);                    //循环三次+起始页,需要3个页面显示16*24数字  固定显示从第2页开始
  191.               writecomd(0x00+(addrs%16));                        //起始地址低位        00H~0FH
  192.               writecomd(0x10+(addrs/16));                        //起始地址高位        10H~1FH
  193.                  if(nu<10)                                                                //小于10为数字
  194.                         {
  195.                          for(i=0;i<16;i++)
  196.                                    {
  197.                                    if(s==0)
  198.                                                    {
  199.                                              writedat(num[nu][n]);                //调用数字表格 ,正常显示
  200.                                             }
  201.                                    if(s==1)
  202.                                                     {
  203.                                                  writedat(~(num[nu][n]));                //调用数字表格,反白显示
  204.                                                 }
  205.                                    n++;                                                        //一组数字表格为48字节,单独用一个数字记录,for循环结束时N不被清零,第二次for循环时才能从第17个数字开始调用
  206.                                   }
  207.                          }
  208.                  else                                                                  //否则为冒号
  209.                          {
  210.                          if(nu==10)                                                 //=10用冒号
  211.                             {
  212.                                   for(i=0;i<8;i++)
  213.                                            {
  214.                                             writedat(mao[n]);                //调用冒号表格
  215.                                             n++;
  216.                                           }
  217.                                 }
  218.                          else                                                        //否则清除冒号显示
  219.                                  {
  220.                                  for(i=0;i<8;i++)
  221.                                            {
  222.                                             writedat(0x00);                //空白显示,即擦除冒号
  223.                                             n++;
  224.                                           }
  225.                                 }
  226.                         }
  227.                 }
  228.         }
  229. void tuoji(bit b)                 //脱机标志
  230.         {
  231.          uchar i;
  232.          writecomd(0xb6);
  233.          writecomd(0x04);
  234.          writecomd(0x12);
  235.          if(b==0)                                                 //1 显示脱机标志
  236.             {
  237.                  for(i=0;i<56;i++)
  238.                           {
  239.                           writedat(tuo[i]);
  240.                          }
  241.              }
  242.          if(b==1)                                            //0 清除脱机标志
  243.             {
  244.                  for(i=0;i<56;i++)
  245.                           {
  246.                           writedat(0x00);
  247.                          }
  248.              }
  249.         }
  250. void writetime(uchar add,uchar date)  //  地址 数据  P0口数据
  251.         {
  252.          CS=0;                                                        //片选
  253.          DS=1;
  254.          RW=1;
  255.          AS=1;
  256.          P0=add;
  257.          _nop_();
  258.          AS=0;   
  259.          RW=0;
  260.          P0=date;
  261.           _nop_();  
  262.          RW=1;  
  263.          AS=1;
  264.          CS=1;   
  265.         }
  266. uchar readtime(uchar add)    //读数据  
  267.         {
  268.          uchar a;
  269.          CS=0;
  270.          RW=1;
  271.          DS=1;
  272.          AS=1;
  273.          P0=add;
  274.          AS=0;
  275.          DS=0;
  276.          P0=0xff;
  277.          _nop_();
  278.          a=P0;
  279.          DS=1;
  280.          AS=1;
  281.          CS=1;
  282.          return a;
  283.         }
  284. /*9void inittime( )
  285.         {
  286.          writetime(0X0A,0X20);        //开启时钟振荡器
  287.          writetime(0X0B,0X06);        //不开启闹钟使能中断,二进制数据,24小时格式
  288.          writetime(0,7);
  289.          writetime(1,0);
  290.            writetime(2,54);
  291.          writetime(3,0);
  292.            writetime(4,10);
  293.             writetime(5,0);
  294.            writetime(6,3);
  295.            writetime(7,16);
  296.           writetime(8,7);
  297.            writetime(9,19);                                                                   //初始化芯片,仅须1次
  298.         } */
  299. void timedisplay( )                                                          //显示时间
  300.         {
  301.          uchar shi,fen,mia;
  302.          uchar a1,a2,a3,a4,a5,a6;
  303.          shi=readtime(4);
  304.          fen=readtime(2);
  305.          mia=readtime(0);                  //读时间
  306.          if(smiao!=mia)                          //秒针有变化,没有变化的时候就不用去刷新屏幕了
  307.                  {
  308.                  a1=shi/10;
  309.                  a2=shi%10;
  310.                  a3=fen/10;
  311.                  a4=fen%10;
  312.                  a5=mia/10;
  313.                  a6=mia%10;
  314.                  writezi(0,8,a1);
  315.                  writezi(0,24,a2);                   //时
  316.                  writezi(0,40,10);                  //10代表:冒号
  317.                  writezi(0,48,a3);
  318.                  writezi(0,64,a4);                   //分
  319.                  writezi(0,88,a5);
  320.                  writezi(0,104,a6);                   //秒
  321.                  writezi(0,80,10);
  322.                  smiao=mia;                                   //备份秒数,以便下一秒比较
  323.                  SBUF=mia;                                   //串口查看秒针更新
  324.                  TI=0;
  325.                  TH0=0X4C;
  326.                  TL0=0X00;
  327.                  TR0=1;
  328.                  }
  329.         }
  330. void setup(uchar add,uchar num1,uchar num2,uchar num3)
  331.         {
  332.          uchar n1,n2,n3,n4,n5,n6;
  333.          n1=num1/10;
  334.          n2=num1%10;
  335.          n3=num2/10;
  336.          n4=num2%10;
  337.          n5=num3/10;
  338.          n6=num3%10;
  339.          switch(add)
  340.              {
  341.                   case 1:
  342.                                    {
  343.                                   writezi(1,8,n1);
  344.                                   writezi(1,24,n2);                   //时
  345.                                      writezi(0,40,10);                  //10代表:冒号
  346.                                    writezi(0,48,n3);
  347.                                    writezi(0,64,n4);                   //分
  348.                                   writezi(0,80,10);
  349.                                    writezi(0,88,n5);
  350.                                    writezi(0,104,n6);                   //秒
  351.                                  };break;
  352.                   case 2:
  353.                                    {
  354.                                     writezi(0,8,n1);
  355.                                   writezi(0,24,n2);                   //时
  356.                                      writezi(0,40,10);                  //10代表:冒号
  357.                                    writezi(1,48,n3);
  358.                                    writezi(1,64,n4);                   //分
  359.                                   writezi(0,80,10);
  360.                                    writezi(0,88,n5);
  361.                                    writezi(0,104,n6);                   //秒
  362.                                    };break;
  363.                   case 3:
  364.                                    {
  365.                                   writezi(0,8,n1);
  366.                                   writezi(0,24,n2);                   //时
  367.                                      writezi(0,40,10);                  //10代表:冒号
  368.                                    writezi(0,48,n3);
  369.                                    writezi(0,64,n4);                   //分
  370.                                   writezi(0,80,10);
  371.                                    writezi(1,88,n5);
  372.                                    writezi(1,104,n6);                   //秒
  373.                                    };break;
  374.               default:break;
  375.                  }
  376.         }
  377. void initdisplay( )
  378.         {
  379.          uchar h,v;
  380.          for(h=0;h<2;h++)
  381.                  {
  382.                   writecomd(0xb1+h);               
  383.               writecomd(0x00);                        //起始地址低位        00H~0FH
  384.               writecomd(0x13);                        //起始地址高位        10H~1FH
  385.                  for(v=0;v<32;v++)
  386.                          {
  387.                          writedat(zizuo[h][v]);
  388.                         }
  389.                 }
  390.          for(h=0;h<3;h++)
  391.                  {
  392.                   writecomd(0xb3+h);                    
  393.               writecomd(0x04);                        //起始地址低位        00H~0FH
  394.               writecomd(0x11);                        //起始地址高位        10H~1FH
  395.                  for(v=0;v<88;v++)
  396.                          {
  397.                          writedat(zi[h][v]);
  398.                         }
  399.                 }
  400.         }
  401. void timer ( )
  402.         {
  403.          TMOD = 0x21;
  404.      PCON = 0x00;
  405.      SCON = 0x50;                        
  406.      TH1 = 0xFd;    //设置波特率 9600
  407.      TL1 = 0xFd;
  408.      TR1 = 1;                //启动定时器1
  409.          TH0=0X4C;
  410.          TL0=0X00;
  411.          EA=1;
  412.          ET0=1;
  413.         }
  414. void main( )
  415.         {
  416.          uchar sshi,sfen,smia,she;
  417.          uchar as,ag;
  418.          bit key,set;
  419.          bit xz,lj;
  420.          smiao=0x62;
  421.          set=0;
  422.          xz=0;
  423.          lj=0;
  424.          timer( );
  425.          initoled( );
  426.          initdisplay( );
  427.          delay(4000);
  428.          display( );
  429.          //inittime( );                                        //DS12C887芯片初始化         
  430.          tuoji(lj);
  431.          j1=j2=0;
  432.          while(1)
  433.                  {
  434.                  if(set==0)                                   //非设置状态,正常显示时间
  435.                          {
  436.                           timedisplay( );
  437.                           delay(50);
  438.                          }
  439.                  if(ts==1)                                          //冒号闪烁,秒针更新后启动定时器0.5S以后定时器把ts置1,在主程序里面擦除冒号
  440.                          {
  441.                          //writezi(0,40,11);        
  442.                          writezi(0,80,11);
  443.                          ts=0;
  444.                         }
  445.                  if(km==0&&key==0)                           //设置键
  446.                          {
  447.                          delay(10);
  448.                          if(km==0)
  449.                                  {
  450.                                  key=1;
  451.                                  if(set==0)                                 //设置之前读一次就可
  452.                                          {
  453.                                          sshi=readtime(4);
  454.                                   sfen=readtime(2);
  455.                                  smia=readtime(0);
  456.                                          }
  457.                                  set=1;
  458.                                  she++;
  459.                                  if(she>3)
  460.                                          {
  461.                                           she=0;
  462.                                          set=0;                                           //清除设置状态
  463.                                          writetime(4,sshi);
  464.                                          writetime(2,sfen);
  465.                                          writetime(0,smia);                  //把设置好的参数写入时钟
  466.                                         }
  467.                                  setup(she,sshi,sfen,smia);
  468.                                 }
  469.                         }
  470.                  if(jia==0&&key==0&&set==1)                   //设置状态加键允许操作
  471.                          {
  472.                          delay(10);
  473.                          if(jia==0)
  474.                                  {
  475.                                  key=1;
  476.                                  t=100;
  477.                                  while(jia==0)
  478.                                          {
  479.                                          while(jia==0&&t>0)
  480.                                                  {
  481.                                                  t--;
  482.                                                  delay(10);                        //10毫秒1次,100次即1秒后仍未松手判定为长按
  483.                                                 }                                        //反之没到1秒松手,只能运行一次加操作
  484.                                           switch(she)
  485.                                                  {
  486.                                                  case 1:
  487.                                                            {
  488.                                                           sshi++;
  489.                                                           if(sshi==24)
  490.                                                                   {
  491.                                                                  sshi=0;
  492.                                                                 }
  493.                                                           as=sshi/10;
  494.                                                           ag=sshi%10;
  495.                                                           writezi(1,8,as);
  496.                                                           writezi(1,24,ag);                   //时
  497.                                                          };break;
  498.                                                  case 2:
  499.                                                            {
  500.                                                           sfen++;
  501.                                                           if(sfen==60)
  502.                                                                   {
  503.                                                                  sfen=0;
  504.                                                                 }
  505.                                                           as=sfen/10;
  506.                                                           ag=sfen%10;
  507.                                                           writezi(1,48,as);
  508.                                                           writezi(1,64,ag);                   //分
  509.                                                          };break;
  510.                                                  case 3:
  511.                                                            {
  512.                                                           smia++;
  513.                                                           if(smia==60)
  514.                                                                   {
  515.                                                                  smia=0;
  516.                                                                 }
  517.                                                           as=smia/10;
  518.                                                           ag=smia%10;
  519.                                                           writezi(1,88,as);
  520.                                                           writezi(1,104,ag);                   //秒
  521.                                                          };break;
  522.                                                  default:break;
  523.                                                 }
  524.                                          delay(60);                                                     //长按状态60毫秒加一次,直到松手为止
  525.                                          }
  526.                                 }
  527.                         }
  528.                  if(qh==0&&key==0&&set==1)                                  //取消键
  529.                         {
  530.                          delay(10);
  531.                          if(qh==0)
  532.                                  {
  533.                                  key=1;
  534.                              set=0;
  535.                                  she=0;
  536.                                 }
  537.                         }
  538.                  if(key==1)                                                                          //按键松手检测
  539.                          {
  540.                          if(km==1&&jia==1&&qh==1&&k==1)
  541.                                  {
  542.                                  delay(10);
  543.                                  if(km==1&&jia==1&&qh==1&&k==1)
  544.                                          {
  545.                                          key=0;
  546.                                         }
  547.                                 }
  548.                         }
  549.                  if(RTS==0&&xz==0&&lj==0)                          //联机状态,下载允许状态 lj=1脱机状态不会触发冷启动
  550.                          {
  551.                          delay(5);
  552.                          if(RTS==0)
  553.                                  {
  554.                                  j1=j2=1;
  555.                                  delay(1800);
  556.                                  j1=j2=0;                                          //断电冷启动
  557.                                  xz=1;                                                 //下载标志位,联机下载过程中RTS一直为0,避免下载完成之前再次触发冷启动
  558.                                 }
  559.                         }
  560.                  if(xz==1)                                                        //检测RTS恢复高电平后,解除下载标志
  561.                          {
  562.                          if(RTS==1)
  563.                                  {
  564.                                  delay(10);
  565.                                  if(RTS==1)
  566.                                          {
  567.                                          xz=0;
  568.                                         }
  569.                                 }
  570.                         }
  571.                  if(k==0&&key==0)                                          //面板按键 短按开关电源,长按脱机/联机切换
  572.                          {
  573.                          delay(10);
  574.                          if(k==0)
  575.                                  {
  576.                                  t=100;
  577.                                  while(k==0&&t>0)
  578.                                          {
  579.                                          delay(10);
  580.                                          t--;
  581.                                          if(t==0)                                                 //超过1秒长按识别
  582.                                                  {
  583.                                                  lj=~lj;                                         //联机/脱机状态
  584.                                                  tuoji(lj);                                         //屏幕显示联机/脱机图标
  585.                                                 }
  586.                                         }
  587.                                  key=1;
  588.                                 if(t>0)                                                                //小于1秒短按识别
  589.                                         {
  590.                                           j1=~j1;
  591.                                           j2=~j2;
  592.                                          }
  593.                                 }
  594.                         }
  595.                 }
  596.         }
  597. void aa( ) interrupt 1
  598.         {
  599.          TH0=0X4C;
  600.          TL0=0X00;
  601.          tt++;
  602.          if(tt==10)
  603.                  {
  604.                  TR0=0;
  605.                  ts=1;
  606.                  tt=0;
  607.                 }
  608.         }
复制代码
51hei.png
附件里面是Gerber文件下载: Gerber文件与原理图.7z (285.41 KB, 下载次数: 16)

评分

参与人数 1黑币 +90 收起 理由
admin + 90 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:1026949 发表于 2022-5-16 11:41 | 显示全部楼层
这个实现的功能主要包括哪些呢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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