找回密码
 立即注册

QQ登录

只需一步,快速开始

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

使用51单片机+ampire12864的倒计时报警装置(proteus仿真)

[复制链接]
跳转到指定楼层
楼主
/*********************************************************************************
* 【编写时间】: 2020年7月3日
* 【作    者】: march
* 【版    本】: 1.0
* 【外部晶振】: 12mhz      
* 【主控芯片】: STC89C52RC
* 【编译环境】: Keil μVisio4      
* 【程序功能】: 12864液晶显示倒计时报警                                                                                          
* 【使用说明】:
液晶引脚定义
sbit rs=P1^4;
sbit E=P1^2;         
sbit CS1=P1^1;
sbit CS2=P1^0;
sbit RW=P1^3;
sbit key1 = P3^1;          选择
sbit key2 = P3^2;                  =
sbit key3 = P3^3;                   -
sbit bj = P3^0;                   输出

            E_display_R(页,列,字库);
                        E_display_L(3,0*8,hour/10);//小时若变化则重新写入
                        E_display_L(3,1*8,hour%10);//小时若变化则重新写入
                        E_display_L(3,2*8,19);//冒号                       
                        E_display_L(3,3*8,min/10);//分若变化则重新写入
                        E_display_L(3,4*8,min%10);//分若变化则重新写入
                        E_display_L(3,5*8,19);//冒号               
                        E_display_L(3,6*8,sec/10);//秒若变化则重新写入
                        E_display_L(3,7*8,sec%10);//秒若变化则重新写入      
                       
                        C_display_L(1,3*8,1);                输出字符
                        取字模软件选项(阴码、逆向、列行式)         
**********************************************************************************/
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include <reg52.h>
  2. #define uchar unsigned char
  3. #define uint  unsigned int
  4. #define PAGEADD 0xb8                //设置起始页10111xxx    转换后0xb8
  5. #define TIERADD 0x40
  6. #define rsS_STARADD 0xc0
  7. #define _nop {}
  8. //液晶引脚定义
  9. sbit rs=P1^4; //rs
  10. sbit E=P1^2;          //e
  11. sbit CS1=P1^1;
  12. sbit CS2=P1^0;
  13. sbit RW=P1^3;                 //rw

  14. sbit key1 = P3^1;
  15. sbit key2 = P3^2;
  16. sbit key3 = P3^3;
  17. sbit bj = P3^0;
  18. uchar key1num,count,hour,min,sec;
  19. /*****************************
  20.           字符表
  21.          显示"Welcome Use"
  22. ******************************/
  23. uchar code table1[]={
  24. 0x00,0x3e,0x51,0x49,0x45,0x3e,0x00,0x00,//0(0)
  25. 0x00,0x00,0x42,0x7f,0x40,0x00,0x00,0x00,//1
  26. 0x00,0x42,0x61,0x51,0x49,0x46,0x00,0x00,//2
  27. 0x00,0x21,0x41,0x45,0x4b,0x31,0x00,0x00,//3
  28. 0x00,0x18,0x14,0x12,0x7f,0x10,0x00,0x00,//4
  29. 0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00,//5
  30. 0x00,0x3c,0x4a,0x49,0x49,0x30,0x00,0x00,//6
  31. 0x00,0x01,0x01,0x79,0x05,0x03,0x00,0x00,//7
  32. 0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00,//8
  33. 0x00,0x06,0x49,0x49,0x29,0x1e,0x00,0x00,//9
  34. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// (10)
  35. 0x00,0x00,0x00,0x47,0x00,0x00,0x00,0x00,//!
  36. 0x00,0x23,0x13,0x08,0x64,0x62,0x00,0x00,//%
  37. 0x00,0x36,0x49,0x55,0x22,0x50,0x00,0x00,//&
  38. 0x00,0x14,0x08,0x3e,0x08,0x14,0x00,0x00,//*
  39. 0x00,0x08,0x08,0x3e,0x08,0x08,0x00,0x00,//+
  40. 0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00,//-
  41. 0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,//.
  42. 0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00,///
  43. 0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00,//:(19)
  44. 0x00,0x14,0x14,0x14,0x14,0x14,0x00,0x00,//=
  45. 0x00,0x02,0x01,0x51,0x09,0x06,0x00,0x00,//?

  46. };
  47. /****************************
  48.         中文字符表
  49.         显示"欢迎使用液晶模块"
  50. *****************************/
  51. uchar code table2[]={
  52. /*0x14,0x24,0x44,0x84,0x64,0x1c,0x20,0x18,
  53. 0x0f,0xe8,0x08,0x08,0x28,0x18,0x08,0x00,
  54. 0x20,0x10,0x4c,0x43,0x43,0x2c,0x20,0x10,
  55. 0x0c,0x03,0x06,0x18,0x30,0x60,0x20,0x00,//欢(0)
  56. 0x40,0x41,0xce,0x04,0x00,0xfc,0x04,0x02,
  57. 0x02,0xfc,0x04,0x04,0x04,0xfc,0x00,0x00,
  58. 0x40,0x20,0x1f,0x20,0x40,0x47,0x42,0x41,
  59. 0x40,0x5f,0x40,0x42,0x44,0x43,0x40,0x00,//迎(1)
  60.   */




  61. 0x80,0x60,0xF8,0x07,0x04,0x64,0x5C,0xC4,0x64,0x44,0x00,0xF8,0x00,0xFF,0x00,0x00,
  62. 0x00,0x00,0xFF,0x00,0x20,0x62,0x22,0x1F,0x12,0x12,0x00,0x4F,0x80,0x7F,0x00,0x00,/*"倒",0*/
  63. /* (16 X 16 , 宋体 )*/

  64. 0x40,0x40,0x42,0xCC,0x00,0x40,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x40,0x00,
  65. 0x00,0x00,0x00,0x7F,0x20,0x10,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,/*"计",1*/
  66. /* (16 X 16 , 宋体 )*/

  67. 0x00,0xFC,0x84,0x84,0x84,0xFC,0x00,0x10,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x00,
  68. 0x00,0x3F,0x10,0x10,0x10,0x3F,0x00,0x00,0x01,0x06,0x40,0x80,0x7F,0x00,0x00,0x00,/*"时",2*/
  69. /* (16 X 16 , 宋体 )*/






  70. };
  71. /*延时函数*/
  72. void delay(uint xms)
  73. {
  74.         uint i,j;
  75.         for(i=xms;i>0;i--)
  76.         for(j=114;j>0;j--);
  77. }


  78. /*****************************************
  79.     DEM12864B状态检测,从EDM12864B读出数
  80.     据检测标志位BF
  81. ******************************************/


  82. void LCD_Busy()
  83. {
  84.   uchar busy;
  85.   E=0;
  86.   rs=0;
  87.   RW=1;
  88.   while(1)
  89.   {
  90.     E=1;
  91.     _nop;
  92.     busy=P2;//读状态标志寄存器
  93.         _nop;
  94.     E=0;
  95.     if((busy&0x90)==0)//检测BF和RES位,两者都为零时表示可进行写入
  96.     break;
  97.   };
  98. }


  99. /*1602液晶*/
  100. //写命令

  101. void WRCommand_L(uchar command)
  102. {
  103.   CS1=1;
  104.   CS2=0;
  105.   LCD_Busy();
  106.   rs=0;
  107.   _nop;
  108.   RW=0;
  109.   _nop;
  110.   E=1;
  111.   _nop;
  112.   P2=command;
  113.   _nop;
  114.   E=0;
  115.   _nop;
  116. }


  117. void WRCommand_R(uchar command)
  118. {
  119.   CS1=0;
  120.   CS2=1;
  121.   LCD_Busy();
  122.   rs=0;
  123.   _nop;
  124.   RW=0;
  125.   _nop;
  126.   E=1;
  127.   _nop;
  128.   P2=command;
  129.   _nop;
  130.   E=0;
  131.   _nop;
  132. }


  133. //写数据
  134. void WRdata_L(uchar ucdata)
  135.   {
  136.    CS1=1;
  137.    CS2=0;
  138.    LCD_Busy();
  139.    rs=1;
  140.    _nop;
  141.    RW=0;
  142.    _nop;
  143.    E=1;
  144.    _nop;
  145.    P2=ucdata;
  146.    _nop;
  147.    E=0;
  148.    _nop;
  149.   }


  150. void WRdata_R(uchar ucdata)
  151.   {
  152.    CS1=0;
  153.    CS2=1;
  154.    LCD_Busy();
  155.    rs=1;
  156.    _nop;
  157.    RW=0;
  158.    _nop;
  159.    E=1;
  160.    _nop;
  161.    P2=ucdata;
  162.    _nop;
  163.    E=0;
  164.    _nop;
  165.   }



  166. /****************************************************
  167.        字符为16*16显示,分为两个部分写入32个字节
  168.        前16个字节写入第一页(16*8),后16个字节写入
  169.            第二页(16*8)
  170.            左侧写入"欢迎",右侧写入"使用"
  171. *****************************************************/
  172. C_display_L(uchar C_Pagenum,uchar C_Tiernum,uchar C_Temp)        // PAGEADD 0xb8
  173.   {                                                                                                                        //TIERADD 0x40
  174.    uchar k;
  175.    C_Pagenum=PAGEADD+C_Pagenum;                           //0xb8|        1
  176.    C_Tiernum=TIERADD+C_Tiernum;                          //0x40|  a*16          a=0  1  2  3  4
  177.    WRCommand_L(C_Pagenum);
  178.    WRCommand_L(C_Tiernum);
  179.    for(k=0;k<16;k++)
  180.       {
  181.        WRdata_L(table2[C_Temp*32+k]);
  182.              };
  183.    C_Pagenum=C_Pagenum+1;
  184.    WRCommand_L(C_Pagenum);
  185.    WRCommand_L(C_Tiernum);
  186.    for(k=0;k<16;k++)
  187.       {
  188.        WRdata_L(table2[C_Temp*32+k+16]);
  189.            };
  190.    }

  191. C_display_R(uchar C_Pagenum,uchar C_Tiernum,uchar C_Temp)
  192.   {
  193.    uchar k;
  194.    C_Pagenum=PAGEADD|C_Pagenum;
  195.    C_Tiernum=TIERADD|C_Tiernum;
  196.    WRCommand_R(C_Pagenum);
  197.    WRCommand_R(C_Tiernum);
  198.    for(k=0;k<16;k++)
  199.       {
  200.        WRdata_R(table2[C_Temp*32+k]);
  201.              };
  202.    C_Pagenum=C_Pagenum+1;
  203.    WRCommand_R(C_Pagenum);
  204.    WRCommand_R(C_Tiernum);
  205.    for(k=0;k<16;k++)
  206.       {
  207.        WRdata_R(table2[C_Temp*32+k+16]);
  208.              };
  209.   }
  210. /****************************************
  211.    写入西文字符,共11个字符,左侧写入6个
  212.    右侧写入5个,左侧起始从16开始,右侧从
  213.    0开始
  214. *****************************************/

  215. E_display_L(uchar E_Pagenum,uchar E_Tiernum,uchar E_Temp)
  216.   {
  217.    uchar k;
  218.    WRCommand_L(PAGEADD|E_Pagenum);
  219.    WRCommand_L(TIERADD|E_Tiernum);
  220.    for(k=0;k<8;k++)
  221.           {
  222.            WRdata_L(table1[E_Temp*8+k]);
  223.            };
  224.    }   
  225. E_display_R(uchar E_Pagenum,uchar E_Tiernum,uchar E_Temp)
  226.    {
  227.    uchar k;
  228.                    // WRCommand_R(PAGEADD|E_Pagenum);
  229.                  //   WRCommand_R(TIERADD|E_Tiernum);
  230.    for(k=0;k<8;k++)
  231.           {
  232.            WRdata_R(table1[E_Temp*8+k]);
  233.            };
  234.            }

  235.   //////////////////////////////////////////////////////////////////////////////

  236. /*********************************
  237.            清除所有显示RAM内容
  238. **********************************/

  239. CLR_displayRAM()
  240.    {
  241.     uchar C_page,i,k;
  242.     for(i=0;i<8;i++)
  243.            {
  244.             C_page=PAGEADD|i;//清除起始页为0
  245.             WRCommand_L(C_page);//清除起始页写入
  246.                 WRCommand_L(TIERADD);//清除起始行地址写入
  247.                 WRCommand_R(C_page);
  248.                 WRCommand_R(TIERADD);
  249.                 for(k=0;k<64;k++)
  250.                    {                           
  251.                         WRdata_L(0x00);
  252.                         WRdata_R(0x00);//lcm的ram自动加一,只许循环64次即可   
  253.                          };
  254.                  };
  255.     }


  256. //初始化
  257. void Init_LCD(void)
  258.    {
  259.         CLR_displayRAM();//清除所有显示寄存器
  260.         WRCommand_L(rsS_STARADD);
  261.         WRCommand_R(rsS_STARADD);//设置显示起始行地址
  262.         WRCommand_L(0x3f);
  263.         WRCommand_R(0x3f);//开显示         3e关显示
  264.     }
  265. /*键盘扫描函数*/
  266. void keyscan()//按键扫描函数
  267. {
  268.         
  269.         if(key1==0)
  270.         {         
  271.                 delay(5);
  272.                 if(key1==0)//确认功能键被按下
  273.                 {         
  274.                         key1num++;//功能键按下次数记录
  275.                         while(!key1);//释放确认
  276.                         if(key1num==1)//第一次被按下时
  277.                         {
  278.                                 TR0=0; //关闭定时器
  279.                                                 E_display_L(3,6*8,20);//秒若变化则重新写入
  280.                                                 E_display_L(3,7*8,20);
  281.                         //        write_com(0x80+0x40+7);//光标定位到秒位置
  282.                         //        write_com(0x0f); //光标开始闪烁
  283.                         }
  284.                         if(key1num==2)//第二次按下光标闪烁定位到分钟位置
  285.                         {
  286.                                         E_display_L(3,3*8,20);//秒若变化则重新写入
  287.                                         E_display_L(3,4*8,20);
  288.                         //        write_com(0x80+0x40+4);
  289.                         }
  290.                         if(key1num==3)//第三次按下光标闪烁定位到小时位置
  291.                         {
  292.                                         E_display_L(3,0*8,20);//秒若变化则重新写入
  293.                                         E_display_L(3,1*8,20);
  294.                         //        write_com(0x80+0x40+1);
  295.                         }
  296.                         if(key1num==4)//第四次按下
  297.                         {
  298.                                 key1num=0;//记录按键数清零
  299.                         //        write_com(0x0c);//取消光标闪烁
  300.                         E_display_L(3,0*8,hour/10);//小时若变化则重新写入
  301.                         E_display_L(3,1*8,hour%10);//小时若变化则重新写入
  302.                         E_display_L(3,2*8,19);//冒号                        
  303.                         E_display_L(3,3*8,min/10);//分若变化则重新写入
  304.                         E_display_L(3,4*8,min%10);//分若变化则重新写入
  305.                         E_display_L(3,5*8,19);//冒号               
  306.                         E_display_L(3,6*8,sec/10);//秒若变化则重新写入
  307.                         E_display_L(3,7*8,sec%10);//秒若变化则重新写入
  308.                                 TR0=1; //启动定时器使时钟开始走
  309.                         }
  310.                 }
  311.         }
  312.         if(key1num!=0)//只有功能键被按下后,增加和减小键才有效
  313.         {
  314.                 if(key2==0)
  315.                 {
  316.                         delay(5);
  317.                         if(key2==0)//增加键确认被按下
  318.                         {
  319.                                 while(!key2);//按键释放
  320.                                 if(key1num==1)//若功能键第一次按下
  321.                                 {
  322.                                         sec++; //则调整秒加1
  323.                                         if(sec==60)//若满60后将清零
  324.                                         sec=0;
  325.                         E_display_L(3,6*8,sec/10);//秒若变化则重新写入
  326.                         E_display_L(3,7*8,sec%10);//秒若变化则重新写入
  327.                                 //        write_sfm(6,sec);//每调节一次送液晶显示一下
  328.                                 //        write_com(0x80+0x40+7);//显示位置重新回到调节处
  329.                                 }
  330.                                 if(key1num==2)//若功能键第二次按下
  331.                                 {
  332.                                         min++;//则调整分钟加1
  333.                                         if(min==60)//若满60后将清零
  334.                                         min=0;
  335.                                         E_display_L(3,3*8,min/10);//分若变化则重新写入
  336.                                  E_display_L(3,4*8,min%10);//分若变化则重新写入
  337.                                 //        write_sfm(3,min);//每调节一次送液晶显示一下
  338.                                 //        write_com(0x80+0x40+4);//显示位置重新回到调节处
  339.                                 }
  340.                                 if(key1num==3)//若功能键第三次按下
  341.                                 {
  342.                                         hour++;//则调整小时加1
  343.                                         if(hour==24)//若满24后将清零
  344.                                         hour=0;
  345.                                            E_display_L(3,0*8,hour/10);//小时若变化则重新写入
  346.                                 E_display_L(3,1*8,hour%10);//小时若变化则重新写入
  347.                                 //        write_sfm(0,hour);;//每调节一次送液晶显示一下
  348.                                 //        write_com(0x80+0x40+1);//显示位置重新回到调节处
  349.                                 }
  350.                         }
  351.                 }
  352.                 if(key3==0)
  353.                 {
  354.                         delay(5);
  355.                         if(key3==0)//确认减小键被按下
  356.                         {
  357.                                 while(!key3);//按键释放
  358.                                 if(key1num==1)//若功能键第一次按下
  359.                                 {
  360.                                         sec--;//则调整秒减1
  361.                                         if(sec==-1)//若减到负数则将其重新设置为59
  362.                                                 sec=59;
  363.                         E_display_L(3,6*8,sec/10);//秒若变化则重新写入
  364.                         E_display_L(3,7*8,sec%10);//秒若变化则重新写入
  365.                                 //        write_sfm(6,sec);//每调节一次送液晶显示一下
  366.                                 //        write_com(0x80+0x40+7);//显示位置重新回到调节处
  367.                                 }
  368.                                 if(key1num==2)//若功能键第二次按下
  369.                                 {
  370.                                         min--;//则调整分钟减1
  371.                                         if(min==-1)//若减到负数则将其重新设置为59
  372.                                                 min=59;
  373.                                         E_display_L(3,3*8,min/10);//分若变化则重新写入
  374.                                  E_display_L(3,4*8,min%10);//分若变化则重新写入
  375.                                 //        write_sfm(3,min);//每调节一次送液晶显示一下
  376.                         //        write_com(0x80+0x40+4);//显示位置重新回到调节处
  377.                                 }
  378.                                 if(key1num==3)//若功能键第二次按下
  379.                                 {
  380.                                         hour--;//则调整小时减1
  381.                                         if(hour==-1)//若减到负数则将其重新设置为23
  382.                                                 hour=23;
  383.                                                 E_display_L(3,0*8,hour/10);//小时若变化则重新写入
  384.                                     E_display_L(3,1*8,hour%10);//小时若变化则重新写入
  385.                                 //        write_sfm(0,hour);//每调节一次送液晶显示一下
  386.                                 //        write_com(0x80+0x40+1);//显示位置重新回到调节处
  387.                                 }
  388.                         }
  389.                 }
  390.         }
  391. }
  392. /*主函数*/
  393. void main()
  394. {
  395.         Init_LCD();
  396.         hour=0;         //初始化时间
  397.         min=1;
  398.         sec=37;
  399.         count=0;
  400.         C_display_L(1,0*8,0); //倒计时
  401.         C_display_L(1,3*8,1);
  402.         C_display_L(1,6*8,2);
  403.                         E_display_L(3,0*8,hour/10);//小时若变化则重新写入
  404.                         E_display_L(3,1*8,hour%10);//小时若变化则重新写入
  405.                         E_display_L(3,2*8,19);//冒号                        
  406.                         E_display_L(3,3*8,min/10);//分若变化则重新写入
  407.                         E_display_L(3,4*8,min%10);//分若变化则重新写入
  408.                         E_display_L(3,5*8,19);//冒号               
  409.                         E_display_L(3,6*8,sec/10);//秒若变化则重新写入
  410.                         E_display_L(3,7*8,sec%10);//秒若变化则重新写入
  411.                 TMOD=0x01;//设置定时器0工作模式1
  412.         TH0=(65536-50000)/256;//定时器装初值
  413.         TL0=(65536-50000)%256;
  414.         EA=1; //开总中断
  415.         ET0=1; //开定时器0中断
  416.         TR0=1; //启动定时器0
  417.         while(1)
  418. {                         keyscan();
  419.                 if(hour==0&min==0&sec==0)
  420.                 {
  421.                 bj=0;
  422.                 EA=0;}        
  423.                                 }
  424.                           }


  425. void timer0() interrupt 1//定时器0中断服务程序
  426. {
  427.         TH0=(65536-50000)/256;//再次装定时器初值
  428.         TL0=(65536-50000)%256;
  429.         count++; //中断次数累加
  430.         if(count==1) //20次50毫秒为1秒
  431.         {
  432.                 count=0;
  433.                 sec--;
  434.                 if(sec==-1)//秒加到60则进位分钟
  435.                 {
  436.                         sec=59;//同时秒数清零
  437.                         min--;
  438.                         if(min==-1)//分钟加到60则进位小时
  439.                         {
  440.                                 min=59;//同时分钟数清零
  441.                                 hour--;
  442.                                 if(hour==-1)//小时加到24则小时清零
  443.                                 {
  444.                                         hour=23;
  445.                                 }
  446.                         E_display_L(3,0*8,hour/10);//小时若变化则重新写入
  447.                         E_display_L(3,1*8,hour%10);//小时若变化则重新写入
  448.                         }
  449.                         E_display_L(3,3*8,min/10);//分变化则重新写入
  450.                         E_display_L(3,4*8,min%10);//分变化则重新写入
  451.                 }
  452.                         E_display_L(3,6*8,sec/10);//秒若变化则重新写入
  453.                         E_display_L(3,7*8,sec%10);//秒若变化则重新写入

  454.         }
  455. }         
复制代码

所有资料51hei提供下载:
12864可调倒计时可调显示okampire12864.rar (130.72 KB, 下载次数: 26)


评分

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

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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