[其他ST产品] STM32 NEC红外遥控器解码

[复制链接]
1475|32
 楼主| wang6623 发表于 2023-2-28 23:27 | 显示全部楼层 |阅读模式
STM32 NEC红外遥控器解码
红外遥控编码格式
一体化红外接收头
STM32显示遥控器按下的数字代码
代码片
总结
原文链接:https://www.yourcee.com/newsinfo/2925876.html

红外遥控编码格式
现有的红外遥控包括两种方式:PWM(脉冲宽度调制)和PPM(脉冲位置调制)。两种形式编码的代表分别为NEC 和PHILIPS 的RC-5、RC-6 以及将来的RC-7。
NEC 格式的特征:
1:使用38 kHz 载波频率
2:引导码间隔是9 ms + 4.5 ms
3:使用16 位客户代码
4:使用8 位数据代码和8 位取反的数据代码

 楼主| wang6623 发表于 2023-2-28 23:27 | 显示全部楼层
NEC 协议通过脉冲串之间的时间间隔来实现信号的调制(英文简写PWM) 。 逻辑“0”是由0.56ms的38KHZ载波和0.56ms 的无载波间隔组成; 逻辑“1”是由0.56ms 的38KHZ 载波和1.68ms 的无载波间隔组成; 结束位是0.56ms 的38K 载波。
 楼主| wang6623 发表于 2023-2-28 23:27 | 显示全部楼层
 楼主| wang6623 发表于 2023-2-28 23:27 | 显示全部楼层
PPM(脉冲位置调制):以发射载波的位置表示“0”和“1”。从发射载波到不发射载波为“0”,从不发射载波到发射载波为“1”。其发射载波和不发射载波的时间相同,都为0.68ms,也就是每位的时间是固定的。RC5 编码相对简单一些:
 楼主| wang6623 发表于 2023-2-28 23:28 | 显示全部楼层
 楼主| wang6623 发表于 2023-2-28 23:28 | 显示全部楼层
 楼主| wang6623 发表于 2023-2-28 23:28 | 显示全部楼层
得到一组数字: 110, 11010, 001101根据编码定义:
第一位是起始位S通常是逻辑1
第二位是场位F通常为逻辑1, 在RC5 扩展模式下它将最后6位命令代码扩充到7 位代码(高位MSB) , 这样可以从64 个键值扩充到128 个键值。
第三位是控制位C它在每按下了一个键后翻转, 这样就可以区分一个键到底是一直按着没松手还是松手后重复按。
 楼主| wang6623 发表于 2023-2-28 23:28 | 显示全部楼层
其后是五个系统地址位:11010=1A, 最后是六个命令位:001101=0D。
 楼主| wang6623 发表于 2023-2-28 23:31 | 显示全部楼层
一体化红外接收头
红外接收电路通常被厂家集成在一个元件中,成为一体化红外接收头。内部电路包括红外监测二极管,放大器,限副器,带通滤波器,积分电路,比较器等。红外监测二极管监测到红外信号,然后把信号送到放大器和限幅器,限幅器把脉冲幅度控制在一定的水平,而不论红外发射器和接收器的距离远近。交流信号进入带通滤波器,带通滤波器可以通过30khz到60khz的负载波,通过解调电路和积分电路进入比较器,比较器输出高低电平,还原出发射端的信号波形。注意输出的高低电平和发射端是反相的,这样的目的是为了提高接收的灵敏度。
 楼主| wang6623 发表于 2023-2-28 23:31 | 显示全部楼层
红外接收头的种类很多,引脚定义也不相同,一般都有三个引脚,包括供电脚,接地和信号输出脚。根据发射端调制载波的不同应选用相应解调频率的接收头。
 楼主| wang6623 发表于 2023-2-28 23:31 | 显示全部楼层
红外接收头内部放大器的增益很大,很容易引起干扰,因此在接收头的供电脚上须加上滤波电容,一般在22uf以上。有的厂家建议在供电脚和电源之间接入330欧电阻,进一步降低电源干扰。
 楼主| wang6623 发表于 2023-2-28 23:32 | 显示全部楼层
