51单片机红外遥控解码器设计(汇编语言)

发布者:Meilin8888最新更新时间:2020-12-05 来源: 51hei关键字:51单片机  红外遥控  解码器  汇编语言 手机看文章 扫描二维码
随时随地手机看文章

你家里是否有一个电视机遥控器或者空调机遥控器呢?你是否也想让它遥控其他的电器甚至让它遥控您的电脑呢?那好,跟我一起做这个“红外遥控解码器”。


该小制作所需要的元件很少:单片机TA89C2051一只,RS232接口电平与TTL电平转换心片MAX232CPE一只,红外接收管一只,晶振11.0592MHz,电解电容10uF4只,10uF一只,电阻1K1个,300欧姆左右1个,瓷片电容30P2个。发光二极管8个。价钱不足20元。


电路原理介绍:

主控制单元是单片机AT89C2051,中断口INT0跟红外接受管U1相连,接收红外信号的脉冲,8个发光二极管作为显示解码输出(也可以用来扩展接其他控制电路),U3是跟电脑串行口RS232相连时的电平转换心片,9、10脚分别与单片机的1、2脚相连,(1脚为串行接收,2脚为串行发送),MAX232CPE的7、8脚分别接电脑串行口的2(接收)脚、3(发送脚)。晶振采用11.0592MHz,这样才能使得通讯的波特率达到9600b/s,电脑一般默认值是9600b/s、8位数据位、1位停止位、无校验位。电路就这么简单了,现在分析具体的编程过程吧。


如图所示,panasonic遥控器的波形是这样的(经过反复测试的结果)。

开始位是以3.6ms低电平然后是3.6ms高电平,然后数据表示形式是0.9ms低电平0.9ms高电平周期为1.8ms表示“0”, 0.9ms低电平 2.4ms高电平周期为3.3ms表示“1”,编写程序时,以大于3.4ms小于3.8ms高电平为起始位,以大于2.2ms小于2.7ms高电平表示“1”,大于0.84ms小于1.11ms高电平表示“0”。因此,我们主要用单片机测量高电平的长短来确定是“1”还是“0”即可。定时器0的工作方式设置为方式1:mov tmod,#09h,这样设置定时器0即是把GATE置1,16位计数器,最大计数值为2的16次方个机器周期,此方式由外中断INT0控制,即INT0为高时才允许计数器计数。比如:

jnb p3.2,$

jb p3.2,$

clr tr0

这3条指令就可以测量一个高电平,接下来读取计数值TH0,TL0就可以分辨是起始位还是“1”或“0”。在确定码表之前,您可以使用P0口的8个发光二极管来显示编码,16位编码分两次显示:

mov p0,keydata

acall delay_1s ;//1ms延时子程序

mov p0,keydata+1

ljmp main

根据P0相继的两次显示的编码,记录每个按键的编码,形成编码表,即遥控器编码的解码完毕。码表确定之后,以后接收到遥控器的编码之后,就与码表比较,找到匹配的码项,并把该码项对应的顺序号输出到P0口,同时也把顺序号向串行口输出到电脑,电脑接收该数据后由串口软件决定如何处理。


程序不长,下面是完整的程序和注释:

keydata equ 30h ;//该地址和31H地址用来存放遥控器按键编码。

org 00h

main:

    movkeydata,#0  ;// 清零

    mov tmod,#09h       ;//设置定时0方式1,GATE=1

        mov r7,#0      ;//计数器,用来计数是否满8位

    mov  r6,#0           ;//计数器,用来计数是否满2字节(解16位编码)

    jb p3.2,[        DISCUZ_CODE_2        ]nbsp;           ;//是否为低电平

again:                        ;//如果为低,继续往下面执行

    movtl0,#0           ;//清零TL0

    mov th0,#0         ;//清零TH0

    setb tr0       ;//开启定时器0

    jnbp3.2,[        DISCUZ_CODE_2        ]nbsp;          ;//等待高电平到来

    jb p3.2,[        DISCUZ_CODE_2        ]nbsp;    ;//高电平到来,此时开始计数

    clr tr0 ;//高电平结束,停止计数

    mov a,th0     ;//读取th0 值,TL0忽略不计     

    clr c             ;//

    subba,#12    ;//

    jc again ;//th0<12则转,即小于3.4ms,你可以算一下这个时间

    mov a,#14     ;//

    clr c             ;//

    subba,th0    ;//和14比较,如果TH0>14则大于3.8ms

        jcagain      ;//大于3.8ms,从新再检测

