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在没有按遥控时一直处于高电平,当按下遥控时,同步码头先过来,拉低,代表数据传输开始 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于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 电视制式及声音制式的划分