找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机如何实现红外输入数字

[复制链接]
跳转到指定楼层
楼主
我有一个想法,用51单片机做个密码锁,用红外来开锁,,,
奈何写不出解码红外后的数组判断,,,,求大神赐教
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:82765 发表于 2017-9-12 19:23 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

板凳
ID:229064 发表于 2017-9-12 20:00 | 只看该作者
你的意思是,让单片机,检测到红外之后,自己开锁吗?
回复

使用道具 举报

地板
ID:228987 发表于 2017-9-12 20:36 | 只看该作者
AAAAAA666666 发表于 2017-9-12 20:00
你的意思是,让单片机,检测到红外之后,自己开锁吗?

他的意思应该是门自己锁,然后用红外密码解锁
回复

使用道具 举报

5#
ID:60379 发表于 2017-9-12 21:00 | 只看该作者
《51单片机轻松入门 基于STC15W4K系列》有配套例程可以直接使用,占用一个定时器,使用任意一个IO口即可接收遥控器的发出的各个字节,按遥控器不同按键,会接收到不同的字节,接收到的字节自动发送到计算机串口助手显示,程序代码只需根据自己的硬件连接更改红外接收引脚定义,其余代码无需修改。
完整工程见附件 4—只用一个定时器的红外接收程序.rar (24.12 KB, 下载次数: 11)

  1. /****************《51单片机轻松入门-基于STC15W4K系列》配套例程 *************
  2. ★★★★★★★★★★★★★★★★★★★★★★★★
  3. 《51单片机轻松入门-基于STC15W4K系列》 一书已经由北航出版社正式出版发行。
  4.   作者亲手创作的与教材配套的51双核实验板(2个MCU)对程序下载、调试、仿真方便,不需要外部
  5.   仿真器与编程器,这种设计方式彻底解决了系统中多个最高优先级谁也不能让谁的中断竞争问题。
  6.   淘宝店地址:shop117387413点taobao点com
  7.   QQ群:STC51-STM32(3) :515624099 或 STC51-STM32(2):99794374。
  8.         验证信息:STC15单片机
  9.   邮箱:xgliyouquan@126.com
  10.   ★★★★★★★★★★★★★★★★★★★★★★★★*/

  11. ///*************        功能说明        **************      
  12. //红外接收程序。适用于市场上用量最大的HT6121/6122及其兼容IC的编码。
  13. //当遥控器用户码与程序定义的用户码不同时,程序会将遥控器的用户码一起从串口输出。
  14. //使用模拟串口发送用户码与键码,波特率9600,接收端要求使用字符格式显示。      
  15. /******************************************/      
  16. #include        "STC15W4K.H"
  17. #define MAIN_Fosc                22.1184        // 定义主时钟, 红外接收会自动适应,5~36MHZ,但模拟串口输出部分不能自动适应。

  18. #define        User_code                0xFD02                // 定义红外接收用户码  
  19. sbit        Ir_Pin = P3^6;                        // 定义红外接收输入端口
  20. sbit        TXD1 = P3^1;                          // 定义模拟串口发送脚
  21. /*************        用户系统配置        **************/
  22. #define TIME                125                              // 选择定时器时间125us, 红外接收要求在60us~250us之间
  23. /*************        以下宏定义用户请勿修改        **************/
  24. #define Timer0_Reload (unsigned int)(65536 - (TIME * MAIN_Fosc /12.0))  // 定时器初值
  25.                                  
  26. /*************        本地变量声明        **************/
  27. unsigned char        IR_SampleCnt;                // 采样次数计数器,通用定时器对红外口检测次数累加记录
  28. unsigned char        IR_BitCnt;                        // 记录位数
  29. unsigned char        IR_UserH;                        // 用户码(地址)高字节
  30. unsigned char        IR_UserL;                        // 用户码(地址)低字节
  31. unsigned char        IR_data;                        // 键原码
  32. unsigned char        IR_DataShit;                // 键反码
  33. unsigned char        IR_code;                        // 红外键码               
  34. bit                Ir_Pin_temp;                        // 记录红外引脚电平的临时变量
  35. bit                IR_Sync;                                // 同步标志(1——已收到同步信号,0——没收到)
  36. bit                IrUserErr;                            // 用户码错误标志
  37. bit                IR_OK;                        // 完成一帧红外数据接收的标志(0,未收到,1,收到一帧完整数据)

  38. /******************** 红外采样时间宏定义, 用户不要随意修改        *******************/
  39. //数据格式: Synchro,AddressH,AddressL,data,/data, (total 32 bit).
  40. #if ((TIME <= 250) && (TIME >= 60))                        // TIME决定测量误差,TIME太大防错能力降低,TIME太小会干扰其它中断函数执行。
  41.         #define        IR_sample                        TIME                // 定义采样时间,在60us~250us之间,
  42. #endif

  43. #define IR_SYNC_MAX                (15000/IR_sample)        // 同步信号SYNC 最大时间 15ms(标准值9+4.5=13.5ms)
  44. #define IR_SYNC_MIN                (9700 /IR_sample)        // 同步信号SYNC 最小时间 9.5ms,(连发信号标准值9+2.25=11.25ms)
  45. #define IR_SYNC_DIVIDE        (12375/IR_sample)        // 区分13.5ms同步信号与11.25ms连发信号,11.25+(13.5-11.25)/2=12.375ms
  46. #define IR_DATA_MAX                (3000 /IR_sample)        // 数据最大时间3ms    (标准值2.25 ms)
  47. #define IR_DATA_MIN                (600  /IR_sample)        // 数据最小时,0.6ms   (标准值1.12 ms)
  48. #define IR_DATA_DIVIDE        (1687 /IR_sample)        // 区分数据 0与1,1.12+ (2.25-1.12)/2 =1.685ms
  49. #define IR_BIT_NUMBER                32                                // 32位数据

  50. //****************************  红外接收模块  ********************************************
  51. // 信号第1个下降沿时刻清零计数器并让计数器从0开始计数,第2个下降沿时刻计算计数器运行时间
  52. // 因此检测的是每个信号从低电平开始到高电平结束这段时间,也就是脉冲周期。
  53. void IR_RX_HT6121(void)
  54. {
  55.         unsigned char        SampleTime;                                // 信号周期
  56.         IR_SampleCnt++;                                                        // 定时器对红外口检测次数

  57.         F0 = Ir_Pin_temp;                                                // 保存前一次此程序扫描到的红外端口电平         
  58.         Ir_Pin_temp = Ir_Pin;                                        // 读取当前红外接收输入端口电平
  59.         if(F0 && !Ir_Pin_temp)                                        // 前一次采样高电平并且当前采样低电平,说明出现了下降沿
  60.         {
  61.                 SampleTime = IR_SampleCnt;                        // 脉冲周期
  62.                 IR_SampleCnt = 0;                                        // 出现了下降沿则清零计数器
  63.                 //******************* 接收同步信号 **********************************
  64.                 if(SampleTime > IR_SYNC_MAX)                IR_Sync = 0;        // 超出最大同步时间, 错误信息。
  65.                 else if(SampleTime >= IR_SYNC_MIN)                // SYNC
  66.                 {
  67.                         if(SampleTime >= IR_SYNC_DIVIDE)    // 区分13.5ms同步信号与11.25ms连发信号
  68.                         {
  69.                                 IR_Sync = 1;                                    // 收到同步信号 SYNC
  70.                                 IR_BitCnt = IR_BIT_NUMBER;          // 赋值32(32位有用信号)
  71.                         }
  72.                 }
  73.                 //********************************************************************
  74.                 else if(IR_Sync)                                                // 已收到同步信号 SYNC
  75.                 {
  76.                         if((SampleTime < IR_DATA_MIN)|(SampleTime > IR_DATA_MAX)) IR_Sync=0;        // 数据周期过短或过长,错误
  77.                         else
  78.                         {
  79.                                 IR_DataShit >>= 1;                                        // 键反码右移1位(发送端是低位在前,高位在后的格式)
  80.                                 if(SampleTime >= IR_DATA_DIVIDE)        IR_DataShit |= 0x80;        // 区别是数据 0还是1

  81.                                 //***********************  32位数据接收完毕 ****************************************
  82.                                 if(--IR_BitCnt == 0)                                 
  83.                                 {
  84.                                         IR_Sync = 0;                                        // 清除同步信号标志
  85.                                         if(~IR_DataShit == IR_data)                // 判断数据正反码
  86.                                         {
  87.                                                 if((IR_UserH == (User_code / 256)) && IR_UserL == (User_code % 256))
  88.                                                 {
  89.                                                                 IrUserErr = 0;            // 用户码正确
  90.                                                 }
  91.                                                 else        IrUserErr = 1;            // 用户码错误
  92.                                                       
  93.                                                 IR_code      = IR_data;                // 键码值
  94.                                                 IR_OK   = 1;                            // 数据有效
  95.                                         }
  96.                                 }
  97.                                 // 格式:  用户码L —— 用户码H —— 键码 —— 键反码
  98.                                 // 功能:  将 “用户码L —— 用户码H —— 键码”通过3次接收交换后存入对应字节,
  99.                                 //         这样写代码可以节省内存RAM占用,但是不如用数组保存好理解。        
  100.                                 //         键反码前面部分代码已保存好了        :IR_DataShit |= 0x80;                  
  101.                                 //**************************** 将接收的************************************************
  102.                                 else if((IR_BitCnt & 7)== 0)                // 1个字节接收完成
  103.                                 {
  104.                                         IR_UserL = IR_UserH;                        // 保存用户码高字节
  105.                                         IR_UserH = IR_data;                                // 保存用户码低字节
  106.                                         IR_data  = IR_DataShit;                        // 保存当前红外字节
  107.                                 }
  108.                         }
  109.                 }  
  110.         }
  111. }

  112. /**************** Timer0初始化函数 ******************************/
  113. void InitTimer0(void)
  114. {
  115.         TMOD = 0x01;                         // 16位计数方式.
  116.         TH0 = Timer0_Reload / 256;         
  117.         TL0 = Timer0_Reload % 256;
  118.         ET0 = 1;                                         
  119.         TR0 = 1;
  120.         EA  = 1;
  121. }  

  122. /********************** Timer0中断函数************************/
  123. void timer0 (void) interrupt 1
  124. {
  125.         IR_RX_HT6121();
  126.         TH0 = Timer0_Reload / 256;           // 重装定时器初值   
  127.         TL0 = Timer0_Reload % 256;           // 重装定时器初值   
  128. }

  129. /********************** 模拟串口相关函数************************/
  130. void delay104us(void)
  131. {
  132.    unsigned char i,j,k;
  133.    for(i=1;i>0;i--)       // 注意后面没分号
  134.    for(j=3;j>0;j--)       // 注意后面没分号
  135.    for(k=189;k>0;k--);    // 注意后面有分号        101
  136. }

  137. //模拟串口发送
  138. void Tx1Send(unsigned char dat)                //9600,N,8,1                发送一个字节
  139. {
  140.         unsigned char        i;
  141.         EA = 0;
  142.         TXD1 = 0;
  143.         delay104us();
  144.         for(i=0; i<8; i++)
  145.         {
  146.                 if(dat & 1)                TXD1 = 1;
  147.                 else                        TXD1 = 0;
  148.                 dat >>= 1;
  149.                 delay104us();
  150.         }
  151.         TXD1 = 1;
  152.         EA = 1;
  153.         delay104us();
  154.         delay104us();
  155. }

  156. void PrintString(unsigned char code *puts)                    // 发送一串字符串
  157. {
  158.     for (; *puts != 0;        puts++)  Tx1Send(*puts);         // 遇到停止符0结束
  159. }

  160. /********************* 十六进制转ASCII函数 *************************/
  161. unsigned char        HEX2ASCII(unsigned char dat)
  162. {
  163.         dat &= 0x0f;
  164.         if(dat <= 9)        return (dat + '0');        //数字0~9
  165.         return (dat - 10 + 'A');                        //字母A~F
  166. }

  167. /********************* 主函数 *************************/
  168. void main(void)
  169. {
  170.         InitTimer0();                                    // 初始化Timer0      
  171.         PrintString("定时器0初始化完毕\r\n");        // 上电后串口发送一条提示信息

  172.         while(1)
  173.         {
  174.                 if(IR_OK)                                     // 接收到一帧完整的红外数据
  175.                 {
  176.                         PrintString("红外键码: 0x");                // 提示红外键码
  177.                         Tx1Send(HEX2ASCII(IR_code >> 4));        // 键码高半字节
  178.                         Tx1Send(HEX2ASCII(IR_code));                // 键码低半字节
  179.                         if(IrUserErr)                                                // 用户码错误,则发送用户码
  180.                         {
  181.                                 Tx1Send(' ');                                        // 发空格
  182.                                 Tx1Send(' ');                                        // 发空格
  183.                                 PrintString("用户码: 0x");                // 提示用户码
  184.                                 Tx1Send(HEX2ASCII(IR_UserH >> 4));        // 用户码高字节的高半字节
  185.                                 Tx1Send(HEX2ASCII(IR_UserH));                // 用户码高字节的低半字节
  186.                                 Tx1Send(HEX2ASCII(IR_UserL >> 4));        // 用户码低字节的高半字节
  187.                                 Tx1Send(HEX2ASCII(IR_UserL));                // 用户码低字节的低半字节
  188.                         }
  189.                         Tx1Send(0x0d);                          // 发回车
  190.                         Tx1Send(0x0a);                          // 发回车
  191.                         IR_OK = 0;                              // 清除IR键按下标志
  192.                 }
  193.         }
  194. }