STM32显示遥控器按下的数字代码
6112563fe1e77d1094.png
 楼主| wang6623 发表于 2023-2-28 23:32 | 显示全部楼层
 楼主| wang6623 发表于 2023-2-28 23:32 | 显示全部楼层
 楼主| wang6623 发表于 2023-2-28 23:32 | 显示全部楼层
代码片、
  1. //红外遥控初始化
  2. //设置IO以及定时器3的输入捕获
  3. void Remote_Init(void)                              
  4. {  

  5.         RCC->APB1ENR|=1<<1;           //TIM3 时钟使能
  6.         RCC->APB2ENR|=1<<3;            //使能PORTB时钟
  7.         GPIOB->CRL&=0XFFFFFFF0;        //PB0 输入  
  8.         GPIOB->CRL|=0X00000008;        //上拉输入     
  9.         GPIOB->ODR|=1<<0;                //PB0 上拉
  10.        
  11.         TIM3->ARR=10000;                  //设定计数器自动重装值 最大10ms溢出  
  12.         TIM3->PSC=71;                          //预分频器,1M的计数频率,1us加1.       
  13.         TIM3->CCMR2|=1<<0;                //CC3S=01         选择输入端 IC3映射到TI3上
  14.         TIM3->CCMR2|=3<<4;          //IC3F=0011 配置输入滤波器 8个定时器时钟周期滤波
  15.         TIM3->CCMR2|=0<<2;          //IC3PS=00         配置输入分频,不分频
  16.         TIM3->CCER|=0<<9;                 //CC3P=0        上升沿捕获
  17.         TIM3->CCER|=1<<8;                 //CC3E=1         允许捕获计数器的值到捕获寄存器中
  18.         TIM3->DIER|=1<<3;           //允许CC3IE捕获中断                               
  19.         TIM3->DIER|=1<<0;           //允许更新中断                               
  20.         TIM3->CR1|=0x01;            //使能定时器3
  21.           MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2               
  22.        
  23. }
 楼主| wang6623 发表于 2023-2-28 23:33 | 显示全部楼层
  1. //遥控器接收状态
  2. //[7]:收到了引导码标志
  3. //[6]:得到了一个按键的所有信息
  4. //[5]:保留       
  5. //[4]:标记上升沿是否已经被捕获                                                                  
  6. //[3:0]:溢出计时器
  7. u8         RmtSta=0;                    
  8. u16 Dval;                //下降沿时计数器的值
  9. u32 RmtRec=0;        //红外接收到的数据                               
  10. u8  RmtCnt=0;        //按键按下的次数          
  11. //定时器3中断服务程序         
  12. void TIM3_IRQHandler(void)
 楼主| wang6623 发表于 2023-2-28 23:33 | 显示全部楼层
  1. {        
  2.     u16 tsr;
  3.         tsr=TIM3->SR;
  4.        
  5.     if(tsr&0X01)//溢出
  6.         {
  7.                 if(RmtSta&0x80)//上次有数据被接收到了
  8.                 {       
  9.                         RmtSta&=~0X10;                                                //取消上升沿已经被捕获标记
  10.                         if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;//标记已经完成一次按键的键值信息采集
  11.                         if((RmtSta&0X0F)<14)RmtSta++;
  12.                         else
  13.                         {
  14.                                 RmtSta&=~(1<<7);//清空引导标识
  15.                                 RmtSta&=0XF0;        //清空计数器       
  16.                         }                                                                   
  17.                 }                                                            
  18.         }
  19.         if(tsr&(1<<3))//CC3IE中断
  20.         {          
  21.                 if(RDATA)//上升沿捕获
  22.                 {                       
  23.                         TIM3->CCER|=1<<9;                                 //CC3P=1        设置为下降沿捕获
  24.                         TIM3->CNT=0;                                        //清空定时器值
  25.                         RmtSta|=0X10;                                        //标记上升沿已经被捕获               
  26.                 }else //下降沿捕获
  27.                 {                       
  28.                        
  29.                         Dval=TIM3->CCR3;                                //读取CCR3也可以清CC2IF标志位
  30.                           TIM3->CCER&=~(1<<9);                        //CC3P=0        设置为上升沿捕获
  31.                        
  32.                         if(RmtSta&0X10)                                        //完成一次高电平捕获
  33.                         {
  34.                                 if(RmtSta&0X80)//接收到了引导码
  35.                                 {
  36.                                        
  37.                                         if(Dval>300&&Dval<800)                        //560为标准值,560us
  38.                                         {
  39.                                                 RmtRec<<=1;        //左移一位.
  40.                                                 RmtRec|=0;        //接收到0          
  41.                                         }else if(Dval>1400&&Dval<1800)        //1680为标准值,1680us
  42.                                         {
  43.                                                 RmtRec<<=1;        //左移一位.
  44.                                                 RmtRec|=1;        //接收到1
  45.                                         }else if(Dval>2200&&Dval<2600)        //得到按键键值增加的信息 2500为标准值2.5ms
  46.                                         {
  47.                                                 RmtCnt++;                 //按键次数增加1次
  48.                                                 RmtSta&=0XF0;        //清空计时器               
  49.                                         }
  50.                                 }else if(Dval>4200&&Dval<4700)                //4500为标准值4.5ms
  51.                                 {
  52.                                         RmtSta|=1<<7;        //标记成功接收到了引导码
  53.                                         RmtCnt=0;                //清除按键次数计数器
  54.                                 }                                                 
  55.                         }
  56.                         RmtSta&=~(1<<4);
  57.                 }                                                                                                            
  58.         }       
  59.    TIM3->SR=0;//清除中断标志位     
  60. }
 楼主| wang6623 发表于 2023-2-28 23:33 | 显示全部楼层
  1. //处理红外键盘
  2. //返回值:
  3. //         0,没有任何按键按下
  4. //其他,按下的按键键值.
  5. u8 Remote_Scan(void)
  6. {        
  7.         u8 sta=0;      
  8.     u8 t1,t2;  
  9.         if(RmtSta&(1<<6))//得到一个按键的所有信息了
  10.         {
  11.             t1=RmtRec>>24;                        //得到地址码
  12.             t2=(RmtRec>>16)&0xff;        //得到地址反码
  13.             if((t1==(u8)~t2)&&t1==REMOTE_ID)//检验遥控识别码(ID)及地址
  14.             {
  15.                 t1=RmtRec>>8;
  16.                 t2=RmtRec;        
  17.                 if(t1==(u8)~t2)sta=t1;//键值正确         
  18.                 }   
  19.                 if((sta==0)||((RmtSta&0X80)==0))//按键数据错误/遥控已经没有按下了
  20.                 {
  21.                          RmtSta&=~(1<<6);//清除接收到有效按键标识
  22.                         RmtCnt=0;                //清除按键次数计数器
  23.                 }
  24.         }  
  25.     return sta;
  26. }
 楼主| wang6623 发表于 2023-2-28 23:34 | 显示全部楼层
  1. // 共阴数字数组
  2. // 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, .,全灭
  3. u8 smg_num[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e,0x01,0x00};
  4. u8 key=0;  //按键值
  5. u8 num=0x00;//数值
  6. u8 num1=0x00;//数值
  7. u8 smg_wei=6;//数码管位选
  8. u8 smg_duan=0;//数码管段选
  9. u8 smg_flag=0;//数码管显示标志 0:正常显示 1:不显示(消除鬼影)
  10. u8 t=0;
  11. int main(void)
 楼主| wang6623 发表于 2023-2-28 23:34 | 显示全部楼层
  1. {
  2.        
  3.         Stm32_Clock_Init(9);        //系统时钟设置
  4.         uart_init(72,115200);        //串口初始化为115200
  5.         delay_init(72);                            //延时初始化
  6.         BEEP_Init();            //蜂鸣器初始化
  7.         LED_Init();                                  //初始化与LED连接的硬件接口
  8.     LED_SMG_Init();         //数码管初始化
  9.     TIM4_Init(19,7199);     //数码管2ms定时显示
  10.     Remote_Init();                        //红外接收初始化                 
  11.         while(1);
  12. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

71

主题

617

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部