nextbit:       ;//起始位找到了,然后下一位

    movtl0,#0    ;//

    movth0,#0    ;//

    setb tr0 ;//启动定时器

    jnbp3.2,[        DISCUZ_CODE_2        ]nbsp;   ;//等待高电平

    jb p3.2,[        DISCUZ_CODE_2        ]nbsp;   ;//高电平到来,此时开始计数

    clr tr0  ;//高电平结束,停止计数

    mov a,th0     ;//读取计数值,TL0忽略不计

    clr c             ;//

    subb a,#8     ;//th0和8比较

    jcnext  ;;;;//若 <2.2ms则转,再判断是否大于0.84ms

    mov a,#10     ;//再跟10比较

    clr c             ;//

    subba,th0    ;//

    jc again;;;;;;;//若 >2.7ms,则放弃,从新检测

    mova,keydata      ;//符合大于2.2ms 小于2.7ms,即为“1”

    setbc        ;//C = 1

    rrc a             ;//把1移位进A

    movkeydata,a      ;//保存

    inc r7           ;//计数器加1

    cjner7,#8,nextbit    ;//是否满8位

    inc r6                  ;//计数加1

    cjner6,#2,last8 ;//是否满两字节

    sjmpseach           ;//不满两字节,再新采集

last8:                        ;//满1字节,再接下来第二字节

    movkeydata+1,a  ;//把第一字节编码数据保存到31h里

    mov r7,#0            ;//计数器R7清零

    sjmpnextbit        ;//继续采集数据

next:                  ;//小于2.2ms时转到这里

    mov a,th0            ;//读取计数值TH0

    swap a                  ;//高4位与低4位对换

    mov r1,a       ;//保存到R1

    anltl0,#0f0h             ;//取TL0高4位,低4位忽略不计

    mov a,tl0            ;//

    clr c                    ;//

    rrc a             ;//

    rrc a             ;//

    rrc a             ;//

    rrc a             ;//

    add a,r1 ;//

    mov r1,a ;//

    subba,#30    ;//以上几行是把TH0的低4位和TL0的高4位合并为1字节作为计数值

    jc nextbit; //判断是否 <0.84ms,是则放弃,继续采集

    mov a,r1 ;//否

    clr c             ;//

    cjnea,#64,continue   ;//跟64比较

continue:            ;//

    jncnextbit ;  //a>64表示采样值>1.11ms  放弃

    mova,keydata  ;//否则 ,符合位“0”

    clrc          ;//C  = 0

    rrc a                    ;//把零右移进A

    movkeydata,a             ;//保存

    inc r7                  ;//计数器加1

    cjner7,#8,nextbit    ;//是否满8位

    inc r6                  ;//计数器加1

    cjner6,#2,last_8      ;//是第一字节已经满

    sjmpseach           ;//

last_8:                ;//如果为第二字节

    movkeydata+1,a  ;//则保存第一字节到31h

    mov r7,#0            ;//清零R7

    sjmpnextbit       ;//

seach:                       ;//匹配按键编码

    movr0,#-2  ;//按键编码字节个数计数器

    movr1,#-1  ;//按键顺序计数器

seach1:                ;//

        incr0           ;//

seach2:               ;//

       incr0                  ;//

    inc r1                  ;//

    cjner1,#29,compare   ;//是否R1=29

    sjmpexit0           ;//

compare:              ;//开始匹配

    mov a,r0       ;//

    movdptr,#keycode      ;//地址指针指向码表首址

    movca,@a+dptr    ;//取码

    cjnea,keydata,seach1      ;//比较

    inc r0                  ;//R0+1,再比较下一字节(每个按键编码为2字节)

    mov a,r0       ;//

    ;mov dptr,#keycode   ;//

    movca,@a+dptr    ;//比较

    cjnea,keydata+1,seach2   ;//是否匹配,不匹配则继续跟下一字节比较

    movp1,r1         ;//如果匹配,把按键顺序号输出到p1

