找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机计算器加温度报警器制作(仿真代码PCB)全新版本

[复制链接]
跳转到指定楼层
楼主
                    仿真  代码  原理图 PCB实物已设计整理好!各位下载可直接使用

      这是本人做的关于51单片机的一个小设计,主要将论坛里的温度报警器和计算器代码进行了整合,简单的说可以当做计算器使用也可以当做温度报警器使用。PCB也对各个版本进行了优化,原理图划分了功能块方便看不懂的小伙伴,这主要针对一些不会做手工PCB的小伙伴,而且现在立创和捷配的打样活动也比自己手工做PCB成本低很多,鉴于能白嫖就白嫖的原则,请大家不要错过。
      功能简单介绍:
      一、温度报警器功能
      插电后打开开关(开关可直接短接)初始化完成后LCD1602第一行居中显示实时温度,第二行显示HT:60 LT:2表示默认设置的温度上限以及下限,若温度超过上限或者低于下限值,对应led发光以提示用户。按下k2键,可进入温度报警器的设置模式,此时lcd显示屏幕上第一行最末尾出现H或者L,表示此时可按K3,K4对对应的HT或者LT的上下限值进行加减来改变报警阈值,并且这三个按键按下时蜂鸣器会有响声提醒。
     二、计算器功能
     按下K1键可切换为计算器模式,此时矩阵键盘生效,lcd显示屏幕清空,进入计算器模式,矩阵键盘上PCB丝印字体对应按键按下的值。其余不多做解释,按照正常计算器玩法操作。再按下K1键可切换回温度报警器模式。
     代码篇幅有限,这里不做介绍,上传文件中可自行查阅。有其他建议联系我哈。
制作出来的实物图如下:

Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)


单片机源程序如下:
  1. /*******************************************************************************
  2. *  标题:                       LCD1602简易计算器                               *
  3. *                                                                                                                                                           *
  4. *  实验说明:1602简易计算器,可以实现四位数以内的加减乘除,                                     *                                                      
  5. ********************************************************************************
  6. * 实验心得:当内部ram不够用的时候,可以定义成xdata,使用外部ram,但是有一个问题*
  7. 就是在用proteus仿真的时候,如果有xdata的代码,可能仿真会出现点问题,因为peoteus*
  8. 不支持外部扩展ram                                                               *
  9. ********************************************************************************/
  10. #include<reg52.h>        
  11. #include"lcd.h"
  12. #include"math.h"
  13. #include"temp.h"
  14. #include"intrins.h"
  15. //--定义使用的IO口--//        
  16. #define GPIO_KEY P1
  17. sbit K_set=P3^3;
  18. sbit K_up=P3^5;
  19. sbit K_down=P3^6;
  20. sbit bee_key=P3^7;
  21. sbit ledL=P2^3;
  22. sbit ledH=P2^4;


  23. unsigned char setting_flag=0,up_flag=0,down_flag=0;

  24. //--定义全局变量--//
  25. unsigned char code XuJian[16]="01470258=369+-x/";
  26. long value[16];
  27. unsigned char Num[8];//此处写成unsigend char xdata Num[8]时,实物可以用,但是仿真有点问题,因为proteus不支持外部扩展ram.
  28. unsigned long result;//运算结果
  29. unsigned int flag=0;//标志位
  30. unsigned int  m;
  31. unsigned int c=0;
  32. long First=0;//输入的第一位数
  33. long Second=0;//输入的第二位数
  34. unsigned int Key;//符号判断,如果key=12,为+,13,为-,14为×,15为/。
  35. unsigned char KeyValue=-1;
  36. //用来存放读取到的键值

  37. //--声明全局函数--//
  38. int KeyScan(void);//键值判断函数
  39. void Delay10ms(unsigned int c);   //误差 0us
  40. void RES();//结果运算函数
  41. //

  42. //模式切换标致
  43. unsigned char moshi_flag=0,temp_max=60,temp_min=2,lcd_flag=0;
  44. unsigned int temp=0;
  45. uchar code Init1[]="    DB:000   ";          //初始化时1行显示
  46. uchar code Init2[]="  HT:000 LT:000  ";          //初始化时2行显示
  47. void Init1602_temp()
  48. {
  49.   uchar i=0;
  50.   LcdWriteCom(0x38);//屏幕初始化
  51.   LcdWriteCom(0x0c);//打开显示 无光标 无光标闪烁
  52.   LcdWriteCom(0x06);//当读或写一个字符是指针后一一位
  53.   LcdWriteCom(0x01);//清屏
  54.   LcdWriteCom(0x80);//设置位置

  55.   for(i=0;i<16;i++)                  
  56.   {
  57.                 LcdWriteData(Init1[i]); //1行初始化显示
  58.   }
  59.   LcdWriteCom(0x80+0x40);
  60.   for(i=0;i<16;i++)
  61.   {
  62.                 LcdWriteData(Init2[i]);//2行初始化显示
  63.   }
  64. }
  65.   //显示实时温度
  66. void display_temp(unsigned int temp)
  67. {         
  68.         unsigned char a,b,c;
  69.         
  70.   a=temp/1000%10;
  71.   b=temp/100%10;
  72.   c=temp/10%10;

  73.    LcdWriteCom(0x80+7);
  74.    LcdWriteData(a+0x30);
  75.     LcdWriteData(b+0x30);
  76.          LcdWriteData('.');
  77.          LcdWriteData(c+0x30);


  78. }
  79. //显示温度上下限

  80. void display_temp_M(unsigned char temp_max,unsigned char temp_min)
  81. {        
  82.         unsigned char a,b,c;
  83.         a=temp_max/100;
  84.         b=temp_max/10%10;
  85.         c=temp_max%10;
  86.           LcdWriteCom(0x80+0x40+5);
  87.            LcdWriteData(a+0x30);
  88.     LcdWriteData(b+0x30);
  89.         LcdWriteData(c+0x30);
  90.         a=temp_min/100;
  91.         b=temp_min/10%10;
  92.         c=temp_min%10;
  93.           LcdWriteCom(0x80+0x40+12);
  94.            LcdWriteData(a+0x30);
  95.     LcdWriteData(b+0x30);
  96.         LcdWriteData(c+0x30);


  97. }
  98. void Delay500us()                //@11.0592MHz
  99. {
  100.         unsigned char i, j;

  101.         _nop_();
  102.         _nop_();
  103.         i = 6;
  104.         j = 93;
  105.         do
  106.         {
  107.                 while (--j);
  108.         } while (--i);
  109. }
  110. void bee_anjian(unsigned int c )
  111. {        
  112.     unsigned char a, b;
  113.         bee_key=0;
  114.         //--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
  115.     for (;c>0;c--)
  116.         {
  117.                  bee_key=!bee_key;
  118.                  Delay500us();        
  119.                  
  120.         }
  121.         bee_key=0;      
  122. }


  123. void temp_scan()//按键扫描
  124. {        unsigned char dis_play_flag=0;
  125. if(K_set==0)  //判断设置是否按下
  126. {
  127. Delay10ms(1);
  128. if(K_set==0)
  129. { bee_key=0;
  130. setting_flag=setting_flag+1;
  131. dis_play_flag=1;
  132. if(setting_flag>2)
  133. {setting_flag=0;}
  134. //        bee_anjian(100);
  135. //bee_anjian(100);
  136. Delay10ms(50);

  137. }
  138. }
  139. if(dis_play_flag)
  140. {
  141.          
  142.         if(setting_flag==1)
  143.         {
  144.         LcdWriteCom(0x80+15);
  145.         LcdWriteData('H');
  146.         }
  147.         else if(setting_flag==2)
  148.         {
  149.         LcdWriteCom(0x80+15);
  150.         LcdWriteData('L');
  151.         }
  152.         else
  153.         {
  154.         LcdWriteCom(0x80+15);
  155.         LcdWriteData(' ');
  156.         }
  157.            dis_play_flag=0;


  158. }

  159. if(setting_flag)   //设置按下
  160. {        
  161.          if(K_up==0)
  162.         {
  163.         Delay10ms(1);
  164.         if(K_up==0)
  165.         {
  166.         bee_key=0;        
  167.          up_flag=1;
  168.         }
  169. }



  170. }
  171. if(setting_flag)
  172. {        
  173.          if(K_down==0)
  174.         {
  175.         Delay10ms(1);

  176.         if(K_down==0)
  177.         {
  178.         bee_key=0;        
  179.          down_flag=1;
  180.         }
  181. }

  182. }
  183. if(up_flag==1)
  184. {
  185. if(setting_flag==1)
  186. {
  187.         temp_max=temp_max+1;


  188.         if(temp_max>99)
  189.         {temp_max=99;}        

  190.         display_temp_M(temp_max,temp_min);        
  191.         
  192. //        bee_anjian(50);
  193. //bee_anjian(100);
  194. Delay10ms(50);
  195.         up_flag=0;

  196. }
  197. else if(setting_flag==2)
  198. {
  199.         temp_min=temp_min+1;


  200.         if(temp_min>99)
  201.         {temp_min=99;}        

  202.         display_temp_M(temp_max,temp_min);        
  203. //        bee_anjian(50);
  204. //bee_anjian(100);
  205. Delay10ms(50);
  206.         up_flag=0;


  207. }

  208. }
  209. if(down_flag==1)
  210. {
  211. if(setting_flag==1)
  212. {
  213. temp_max=temp_max-1;

  214. if(temp_max<1)
  215. {temp_max=1;}        
  216. display_temp_M(temp_max,temp_min);
  217. Delay10ms(50);
  218. // bee_anjian(100);

  219. down_flag=0;        
  220. }
  221. else if(setting_flag==2)
  222. {
  223. temp_min=temp_min-1;

  224. if(temp_min<1)
  225. {temp_min=1;}        
  226. display_temp_M(temp_max,temp_min);
  227. Delay10ms(50);
  228. //bee_anjian(100);
  229. down_flag=0;        
  230. }

  231. }

  232. bee_key=1;
  233. }



  234. //中断函数初始化
  235. void Init_INT()
  236. {

  237.         IT0 = 1;                          //设置为下降沿触发
  238.     EX0 = 1;                          //外部中断0中断允许位                    
  239.     EA = 1;

  240. }

  241. void EX0_ISR(void) interrupt 0                //中断服务函数的书写格式
  242. {
  243.    
  244.         moshi_flag=!moshi_flag;
  245.         lcd_flag=moshi_flag+1;
  246.          
  247.    
  248. }


  249. /*******************************************************************************
  250. * 函 数 名         : main
  251. * 函数功能                   : 主函数
  252. * 输    入         : 无
  253. * 输    出         : 无
  254. *******************************************************************************/
  255. void main(void)
  256. {
  257.         LcdInit();
  258. //        for(i=0;i<7;i++)
  259. //        {
  260. //                LcdWriteData(TiShi[i]);
  261. //        }
  262.         Init_INT();//开启外部中断
  263.         Init1602_temp();
  264.         bee_anjian();
  265.         while(1)
  266.         {         


  267.         if(lcd_flag==1)
  268.         {
  269.          Init1602_temp();
  270.          lcd_flag=0;
  271.         }
  272.         else if(lcd_flag==2)
  273.         {
  274.         LcdInit();
  275.         lcd_flag=0;
  276.         }
  277.         if(moshi_flag==1)
  278.         {
  279.             KeyValue=KeyScan();
  280.                 switch(KeyValue)
  281.                 {
  282.                         case(0):
  283.                         LcdWriteCom(0x01);
  284.                         KeyValue=-1;
  285.                         First=0;
  286.                         Second=0;
  287.                         c=0;
  288.                         break;

  289.                         case(1):                        
  290.                         if(flag==0)//flag为0时,正常计算
  291.                         {
  292.                         LcdWriteData(XuJian[1]);
  293.                         KeyValue=-1;
  294.                         if(c==0)
  295.                         First=10*First+1;
  296.                         else if(c==1)
  297.                         Second=10*Second+1;
  298.                         }

  299.                         else if(flag==1)//flag为1时,可以在第一次运算好后,继续输入数字,开始第二次计算
  300.                         {
  301.                     LcdWriteCom(0x01);
  302.                         LcdWriteData(XuJian[1]);
  303.                         KeyValue=-1;
  304.                         First=0;
  305.                         Second=0;
  306.                         c=0;
  307.                         flag=0;
  308.                         
  309.                         ................限于篇幅代码请下载附件................

  310.         do
  311.         {
  312.         value[i]=result%10;
  313.         result/=10;
  314.         i++;
  315.         }while((result/10)!=0);

  316.         value[i]=result;
  317.         m=i;

  318.         for(j=0;j<=i;j++) //for循环如果是for(j=i;j>=0;j++)就会出现不同的结果,很奇怪
  319.         {
  320.                   Num[j]=value[j]+'0';
  321.         }

  322.         for(i=0;i<=m;i++)//这里的for循环也是和上面一样的结果,改成for(i=m;i>=0;i--)就会出现奇怪的结果,有兴趣的可以试试。
  323.     {
  324.                 LcdWriteData(Num[m-i]);
  325.         }
  326.         

  327. }


  328. /*******************************************************************************
  329. * 函 数 名         : KeyScan
  330. * 函数功能                   : 检测有按键按下并读取键值
  331. * 输    入         : 无
  332. * 输    出         : 无
  333. *******************************************************************************/

  334. int KeyScan(void)          //测试行(row)的时候就是线是竖着的的那一列为1,测试列(col)的时候就是线是横着的那几行为1
  335. {
  336.         char a = 0;
  337.         GPIO_KEY=0x0f;
  338.         if(GPIO_KEY!=0x0f)//读取按键是否按下
  339.         {
  340.                 Delay10ms(1);//延时10ms进行消抖
  341.                 if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
  342.                 {
  343.                         
  344.                         //测试列
  345.                         GPIO_KEY=0X0F;
  346.                         switch(GPIO_KEY)
  347.                         {
  348.                                 case(0X07):        KeyValue=0;break;
  349.                                 case(0X0b):        KeyValue=4;break;
  350.                                 case(0X0d): KeyValue=8;break;
  351.                                 case(0X0e):        KeyValue=12;break;
  352.                         }
  353.                         //测试行
  354.                         GPIO_KEY=0XF0;
  355.                         switch(GPIO_KEY)
  356.                         {
  357.                                 case(0X70):        KeyValue=KeyValue+3;break;
  358.                                 case(0Xb0):        KeyValue=KeyValue+2;break;
  359.                                 case(0Xd0): KeyValue=KeyValue+1;break;
  360.                                 case(0Xe0):        KeyValue=KeyValue;break;
  361.                         }
  362.                         while((a<50) && (GPIO_KEY!=0xf0))         //检测按键松手检测
  363.                         {
  364.                                 Delay10ms(1);
  365.                                 a++;
  366.                         }
  367.                 }
  368.         }
  369.         return KeyValue;

  370. }

  371. /*******************************************************************************
  372. * 函 数 名         : Delay10ms
  373. * 函数功能                   : 延时函数,延时10ms
  374. * 输    入         : 无
  375. * 输    出         : 无
  376. *******************************************************************************/

  377. void Delay10ms(unsigned int c)   //误差 0us
  378. {
  379.     unsigned char a, b;

  380.         //--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
  381.     for (;c>0;c--)
  382.         {
  383.                 for (b=38;b>0;b--)
  384.                 {
  385.                         for (a=130;a>0;a--);
  386.                 }         
  387.         }      
  388. }
复制代码

所有资料51hei提供下载:
温度报警加简易计算器资料.7z (3.52 MB, 下载次数: 76)

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:315554 发表于 2021-4-22 15:00 | 只看该作者
谢谢分享,1620显示很想学一下,
回复

使用道具 举报

板凳
ID:430492 发表于 2021-4-24 20:17 | 只看该作者
这算是多功能计算器吧,增加了温度显示,不错!还可以扩展其他应用啊!!
回复

使用道具 举报

地板
ID:541089 发表于 2021-4-28 22:53 | 只看该作者
cooleaf 发表于 2021-4-24 20:17
这算是多功能计算器吧,增加了温度显示,不错!还可以扩展其他应用啊!!

对对,按照小伙伴题目要求来的,只要性能够用,啥都可以拓展
回复

使用道具 举报

5#
ID:541089 发表于 2021-5-27 23:26 | 只看该作者
注意:代码是和PCB完全对应的,仿真引脚有轻微变动,仿真时注意改一下代码引脚
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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