找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机红外遥控器解码实验 C语言和汇编2个版本的程序都有

[复制链接]
跳转到指定楼层
楼主
注:
每个EXP实验的文件夹下文件夹分别是P_ASM、P_EMULATOR_C,P_PROTEUS_C,P_EMULATOR_ASM。
P_PROTEUS_ASM        为PROTEUS汇编实例工程
P_PROTEUS_C        为PROTEUS C51仿真实例工程
P_EMULATOR_C        为硬件仿真器(可选配件)C51实例工程
P_EMULATOR_ASM        为硬件仿真器汇编实例工程
一般情况下P_PROTEUS_ASM,P_PROTEUS_C和P_EMULATOR_C和P_EMULATOR_ASM都支持ISP下载脱机运行

P_ISP_C,P_ISP_ASM为ISP下载脱机运行实例。比如看门狗实验,仿真器不支持,因为复位信号被仿真器接管,所以就只能做硬件脱机实验,通过ISP下载程序。

如果文件夹带有(缺省)说明暂时没有提供此程序,可根据需要再添加。
汇编和c的代码都有很全面.

c语言程序:
  1. /*************************************************  
  2. *文件名称: main.c
  3. *作 者:   
  4. *版 本:    V1.00
  5. *说 明:    红外遥控器解码实验
  6. *修改记录:  
  7. --------------------------------------------------
  8. *Descriptoon:
  9. *接线说明:P32-红外接收,P25-RS,P26-RW,P27-EN,
  10.            P00~P07-DB0~DB7                 
  11. **************************************************/                        

  12. #include <reg52.h>

  13. #define uchar unsigned char
  14. #define uint unsigned int
  15. //char code SST516[3] _at_ 0x003b;
  16. #define c(x)(x*110592/120000) //晶振11.0592

  17. uchar Lcd_Buf[4];             //显示数据缓冲区         
  18. unsigned char Ir_Buf[4];      //用于保存解码结果
  19. sbit Ir_Pin=P3^2;             //红外线数据接口
  20. sbit rs=P2^0;                     //LCD数据命令端
  21. sbit rw=P2^1;                          //读写接口
  22. sbit lcde=P2^2;                          //使能接口
  23. uchar code table[]=" WWW#WINDWAY$CN ";//LCD显示数据
  24. uchar code table1[]="Wait for IR in..";
  25. uchar code table2[]="  IR DATA...";
  26.                   
  27.            unsigned char code Led_Tab[]={
  28.         0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xf8,
  29.         0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};   //共阳极数码显示码0-F
  30. unsigned char code Led_Sel[]={0xf,0xf,0xb,0x7}; //数码管位选,屏蔽前两位
  31. unsigned char Led_Buf[4]; //显示缓冲区
  32. char Led_Index;           //定义位选         
  33. unsigned char Ir_Buf[4];  //用于保存解码结果

  34. sbit LCD_E = P2^7;
  35. //========1MS延时====================================
  36. void delay(uint z)
  37. {
  38.         uint x,y;
  39.         for(x=z;x>0;x--)
  40.                 for(y=113;y>0;y--);
  41. }
  42. //======LCD写命令=====
  43. void write_com(uchar com)
  44. {
  45.         rs=0;
  46.         lcde=0;
  47.         P0=com;
  48.         lcde=1;
  49.         delay(1);//延时1MS跳过忙信号
  50.         lcde=0;
  51.         delay(1);
  52. }
  53. //======LCD写数据=====================================
  54. void write_date(uchar date)
  55. {
  56.         rs=1;
  57.         lcde=0;
  58.         P0=date;
  59.         lcde=1;
  60.         delay(1);
  61.         lcde=0;
  62.         delay(1);
  63. }
  64. //=====初始化函数=====================================
  65. void init()
  66. {        
  67.         uchar num;
  68.         rw=0;                //允许LCD写
  69.         lcde=0;
  70.         write_com(0x38);//显示模式设置                                                         
  71.         write_com(0x0c);//显示开及光标设置
  72.         write_com(0x06);//显示光标移动设置
  73.         write_com(0x01);//清屏
  74.         write_com(0x80);//显示首地址
  75.         for(num=0;num<15;num++)//显示第一行
  76.         {
  77.                 write_date(table[num]);
  78.                 delay(1);
  79.         }
  80.         write_com(0x80+0x40);//显示第二行
  81.         for(num=0;num<16;num++)
  82.         {
  83.                 write_date(table1[num]);
  84.                 delay(1);
  85.         }
  86.         TMOD=0x10;                //设置定时器0、1工作模式为1
  87. }
  88. //=====显示解码========================================
  89. void write_ir(uchar date)
  90. {
  91.         uchar tmp, num,ff;         

  92.         if(ff==0)
  93.         {
  94.                 ff++;
  95.                 write_com(0x01);
  96.                 write_com(0x80);
  97.                 for(num=0;num<12;num++)
  98.                 {
  99.                         write_date(table2[num]);
  100.                         delay(1);
  101.                 }                 
  102.         }
  103.         
  104.         write_com(0xC0+6);//定位在第二行第六位
  105.         tmp = date>>4;                        // 高四位         
  106.         write_date(tmp > 9 ? 'A'+tmp-10 : '0'+tmp);
  107.         write_com(0xC0+7);//定位第二行第七位           
  108.         tmp = date&0x0F;                        // 低四位
  109.         write_date(tmp > 9 ? 'A'+tmp-10 : '0'+tmp);         

  110. }
  111. //======================================================
  112. //解码取回低电平
  113. unsigned int Ir_Get_Low()
  114. {
  115.         TL1=0;
  116.         TH1=0;
  117.         TR1=1;
  118.         while(!Ir_Pin && (TH1&0x80)==0);   //等待低电平到来              
  119.         TR1=0;           
  120.         return TH1*256+TL1;//提取低电平时间间隔时长
  121. }
  122. //======================================================
  123. //解码取回高电平========================================
  124. unsigned int Ir_Get_High()
  125. {
  126.         TL1=0;
  127.         TH1=0;
  128.         TR1=1;
  129.         while(Ir_Pin && (TH1&0x80)==0);//等待高电平到来
  130.         TR1=0;
  131.         return TH1*256+TL1;//提取高电平时间间隔时长
  132. }
  133. //======================================================
  134. //======================================================

  135. void main()
  136. {
  137.         unsigned int temp;
  138.         char i,j;
  139.         init();        //初始化
  140. //=====用do做循环,等待遥控按键=========================
  141.         do{
  142. restart:
  143.                 while(Ir_Pin) ;//等待低电平

  144.                 temp=Ir_Get_Low();//把低电平附给变量
  145.                 if(temp<c(8500) || temp>c(9500)) continue;//引导脉冲低电平等待9000us
  146.                 temp=Ir_Get_High();//把高电平附给变量
  147.                 if(temp<c(4000) || temp>c(5000)) continue;//引导脉冲高电平等待4500us
  148.                 //连续读出32个字节
  149.                 for(i=0;i<4;i++) //4个字节
  150.                 {
  151.                         for(j=0;j<8;j++) //每个字节8位
  152.                         {
  153.                                 temp=Ir_Get_Low();
  154.                                 if(temp<c(200) || temp>c(800)) goto restart;//等待560us跳过低电平
  155.                                 temp=Ir_Get_High();
  156.                                 if(temp<c(200) || temp>c(2000)) goto restart;//等待1000us跳过高电平
  157.                                 Ir_Buf[i]>>=1;//把电平移进数组


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

汇编语言:


  1. ;-----------------------------------------------
  2.        IRCOM  EQU  20H       ;20H-23H IR使用
  3.         X     EQU  26H       ;LCD 地址变量

  4.        IRIN   EQU  P3.2
  5. ;       BEEP   EQU  P3.7
  6. ;       RELAY  EQU  P1.0
  7.       
  8.         RS    EQU  P2.0
  9.         RW    EQU  P2.1
  10.         EN    EQU  P2.2
  11. ;------------------------------------------------
  12.          ORG 0000H
  13.          JMP  MAIN
  14. ;------------------------------------------------
  15.           ORG 0100H
  16. MAIN:
  17.           MOV   SP,#40H
  18.           MOV   A,#00H
  19.           MOV   R0,#20H
  20. LOOP0:    MOV   @R0,A          ;20H-26H清零
  21.           INC   R0
  22.           CJNE  R0,#27H,LOOP0
  23.           SETB  IRIN
  24.           CALL  SET_LCD
  25.           CALL  MENU1
  26. LOOP1:
  27.           CALL  IR_IN
  28.           CALL  IR_SHOW

  29. ;          MOV  A,22H
  30. ;          CJNE  A,#40H,LOOP2    ;K17键按下
  31. ;          CLR   RELAY           ;继电器吸合
  32. ;LOOP2:    CJNE  A,#04H,LOOP3    ;K19键按下
  33. ;          SETB  RELAY           ;继电器关闭
  34. ;LOOP3:   
  35.            JMP   LOOP1
  36.          
  37. ;-----------------------------------------------------
  38. ;  LCD 初始化设置
  39. ;-----------------------------------------------------
  40. SET_LCD:
  41.           CLR  EN
  42.           CALL  INIT_LCD     ;初始化 LCD
  43.           CALL  DELAY1
  44.           MOV  DPTR,#INFO1   ;指针指到显示信息1
  45.           MOV  A,#1          ;显示在第一行
  46.           CALL  LCD_SHOW
  47.           MOV  DPTR,#INFO2   ;指针指到显示信息2
  48.           MOV  A,#2          ;显示在第二行
  49.           CALL  LCD_SHOW
  50.           RET
  51. ;-----------------------------------------------------
  52. INIT_LCD:                 ;8位I/O控制 LCD 接口初始化
  53.           MOV  A,#38H     ;双列显示,字形5*7点阵
  54.           CALL  WCOM
  55.           CALL  DELAY1
  56.           MOV  A,#38H     ;双列显示,字形5*7点阵
  57.           CALL  WCOM
  58.           CALL  DELAY1
  59.           MOV  A,#38H     ;双列显示,字形5*7点阵
  60.           CALL  WCOM
  61.           CALL  DELAY1
  62.           MOV  A,#0CH     ;开显示,关光标,
  63.           CALL  WCOM
  64.           CALL  DELAY1
  65.           MOV  A,#01H     ;清除 LCD 显示屏
  66.           CALL  WCOM
  67.           CALL  DELAY1
  68.           RET
  69. ;----------------------------------------------------
  70. LCD_SHOW:       ;在LCD的第一行或第二行显示信息字符

  71.           CJNE  A,#1,LINE2  ;判断是否为第一行
  72.   LINE1:  MOV  A,#80H       ;设置 LCD 的第一行地址
  73.           CALL  WCOM        ;写入命令
  74.           CALL  CLR_LINE    ;清除该行字符数据
  75.           MOV  A,#80H       ;设置 LCD 的第一行地址
  76.           CALL  WCOM        ;写入命令
  77.           JMP  FILL

  78.   LINE2:  MOV  A,#0C0H      ;设置 LCD 的第二行地址
  79.           CALL  WCOM        ;写入命令
  80.           CALL  CLR_LINE    ;清除该行字符数据
  81.           MOV  A,#0C0H      ;设置 LCD 的第二行地址
  82.           CALL  WCOM
  83.   FILL:   CLR  A            ;填入字符
  84.           MOVC  A,@A+DPTR   ;由消息区取出字符
  85.           CJNE  A,#0,LC1    ;判断是否为结束码
  86.           RET
  87.   LC1:    CALL  WDATA       ;写入数据
  88.           INC  DPTR         ;指针加1
  89.           JMP  FILL         ;继续填入字符
  90.           RET
  91. ;---------------------------------------------------
  92. CLR_LINE:                  ;清除该行 LCD 的字符
  93.           MOV  R0,#24
  94.    CL1:   MOV  A,#' '
  95.           CALL  WDATA
  96.           DJNZ  R0,CL1
  97.           RET
  98. ;----------------------------------------------------
  99. MENU1:                      ;LCD 显示工作菜单信息
  100.          MOV   DPTR,#MENU2
  101.          MOV   A,#1         ;在第一行显示信息
  102.          CALL  LCD_SHOW
  103.          RET
  104. MENU2:  DB  " REMOTE CONTROL ",0
  105. ;-----------------------------------------------------
  106. INFO1:  DB  "                ",0  ;LCD 第一行显示信息
  107. INFO2:  DB  "  IR-CODE: --H  ",0  ;LCD 第二行显示信息
  108. ;-----------------------------------------------------

  109. ;-----------------------------------------------------
  110. ; 写指令、数据使能子程序
  111. ;-----------------------------------------------------
  112. WCOM:
  113.           MOV  P0,A        ;写指令使能
  114.           CLR RS           ;RS=L,RW=L,D0-D7=指令码,E=高脉冲
  115.           CLR RW
  116.           SETB EN
  117.           CALL  DELAY0
  118.           CLR EN
  119.           RET
  120.                   
  121. WDATA:
  122.           MOV   P0,A      ;写数据使能
  123.           SETB  RS        ;RS=H,RW=L,D0-D7=数据,E=高脉冲
  124.           CLR   RW
  125.           SETB  EN
  126.           CALL  DELAY0
  127.           CLR   EN
  128.           RET

  129. DELAY0:   MOV  R7,#250      ;延时500微秒
  130.           DJNZ  R7,$
  131.           RET
  132. ;---------------------------------------------------
  133. ;在 LCD 第二行显示字符
  134. ;A=ASC DATA, B=LINE X POS
  135. ;---------------------------------------------------
  136. LCDP2:                    ;在LCD的第二行显示字符
  137.          PUSH  ACC        ;
  138.          MOV  A,B         ;设置显示地址
  139.          ADD  A,#0C0H     ;设置LCD的第二行地址
  140.          CALL  WCOM       ;写入命令
  141.          POP  ACC         ;由堆栈取出A
  142.          CALL  WDATA      ;写入数据
  143.          RET
  144. ;---------------------------------------------------
  145. ; IR 译码子程序
  146. ;---------------------------------------------------
  147. IR_IN:              
  148.           MOV   R0,#IRCOM
  149. I1:      JNB  IRIN,I2       ;等待 IR 信号出现
  150.           JMP  I1
  151. I2:      MOV  R4,#20
  152. I20:     CALL  DEL
  153.           DJNZ  R4,I20
  154.           JB  IRIN,I1        ;确认IR信号出现
  155. I21:     JB  IRIN,I3        ;等 IR 变为高电平
  156.           CALL  DEL
  157.           JMP  I21
  158. I3:      MOV  R3,#0         ;8位数清为0
  159. LL:      JNB  IRIN,I4       ;等 IR 变为低电平
  160.           CALL  DEL
  161.           JMP  LL
  162. I4:      JB  IRIN,I5        ;等 IR 变为高电平
  163.           CALL  DEL
  164.           JMP  I4
  165. I5:      MOV  R2,#0         ;0.14ms 计数
  166. L1:      CALL  DEL
  167.           JB  IRIN, N1       ;等 IR 变为高电平
  168.                              ;IR=0,检查R2中的计数值
  169.           MOV  A,#8
  170.           CLR  C
  171.           SUBB  A,R2         ;判断高低位
  172.                              ;IF C=0  BIT=0
  173.           MOV  A,@R0
  174.           RRC  A
  175.           MOV  @R0,A         ;处理完一位
  176.           INC  R3
  177.           CJNE  R3,#8,LL     ;需处理完8位  
  178.           MOV  R3,#0
  179.           INC  R0
  180.           CJNE  R0,#24H,LL   ;收集到4字节了
  181.           JMP  OK
  182. N1:      INC  R2
  183.           CJNE  R2,#30,L1    ;0.14ms 计数过长则时间到自动离开
  184. OK:      RET
  185. ;--------------------------------------------------------------------
  186. IR_SHOW:
  187.           MOV A,22H
  188.           CPL A                ;将22H取反后和23H比较
  189.           CJNE A,23H,IR_SHOW1  ;如果不等表示接收数据发生错误,放弃。
  190.           CALL   CONV
  191. ;          CALL  BEEP_BL        ;蜂鸣器鸣响表示解码成功
  192. IR_SHOW1: RET
  193. ;--------------------------------------------------------------------
  194. ;转换为 ASCII 码并显示
  195. ;--------------------------------------------------------------------
  196. CONV:
  197.           MOV   X,#11        ;设置显示起始位置
  198.           MOV   A,22H
  199.           ANL   A,#0F0H      ;取出高四位二进制数
  200.           SWAP  A            ;高四位与低四位互换
  201.           PUSH  ACC          ;压入堆栈
  202.           CLR   C            ;C=0
  203.           SUBB  A,#0AH       ;减10
  204.           POP   ACC          ;弹出堆栈
  205.           JC    ASCII0       ;该数小于10,转ASCII0
  206.           ADD   A,#07H       ;大于10的数加上37H
  207. ASCII0:   ADD   A,#30H       ;小于10的数加上30H
  208.           MOV   B,X
  209.           CALL  LCDP2

  210.           MOV   A,22H
  211.           ANL   A,#0FH        ;取出低四位二进制数
  212.           PUSH  ACC
  213.           CLR   C
  214.           SUBB  A,#0AH        ;减10
  215.           POP   ACC
  216.           JC    ASCII1        ;该数小于10,转ASCII0
  217.           ADD   A,#07H        ;大于10的数加上37H
  218. ASCII1:   ADD   A,#30H        ;小于10的数加上30H
  219.           INC   X
  220.           MOV   B,X
  221.           CALL  LCDP2
  222.           RET
  223. ;--------------------------------------------------------
  224. ;蜂鸣器响一声子程序
  225. ;--------------------------------------------------------
  226. BEEP_BL:
  227.          MOV  R6,#100
  228.   BL1:   CALL  DEX1
  229. ;         CPL  BEEP
  230.          DJNZ  R6,BL1
  231.          MOV  R5,#25
  232.          CALL  DELAY
  233.          RET
  234. DEX1:   MOV  R7,#180
  235. DEX2:   NOP
  236.          DJNZ  R7,DEX2
  237.          RET
  238. DELAY:                    ;延时R5×10MS
  239.          MOV  R6,#50
  240.   D1:    MOV  R7,#100
  241.          DJNZ  R7,$
  242.          DJNZ  R6,D1
  243.          DJNZ  R5,DELAY


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

下载:
EXP19_红外遥控器解码实验.zip (70.27 KB, 下载次数: 53)

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

使用道具 举报

沙发
ID:436643 发表于 2018-11-30 16:34 | 只看该作者
新手看看程序
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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