51单片机通过红外遥控控制直流电机是否转动并在LCD1602显示

[复制链接]
查看18 | 回复0 | 2021-6-28 00:48:25 | 显示全部楼层 |阅读模式
部分单片机源程序如下:(完整见附件)
  1. /*
  2. 实验说明:
  3.         根据自己使用的LCD1602是否带有转接板,如果带有转接板的即为4位,需在LCD.H头文件中
  4.         将宏#define LCD1602_4PINS打开,我们这里使用的LCD1602是8位,所以默认将该宏注释。
  5. 实验接线:
  6.         1,LCD1602液晶模块-->单片机管脚
  7.         参考LCD1602液晶显示实验接线(开发攻略内在对应的实验章节内实验现象有接线说明)
  8.         2,红外接收模块-->单片机管脚
  9.         参考红外遥控实验接线(开发攻略内在对应的实验章节内实验现象有接线说明)
  10.         3,直流电机模块-->单片机管脚
  11.         IN1-->P10(参考直流电机实验接线)
  12.       
  13. 实验现象:
  14.         LCD1602显示遥控器键值,并且显示电机状态(ON/OFF),通过按第一个按键可以控制马达的启动和停止
  15. */


  16. #include<reg51.h>
  17. #include"lcd.h"

  18. typedef unsigned char uint8;
  19. typedef unsigned int uint16;


  20. sbit moto=P1^0;

  21. uint8 d1[8]=" RED IR ";
  22. uint8 d2[12]="MOTO STATE: ";
  23. uint8 num[16]="0123456789ABCDEF";

  24. uint8 irtime;          //接收时间
  25. uint8 startflag;  //开始检测
  26. uint8 bitnum;          //bit位数
  27. uint8 irdata[33]; //寄存没有个bit的时间
  28. uint8 irreceok;          //接收完成标志位
  29. uint8 ircode[4];  //将接收的四个字节数据保存
  30. uint8 irprosok;          //接收数据处理标志位
  31. uint8 irdisp[8];  //将四个字节的16进制通过转换变成十进制存储
  32. uint8 dat1,dat2;
  33. uint8 keynum;
  34. uint8 motoflag;
  35. void delay(uint16 i)
  36. {
  37.         while(i--);
  38. }
  39. void lcdwrc(uint8 c)
  40. {
  41.         LcdWriteCom(c);
  42. }
  43. void lcdwrd(uint8 dat)
  44. {
  45.         LcdWriteData(dat);      
  46. }
  47. void lcd_init()
  48. {
  49.         LcdInit();
  50. }
  51. void int0init()
  52. {
  53.         EA=1;
  54.         EX0=1;
  55.         IT0=1;
  56. }
  57. void time0init()
  58. {
  59.         TMOD=0X02;        //设置定时器0模式2.该模式为自动装载模式
  60.         TH0=0X00;
  61.         TL0=0X00;//设定计数初值,每当TL0计数到255时,TH0将把自己的数据给TL0,又重新计数
  62.         TR0=1;
  63.         ET0=1;
  64.         EA=1;      
  65. }
  66. void irpros() //红外接收数据处理 ,区分是数据0还是1
  67. {
  68.         uint8 i,j,value;
  69.         uint8 k=1;        //引导码去掉,所以令k=1;
  70.         for(j=0;j<4;j++)  //取出了一帧数据中的四个字节数据
  71.         {
  72.                 for(i=0;i<8;i++)        //取出了一个字节的数据               
  73.                 {
  74.                         value>>=1;
  75.                         if(irdata[k]>6)
  76.                         {
  77.                                 value=value|0x80;
  78.                         }
  79.                         k++;
  80.                 }
  81.                 ircode[j]=value;
  82.         }
  83.         irprosok=1;
  84. }
  85. void irwork()  //将四个字节的数据转换成10进制数显示
  86. {
  87.         irdisp[0]=ircode[0]/16;//显示高位
  88.         irdisp[1]=ircode[0]%16;//显示低位  
  89.         irdisp[2]=ircode[1]/16;
  90.         irdisp[3]=ircode[1]%16;         //同一个遥控器此2个字节的引导码数据是不会改变的,改变的只是数据码及反码
  91.         irdisp[4]=ircode[2]/16;
  92.         irdisp[5]=ircode[2]%16;
  93.         irdisp[6]=ircode[3]/16;
  94.         irdisp[7]=ircode[3]%16;
  95.         dat1=irdisp[4];
  96.         dat2=irdisp[5];
  97.         keynum++;
  98. }
  99. void display()
  100. {
  101.         uint8 i;
  102.         lcdwrc(0x00+0x80);
  103.         for(i=0;i<8;i++)
  104.         {
  105.                 lcdwrd(d1[i]);
  106.         }      
  107.         for(i=4;i<6;i++)
  108.         {
  109.                 lcdwrd(num[irdisp[i]]);
  110.         }
  111.         lcdwrc(0x40+0x80);
  112.         for(i=0;i<12;i++)
  113.         {
  114.                 lcdwrd(d2[i]);
  115.         }
  116.         if(motoflag==1)                        //马达状态显示
  117.         {
  118.                 lcdwrd('O');
  119.                 lcdwrd('N');
  120.                 lcdwrd(' ');
  121.         }
  122.         else
  123.         {
  124.                 lcdwrd('O');
  125.                 lcdwrd('F');
  126.                 lcdwrd('F');      
  127.         }
  128. }
  129. void motopros()
  130. {
  131.         if((dat1==4)&&(dat2==5)&&(keynum==1))  //按下第一次按键开马达
  132.         {                       
  133.                 dat1=0;
  134.                 dat2=0;
  135.                 motoflag=1;
  136.                 moto=1;                                               
  137.         }
  138.                        
  139.         if((dat1==4)&&(dat2==5)&&(keynum>=2))        //按下第二次此按键时关闭马达
  140.         {
  141.                 dat1=0;
  142.                 dat2=0;
  143.                 keynum=0;
  144.                 motoflag=0;
  145.                 moto=0;                       
  146.         }                              
  147. }
  148. void main()
  149. {
  150.         moto=0;      
  151.         lcd_init();
  152.         int0init();
  153.         time0init();
  154.         while(1)
  155.         {
  156.                 if(irreceok)
  157.                 {
  158.                         irreceok=0;
  159.                         irpros();
  160.                         if(irprosok)
  161.                         {
  162.                                 irwork();
  163.                         }
  164.                 }
  165.                 motopros();
  166.                 display();
  167.         }               
  168. }
  169. void time0() interrupt 1
  170. {
  171.         irtime++;//每进来一次就说明定时时间为256us;      
  172. }
  173. void init0() interrupt 0
  174. {
  175.         if(startflag)
  176.         {
  177.                 if(irtime>32)//检测引导码,求法是用引导码时间除以一次计数时间,看看要多少次
  178.                 {
  179.                         bitnum=0;      
  180.                 }
  181.                 irdata[bitnum]=irtime;
  182.                 irtime=0;
  183.                 bitnum++;
  184.                 if(bitnum==33)
  185.                 {
  186.                         bitnum=0;
  187.                         irreceok=1;//一帧红外数据接收完成标志
  188.                 }
  189.         }
  190.         else
  191.         {
  192.                 startflag=1;//将开始标志位置1,等到下次进入中断即可进入if语句
  193.                 irtime=0;//将开始之前的计数器时间清零。等到下次进入中断的时候才是引导码真正的时间
  194.         }
  195. }
复制代码
完整源码 电机远程控制--红外遥控控制.zip (26.1 KB, 售价: 2 工控币)
回复

使用道具 举报

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

本版积分规则