send:                        ;//

    movtmod,#20h     ;   //设置timer 1,mode 2

    movtl1,#0fdh             ;//设置定时器初值

    movth1,#0fdh             ;//

    movscon,#01010000b;//以上设置,即设置串口波特率系数为:9600,8,1,0

    setb tr1       ;//启动定时器1

loop_s:         ;//

    movsbuf,r1    ;//把R1(按键顺序号)输出到串口

    jnb ti,[        DISCUZ_CODE_2        ]nbsp;      ;//等待是否发送完毕

    clr ti                  ;//发送完毕,清零TI

exit0:                       ;//

ljmp main                   ;//循环

keycode:              ;//每两字节代表一个按键的编码

db 11111000b,00000000b,    11111100b,00000000b,    11111001b,11000000b

db 11111100b,11000000b,    11111010b,00000000b,    11111010b,00100000b

db 11111010b,01000000b,    11111010b,01100000b,    11111010b,10000000b

db 11111010b,10100000b,    11111010b,11000000b,    11111010b,11100000b

db 11111011b,00000000b,    11111011b,00100000b,    11111011b,01000000b

db 11111011b,01100000b,    11111111b,01100000b,    11111111b,10100000b

db 10001100b,10001110b,    10001101b,11101110b,    10001100b,10101110b

db 10001101b,11001110b,    11111000b,11100000b,    11111100b,10000000b

db 11111100b,01000000b,    11111001b,10100000b,    11111100b,10100000b

db 11111100b,01100000b

end


关键字:51单片机  红外遥控  解码器  汇编语言 引用地址:51单片机红外遥控解码器设计(汇编语言)

上一篇:STC12C5A60S2串口二通信ESP8266-01S模块控制LED闪烁
下一篇:STC15W4K60S2单片机2路SPWM源程序 可驱动电机

推荐阅读最新更新时间:2024-11-05 19:45