复制代码








回复

使用道具 举报

6#
ID:232280 发表于 2017-9-12 21:02 来自手机 | 只看该作者
我也是遇到了同样的问题,不过是红外控制继电器,也是写不出红外接收数组的判断
回复

使用道具 举报

7#
ID:200395 发表于 2017-9-13 10:39 | 只看该作者
首先要有红外编解码器,在发射红外线的一端有红外编码器,将要发送的数字调制到红外线上,在接收端,使用红外解码器将数字解调出来,然后单片机根据数字对密码锁进行控制。
回复

使用道具 举报

8#
ID:72333 发表于 2017-9-13 13:52 | 只看该作者
51单片机:038红外接收头 使用外部中断,再结合定时器中断就能实现
回复

使用道具 举报

9#
ID:232875 发表于 2017-9-13 15:01 | 只看该作者
使用外部中断,再结合定时器中断就能实现
回复

使用道具 举报

10#
ID:232530 发表于 2017-9-13 19:54 | 只看该作者
AAAAAA666666 发表于 2017-9-12 20:00
你的意思是,让单片机,检测到红外之后,自己开锁吗?

不是,是类似一个密码锁,检查的对的红外就开锁
回复

使用道具 举报

11#
ID:232530 发表于 2017-9-13 19:55 | 只看该作者
cjjcjj1 发表于 2017-9-12 19:23
你好!那你用按键控制的密码锁完成了吗?
可以在按键的基础之上,修改成红外控制的;
把你完成的打包发一 ...

还没完成,迟点
回复

使用道具 举报

12#
ID:232530 发表于 2017-9-13 19:58 | 只看该作者
无量寿经 发表于 2017-9-12 21:00
《51单片机轻松入门 基于STC15W4K系列》有配套例程可以直接使用,占用一个定时器,使用任意一个IO口即可接 ...

我的是89c52的芯片
回复

使用道具 举报

13#
ID:226263 发表于 2017-9-17 21:02 | 只看该作者
第一种靠中断的方法可以实现简单的红外控制,不能用红外控制PWM。第二种只用一个IO口的方法,51单片可以接受到信号,不过效果不好,不是每次都有用。但是同样的方法,其他单片机却可以很灵敏。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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