找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5272|回复: 7
收起左侧

基于51单片机的红外无线计算器设计

[复制链接]
ID:272887 发表于 2018-1-7 20:17 | 显示全部楼层 |阅读模式
本设计利用红外线作为传输介质,利用红外遥控其实现数据的输入。其次用单片机处理数据,计算结果采用1602液晶显示器显示,可支持负数的输出。系统基本实现了计算器的加减乘除功能。



1系统方案
1.1 红外部分的论证与选择
1.2 显示部分的论证与选择
1.3 控制系统的论证与选择
2系统理论分析与计算
3电路与程序设计
3.1电路的设计
3.1.1系统总体框图
3.1.2控制部分子系统框图与电路原理图
3.1.3 红外部分子系统框图与电路原理图
3.1.4 1602显示子系统框图与电路原理图
3.1.5电源
3.2程序的设计
3.2.1程序功能描述与设计思路
3.2.2程序流程图
4测试方案与测试结果
4.1测试方案
4.2 测试结果及分析
附录1:源程序

基于STC89C516RD+的红外计算器
技术部
1系统方案
本系统主要由红外部分、控制系统部分、显示部分组成,电源直接使用5V直流电。下面分别论证这几个模块的选择。
1.1    红外部分的论证与选择
由于采用矩阵键盘的输入方式会浪费单片机过多的IO口,且键盘扫描函数过于冗长。所以本系统摒弃了矩阵键盘的输入,采用红外遥控输入。红外输入用红外遥控器,接收用一体化红外接收头。整个红外接收只用了3个IO口,使系统的电路设计个更为简便。
1.2    显示部分的论证与选择
系统显示部分采用市场出售的基于HD44780液晶芯片的1602液晶显示器。此类显示器可显示数字和常用的字符。适合用于计算器的设计。
1.3    控制部分的论证与选择
控制部分采用单片机STC90C516RD+实现。由于该计算器程序所用的ROM和RAM较小,没有必要用增强型的1T单片机例如STC12C5A60S2。所以用普通的51单片机即可。系统采用了12M的晶振。实现了对数据的有效处理。
2系统理论分析与计算
              开启系统之后,单片机就一直检测有无红外数据的输入,若有则在单片机中实现数据的处理,后将数据传输到1602显示屏显示出来。
3电路与程序设计3.1电路的设计3.1.1系统总体框图

由于本系统在普中开发板上实现,没有另外焊接电路,故系统电路图省略。

3.1.2 控制部分子系统框图与电路原理图
1、控制部分子系统框图

图1   控制部分子系统框图
3.1.3 红外子系统框图与电路原理图
1、红外子系统框图

图3   红外子系统框图
3.1.4LCD1602显示子系统框图与电路原理图

图3   LCD1602显示子系统框图

3.1.5电源

电源直接使用(普中单片机开发板上的)直流5V供电,确保电路的正常稳定工作。这部分电路比较简单,故不作详述。

3.2程序的设计3.2.1程序功能描述与设计思路

1、程序功能描述

根据题目要求软件部分主要实现红外解码,计算函数和显示函数。

1)红外解码及将键值显示为指定字符。

2)计算器核心计算部分。

3)显示输入的算式及结果。

2、程序设计思路

3.2.2程序流程图

1、主程序流程图

4测试方案与测试结果4.1测试方案

1、硬件测试

              基于普中单片机开发测试仪测试


4.2 测试结果及分析
此设计符合原先设想,一切正常。

综上所述,本设计达到设计要求。


参考文献
《新概念51单片机c语言教程》 , 《C程序设计》


附录1:源程序