51单片机绝对地址访问的两种方法
在进行8051单片机应用系统程序设计时,编程都往往少不了要直接操作系统的各个存储器地址空间。C51程序经过编译之后产生的目标代码具有浮动地址,其绝对地址必须经过BL51连接定位后才能确定。为了能够在C51程序中直接对任意指定的存储器地址进行操作,可以采用扩展关键字 at 、指针、预定义以及连接定位控制命令。 在这些方法中,本人认为最简单而有效的方法是用 _at_ 关键字来对指定变量存储器空间绝对地址来指定。一般格式如下: 数据类型标识符 _at_ 地址常数 其中: 存储器类型 为idata、data、xdata等C51能够识别的所有
[单片机]
C语言中嵌入汇编语言在本论坛中的集锦
论坛中的一些个人看法,我收集了一下,对错的话,大家见仁见智啊 下面是一个简单的例子,具体参数传递等,看书 $NOMOD51 ACC DATA 0E0H P_VM EQU 0DFE2H P_PAGE EQU 0DFE0H NAME VM ?C_VM?VM SEGMENT CODE PUBLIC C_VM MOV ACC,#00H PUSH ACC PUSH ACC MOV DPTR,#P_VM MOV A,#0CH MOVX @DPTR,A NOP RET END 看了KEIL-C的手册,介绍可以这样加入汇编 #pragma asm; nop; nop; #
[单片机]
51单片机--键盘识别
单片机的键盘由于介入了人为操作,并不都是机器按流程跑,所以必须考虑到人的操作时长远大于机器周期,所以对于键盘状态的检测必须是写在while中,进行循环检测,这些需要实时检测的状态是:从没有按下到按下,和从已经按下到松手。而为了可以使while中的循环可以跳出,进入while的判断语句中的变量要在while循环中再次赋值,而这个赋值必须是与新状态相关的。 P3=0xfe; temp=P3; temp=temp&0xf0; while(temp!=0xf0) { delay(5); temp=P3; temp=temp&0xf0; while(temp!=0xf0) { tem
[单片机]
51单片机在智能压力传感器设计中的应用
在现代科技领域中,传感器技术的地位越来越重要。本文主要论述了51单片机在智能压力传感器设计中的应用,以及对其发展的影响。研究的重点是智能压力传感器本身的稳定性,结合51单片机和压力传感器,对压力感器本身抗干扰能力有了改善的作用,也对压力传感器的智能化和标准化有了促进作用。   引言   对目前所有兼容lntel 8031指令系统的单片机,统l称为51单片机。控制系统传统的设计思想和设计方法,因51单片机的应用从根本上得到了改变。现在正在用单片机通过软件的方法,来实现采用硬件电路实现的大部分控制功能,智能化的数字计算控制、模糊控制和自适应控制可通过单片机来实现,从而改变自动控制中的PID调节。压力传感器,英文名称是press
[工业控制]
<font color='red'>51单片机</font>在智能压力传感器设计中的应用
51单片机ADC0832电压测量液晶1602显示的C程序与proteus仿真
很早对AD转换感兴趣,也想自己业余做块单片机开发板,让广大的电子设计爱好者学习使用单片机。 今天通过搜索,整理了proteus 7可以仿真通过的基于51单片机+ADC0832电压采集并通过液晶1602显示电压的C程序及电路连接图,希望对大家有所帮助。 程序是谁写的谁修改的并不主要,主要的是学会并使用单片机AD转换,这才是王道。 电路连接图如下: C程序如下: #include reg52.h #include intrins.h #include math.h /**********************************8/ /**********LCD1602接口程序*********
[单片机]
<font color='red'>51单片机</font>ADC0832电压测量液晶1602显示的C程序与proteus仿真
C51单片机————总线与系统扩展
1.引文 前面说过单片机的特点是体积小,功能全,系统结构紧凑、对于小型的需求可以满足要求。那么稍大一点嵌入式系统呢?那么有可能你的数据存储器、程序存储器还有IO口都可能不够用!那怎么办呢?我们就需要进行系统扩展了。 基本知识与回顾 我们都知道的是CPU大都通过三总线(数据、地址、控制)与外界进行信息交换的。 - 数据总线:传输指令码和数据,外围的芯片都需要它来进行信息交流。 - 地址总线:传输的是地址信息(数据传到哪儿的信息) 2.扩展 单片机系统总线信号 P0口是地址(A0~A7) / 数据复用线(D0~D7),经锁存器提供低8位地址,锁存信号是由CPU的ALE引脚提供的; P2口提供高8位地址 A8 ~ A15。 控
[单片机]
C<font color='red'>51单片机</font>————总线与系统扩展
51单片机基于一个定时器实现多个软件定时器
软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。但由于软件定时器是通过程序实现的,其运行和维护都需要耗费一定的CPU资源,同时精度也相对硬件定时器要差一些。在RTOS等操作系统中,都带有软件定时器,原理大同小异。典型的实现方法是:通过一个硬件定时器产生固定的时钟节拍,每次硬件定时器中断到,就对一个全局的时间标记加一,每个软件定时器都保存着到期时间,程序需要定期扫描所有运行中的软件定时器,将各个到期时间与全局时钟标记做比较,以判断对应软件定时器是否到期,到期则执行相应的回调函数,并关闭该定时器
[单片机]
<font color='red'>51单片机</font>基于一个定时器实现多个软件定时器
LSI 面向STARPRO 媒体处理器推出编解码器
日前, LSI 公司宣布推出系列语音、音频与视频编解码器,可支持实时多媒体通信编码与解码的软件程序。编解码器与处理器的完美结合为在 LSI™ StarPro ™ 系列媒体处理器上运行进行了精心优化,能够实现高密度低功耗的转码功能,满足新一代无线、有线以及企业应用的需求。此外,上述系列还支持音、视频编解码器,能够充分满足要求 MPEG-4 、 H.264 、 H.263 、 Microsoft RT 音频、 iLBC 、 iSAC 以及 AAC-LC/LD 等标准的新兴网络与企业应用领域。 Forward Concepts 首席分析师 Will Strauss 指出: “ 市场需要网络带宽占用更少、功耗
[模拟电子]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved