STM32(三十三)NEC红外遥控

一、红外遥控简介

                                 

     

  • 红外遥控是一种无线、非接触控制技术,
  • 具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,
  • 同类产品的红外线遥控器,可以有相同的遥控频率或编码,而不会出现遥控信号“串门”的情况。
  • 红外遥控的编码目前广泛使用的是: NEC Protocol的PWM(脉冲宽度调制)和Philips的RC-5 Protocol的PPM(脉冲位置调制)。

 二、NEC协议特征

  • 8位地址和8位指令长度;
  • 地址和命令2次传输(确保可靠性)
  • PWM脉冲位置调制,以发射红外载波的占空比代表“0”和“1”;
  • 载波频率为38Khz;
  • 位时间为1.125ms或2.25ms ( 高电平持续时间来区分);

1、NEC码的位定义:

  • 一个脉冲对应560us的连续载波,一个逻辑1传输需要2.25ms ( 560us脉冲+1680us低电平),一个逻辑0的传输需要1.125ms ( 560us脉冲+560us低电平)。
  • 遥控接收头在收到脉冲的时候为低电平,在没有脉冲的时候为高电平,这样,我们在接收头端收到的信号为:逻辑1应该是560us低+1680us高,逻辑0应该是560us低+560us高。

                                                 

 

 

                                                         遥控器发送                                                         接收头收到的

 

 

 

  通过原理图可知检测REMOTE_IN上的信号可以收到遥控发过来的信号,检测到1680us的高电平就是数据1,检测到560us的高电平就是0;

2、NEC遥控器指令格式

  NEC遥控指令的数据格式为:同步码头、地址码、地址反码、控制码、控制反码同步码由一个9ms的低电平和一个4.5ms的高电平组成,地址码、地址反码、控制码、控制反码均是8位数据格式。按照低位在前高位在后的顺序发送。采用反码是为了增加传输的可靠性(可用于校验)                       

                     

 

 

                                                                                                      

 

 

 3、实验:遥控实现蜂鸣器开关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "infrared.h"
 
void Infrared_Init(void)
{
    GPIO_InitTypeDef    GPIO_InitStruct;   
    EXTI_InitTypeDef    EXTI_InitStruct;
    NVIC_InitTypeDef    NVIC_InitStruct;
     
    //使能SYSCFG时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
 
    //使能GPIOA
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
     
    GPIO_InitStruct.GPIO_Pin    =   GPIO_Pin_8;     //引脚
    GPIO_InitStruct.GPIO_Mode   =   GPIO_Mode_IN;   //输入模式
    GPIO_InitStruct.GPIO_PuPd   =   GPIO_PuPd_UP;   //上拉
    GPIO_InitStruct.GPIO_Speed  =   GPIO_Speed_50MHz; //速度50MHZ
 
    GPIO_Init(GPIOA, &GPIO_InitStruct);
     
    //设置IO口与中断线的映射关系,必须分开写     
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource8);
 
    EXTI_InitStruct.EXTI_Mode       =   EXTI_Mode_Interrupt; //中断
    EXTI_InitStruct.EXTI_Line       =   EXTI_Line8;  //中断线8  因为是PA8,所以选择line8    EXTI_InitStruct.EXTI_Trigger   =   EXTI_Trigger_Falling; //下降沿  下降沿触发是因为REMOTE_IN在没有按遥控时一直处于高电平,当按下遥控时,同步码头先过来,拉低,代表数据传输开始   EXTI_InitStruct.EXTI_LineCmd  =   ENABLE; //中断线使能
    //初始化线上中断,设置触发条件等。 
    EXTI_Init(&EXTI_InitStruct);   
 
    NVIC_InitStruct.NVIC_IRQChannel         = EXTI9_5_IRQn; //中断号
    NVIC_InitStruct.NVIC_IRQChannelCmd      = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0x02; //抢占优先级
    NVIC_InitStruct.NVIC_IRQChannelSubPriority =0x02;   //响应优先级
    NVIC_Init(&NVIC_InitStruct);
 
}
//计算高电平时间    t*20us
u32 ir_pluse_high_time(void)
{
    u32 t=0;
     
    while(PAin(8))  
    {
        t++;
        delay_us(20);//20微秒
         
        if(t > 250)//大于5ms数据异常
            break;
    }
    return t;
}
 
 
void EXTI9_5_IRQHandler(void)
{
    u32 t=0;
    u32 ir_bit=0;
    u8  ir_valed=0;
    u32 ir_data = 0;
    u8  ir_cunt=0;
    //判断是否中断线8
    if(EXTI_GetITStatus(EXTI_Line8) == SET)
    {
        //清除中断标志位
        EXTI_ClearITPendingBit(EXTI_Line8);
        while(1)
        {
            if(PAin(8))//等待到高电平,过滤低电平
            {
                t = ir_pluse_high_time();
                if(t>=250)//收到高电平数据异常
                    break;
                 
                if(t>200 && t<250)//高电平时间为 4000 - 5000内也就是4ms - 5ms
                {
                    ir_valed = 1;//有效的同步码头
                    continue;
                }
                //若高电平持续时间为200~1000us内则为数据位为0:  560us在 200-1000us之间
                else if(t>10 && t<50)
                {
                    ir_bit = 0;
                }
                //若高电平持续时间为1200~1800us内则为数据位为1:
                else if(t>60 && t<90)
                {
                    ir_bit = 1;
                }
                 
                if(ir_valed)
                {
                    //将位数据移到到ir_data
                    ir_data |=ir_bit<<ir_cunt;
                     
                    ir_cunt++;
                     
                    if(ir_cunt >= 32)
                    {
                        printf("ir_data = %x\n",ir_data);
                        if(ir_data == 0XBC43FF00)  //遥控上的暂停播放键
                        {
                            PFout(8)^=1; //开关蜂鸣器
                        }
                         
                        break;
                    }
                     
                }      
             
            }
         
        }
 
    }
     
}

  

 

 

 

 

 

 

 

 

1
下降沿触发是因为REMOTE_IN在没有按遥控时一直处于高电平,当按下遥控时,同步码头先过来,拉低,代表数据传输开始
posted @   轻轻的吻  阅读(1793)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
历史上的今天:
2019-05-15 电视制式及声音制式的划分
点击右上角即可分享
微信分享提示