单片机源程序如下:
  1. /****************************************************************************/
  2. /*                                                                                    红外线计算器                                                                                                                                            */
  3. /*功能:可实现整数的加减乘除(由红外遥控输入,1602显示)                                                                      */                                                                                                
  4. /*                            可实现负数的结果输出                                                                                                                                                                        */
  5. /*                                                                                                                                                                                                                                                                */
  6. /*作者:                                                                                                                                                                                                                                */
  7. /****************************************************************************/


  8. /****************************头文件*******************************************/
  9. #include<reg52.h>
  10. /*****************************宏定义******************************************/
  11. #define uchar unsigned char
  12. #define uint unsigned int
  13. #define lin P0                             //宏定义数据口

  14. /******************************位定义*****************************************/
  15. sbit BEEP = P1^5;                         //定义蜂鸣器端口
  16. sbit IRIN=P3^2;                                       //定义红外使用的中断
  17. sbit lcd1602e=P2^7;                         //1602使能端
  18. sbit lcd1602rw=P2^5;                     // 1602读写选择端
  19. sbit lcd1602rs=P2^6;                     // 1602数据命令选择端

  20. /******************************函数声明***************************************/
  21. void delay(uint c);            //延时函数
  22. void writeorder(uchar order);  //写命令函数
  23. void writedata(uchar dat);                 //写数据函数
  24. void initialize();                                             //1602初始化函数
  25. void beep();                                                           //蜂鸣器发声函数
  26. void IrInit();                                                           //红外初始化函数
  27. void outwork(int a);                               //结果显示函数
  28. void IRdelay(unsigned char x); //红外解码延时函数  


  29. /******************************定义全局变量或数组*****************************/
  30. unsigned char IRCOM[6];                     //定义红外解码所用数组

  31. /*******************************主函数****************************************/

  32. void main(void)                                       //主函数
  33. {            
  34.               uchar codedata[]="   welcome you ";                            //定义初始显示界面
  35.                  uchar codedata1[]=" lin chuang wei ";

  36.               uint flag=0,lin0,lin1,k=0;                                              //定义局部变量
  37.               uchar flagfu,fuhao=0,beeplin=0,i,j;
  38.               int a=0,b=0,c=0;

  39.               initialize();                                                                                                  //1602初始化

  40.               for(j=100;j>0;j--)
  41.   {            
  42.                             writeorder(0x80);                   //设置数据指针起点,显示在第一行
  43.                             for(i=0;i<16;i++)
  44.                             writedata(codedata1[i]);
  45.                             writeorder(0x80+0x40);              //设置数据指针起点,显示在第二行
  46.                             for(i=0;i<14;i++)
  47.                                           {
  48.                                           writedata(codedata[i]);            
  49.                                           }
  50.    }
  51.             
  52.             
  53.               IrInit();                                                                                                                //红外初始化
  54.               initialize();                                                                                                  //1602初始化
  55.               writeorder(0x80);                                   //设置显示位置


  56. while(1)
  57.               {                                                                                                                                              //红外解码
  58.                             writeorder(0x06);                                                                      //设置指针加1
  59.                            
  60.                   IRCOM[5]=IRCOM[2]>>4;                                               //高位
  61.                             IRCOM[6]=IRCOM[2]&0x0f;                                     //低位            
  62.                             if(IRCOM[5]>9)
  63.                             {
  64.                                           lin0=0x37+IRCOM[5];              //将数值转换为该显示的ASCII码
  65.                             }
  66.                             else
  67.                             {
  68.                                 lin0=IRCOM[5]+0x30;              //将数值转换为该显示的ASCII码
  69.                             }            
  70.                             if(IRCOM[6]>9)
  71.                             {                           
  72.                                 lin1=IRCOM[6]+0x37;                           //将数值转换为该显示的ASCII码
  73.                             }
  74.                             else
  75.                             {                           
  76.                                 lin1=IRCOM[6]+0x30;                           //将数值转换为该显示的ASCII码
  77.                             }               
  78.                             if((lin0==49)&&(lin1==54))writedata(flagfu='0'); //显示0
  79.               else if((lin0==48)&&(lin1==67))writedata(flagfu='1'); //显示1
  80.               else if((lin0==49)&&(lin1==56))writedata(flagfu='2'); //显示2
  81.               else if((lin0==53)&&(lin1==69))writedata(flagfu='3'); //显示3
  82.               else if((lin0==48)&&(lin1==56))writedata(flagfu='4'); //显示4
  83.               else if((lin0==49)&&(lin1==67))writedata(flagfu='5'); //显示5
  84.               else if((lin0==53)&&(lin1==65))writedata(flagfu='6'); //显示6
  85.               else if((lin0==52)&&(lin1==50))writedata(flagfu='7'); //显示7
  86.               else if((lin0==53)&&(lin1==50))writedata(flagfu='8'); //显示8
  87.               else if((lin0==52)&&(lin1==65))writedata(flagfu='9'); //显示9
  88.               else if((lin0==52)&&(lin1==53))                                                                                      //删除所有显示
  89.                             {
  90.                                           writeorder(0x01);                                                                                                    //清屏
  91.                                           writeorder(0x80);                                                                                                    //设置数据指针起点
  92.                                           a=0;b=0;                                                                                                                                //初始化a,b,避免计算出错
  93.                             }                                
  94.   //else if((lin0==52)&&(lin1==54))                       //剩下1个空按键
  95.               else if((lin0==52)&&(lin1==55))beeplin=1;             // 关声音
  96.               else if((lin0==52)&&(lin1==52))writedata(flagfu='='); //显示=
  97.               else if((lin0==52)&&(lin1==48))writeorder(0x10);      //光标左移1位
  98.               else if((lin0==52)&&(lin1==51))writeorder(0x14);      //光标右移1位
  99.               else if((lin0==48)&&(lin1==55))                                                                                      //删除一位数
  100.               {
  101.                             writeorder(0x10);
  102.                             writedata(' ');
  103.                             writeorder(0x10);
  104.               }
  105.               else if((lin0==49)&&(lin1==53))writedata(flagfu='-');  //显示-
  106.               else if((lin0==48)&&(lin1==57))writedata(flagfu='+');  //显示+
  107.               else if((lin0==49)&&(lin1==57))writedata(flagfu='*');  //显示*
  108.               else if((lin0==48)&&(lin1==68))writedata(flagfu='/');  //显示/
  109.             
  110.               if(beeplin==0)                                                                                                                                               //如果beeplin=0则蜂鸣器发声
  111.                             beep();

  112.                 switch(flagfu)                                                                                                                                  //计算函数                                                                        
  113.                 {                                                      
  114.               case '=': switch(fuhao)
  115.                                     {              case'+':a=b+a;outwork(a);break;                                                      
  116.                                                                                                     case'-':a=b-a;outwork(a);break;
  117.                                                                                                      case'*':a=a*b;outwork(a);break;                                                                     
  118.                                                                                         case'/':a=b/a;outwork(a);break;            
  119.                                                                                                   default:break;                                                                                                                                               
  120.                                                                                     }            
  121.                                                                                     break;            
  122.                  case '+':fuhao='+';b=a;k=0;break;                                                      
  123.                  case '-':fuhao='-';b=a;k=0;break;                                                                                                                                                                                                                                                   
  124.                  case '*':fuhao='*';b=a;k=0;break;                                         
  125.                  case '/':fuhao='/';b=a;k=0;break;                                                                                                                                                                                                            
  126.                  case '0':
  127.                  case '1':
  128.                  case '2':
  129.                  case '3':
  130.                  case '4':
  131.                  case '5':                    
  132.                  case '6':                                                                                                     
  133.                  case '7':
  134.                  case '8':
  135.                  case '9':a=(flagfu-'0')+a*k*10;k=1;;  break;                             //可实现多位数的输入
  136.                                                                                                                                                 
  137.                             }

  138.                
  139.                
  140.                 while(IRIN);                                                                                                                                                          //如果没有发生中断则一直停在这里,避免while(1)重复执行
  141.               }                                                                                                                                                                                                                                                                                
  142. }                                                                                                                             

  143. /******************************延时函数*****************************************/
  144. void delay(uint c)
  145.   { uchar a,b;
  146.   for(a=c;a>0;a--)
  147.     for(b=110;b>0;b--);
  148. }

  149. /*******************************发声函数****************************************/
  150. void beep()
  151. {
  152.   unsigned char i;
  153.   for (i=0;i<20;i++)
  154.    {
  155.    delay(5);
  156.    BEEP=!BEEP;                 //BEEP取反
  157.    }
  158.   BEEP=1;                      //关闭蜂鸣器
  159. }

  160. /*******************************红外初始化函数**********************************/
  161. void IrInit()
  162. {
  163.               IT0=1;//下降沿触发
  164.               EX0=1;//打开中断0允许
  165.               EA=1;              //打开总中断

  166.               IRIN=1;//初始化端口
  167. }

  168. /********************************红外延时函数************************************/
  169. void IRdelay(unsigned char x)    //x*0.14MS
  170. {
  171. unsigned char i;
  172.   while(x--)
  173. {
  174.   for (i = 0; i<13; i++) {}
  175. }
  176. }

  177. /********************************1602写命令函数***********************************/
  178. void writeorder(uchar order)                //写入命令
  179. {

  180.               lcd1602rs = 0;                 //选择发送命令
  181.     lcd1602rw = 0;                 //选择写入
  182.             
  183.     lin=order;    //放入命令
  184.               delay(1);                            //等待数据稳定

  185.     lcd1602e = 1;                        //写入时序
  186.     delay(5);                //保持时间
  187.     lcd1602e=0;
  188. }   

  189. /********************************1602写数据函数************************************/
  190. void writedata(uchar dat)                                          //写入数据
  191. {

  192.               lcd1602rs = 1;              //选择输入数据
  193.               lcd1602rw = 0;              //选择写入

  194.               lin = dat; //写入数据
  195.       delay(1);

  196.               lcd1602e= 1;   //写入时序
  197.               delay(5);   //保持时间
  198.               lcd1602e=0;
  199. }

  200. /**********************************1602初始化函数************************************/
  201. void initialize()                                                                                      //LCD初始化子程序
  202. {              lcd1602e = 0;     //使能
  203.               writeorder(0x38);  //开显示
  204.               writeorder(0x0f);  //开显示不显示光标
  205.               writeorder(0x06);  //写一个指针加1
  206.               writeorder(0x01);  //清屏
  207. }

  208. /***********************************显示函数******************************************/
  209. void outwork(int a)
  210. {                                          
  211.               uchar i,shu[6];
  212.               uint k=0;
  213.               if(a<0)                                                                                       //若是负数,显示负号
  214.                             {writeorder(0x80+0x49);
  215.                             writedata('-');            
  216.                             a=-a;            
  217.                             }            
  218.                                                                                                                         //分离结果
  219.             shu[0]='0'+a/100000;                  //十万
  220.                                           shu[1]='0'+a/10000%10;                            //万
  221.                                           shu[2]='0'+a/1000%10;                  //千
  222.                                           shu[3]='0'+a/100%10;                            //百
  223.                                           shu[4]='0'+a/10%10;                      //十
  224.                                           shu[5]='0'+a%10;                      //个

  225.                             writeorder(0x80+0x4a);
  226.                             for(i=0;i<5;i++)                          //如果前面几位为0就显示空格
  227.                                if(shu[i]=='0')
  228.                                   shu[i]=' ';
  229.                                else
  230.                                                 break;
  231.                             for(i=0;i<6;i++)
  232.                                writedata(shu[i]);
  233. }
  234. /*              while(c!=0)
  235. {                                                                                                      //另一种思路的显示函数
  236. write_date(0x30+c%10);
  237. c=c/10;
  238. }
  239. */



  240. /*******************************红外中断函数****************************************/
  241. void IR_IN(void) interrupt 0      //  进入中断,开始处理红外信号
  242. {
  243.                 unsigned char j,k,N=0;
  244.                 EX0 = 0;                    //进入中断后先关掉中断
  245.                               
  246.                 IRdelay(5);
  247.                 if (IRIN==1)                //  这里是避免干扰信号影响,如出现干扰信号,将会屏蔽掉
  248.                 {
  249.                                  EX0 =1;
  250.                                return;
  251.                 }
  252.                                             //确认IR信号出现
  253.                 while (!IRIN)               //等IR变为高电平,跳过9ms的前导低电平信号。
  254.                 {
  255.                               IRdelay(1);
  256.                 }
  257. ……………………

  258. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

完整的Word格式文档51黑下载地址:
基于单片机-的红外简易计算器设计1.doc (252 KB, 下载次数: 66)

评分

参与人数 1黑币 +5 收起 理由
zqy181818 + 5 赞一个!

查看全部评分

回复

使用道具 举报

ID:342288 发表于 2018-6-3 18:51 | 显示全部楼层
你好,请问有程序和仿真图的下载吗?
回复

使用道具 举报

ID:310558 发表于 2018-6-3 23:16 来自手机 | 显示全部楼层
试一试,谢谢分享
回复

使用道具 举报

ID:359778 发表于 2018-6-27 08:57 | 显示全部楼层
请问一下,有电路完整的图吗。
回复

使用道具 举报

ID:399282 发表于 2018-9-20 00:02 | 显示全部楼层
你好,我在尝试你的程序发现了几种运算均出现了问题
回复

使用道具 举报

ID:422073 发表于 2018-11-6 22:54 | 显示全部楼层
simon小白 发表于 2018-9-20 00:02
你好,我在尝试你的程序发现了几种运算均出现了问题

你好,你解决了吗
回复

使用道具 举报

ID:538338 发表于 2019-5-14 21:02 | 显示全部楼层
哇,大神啊,学单片机正好有用呢
回复

使用道具 举报

ID:538517 发表于 2019-5-15 02:55 来自手机 | 显示全部楼层
我只有摩拜的份了。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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