STM8 调试红外遥控器HS003B

news2025/1/16 6:34:26

背景

项目中使用STM8S003F3P6,控制红外遥控器HS003B,调试过程也遇到了很多问题,这里做个记录。

问题1:长按按键问题,如果长按遥控的某个按键,应该是一直能响应该按键值(需要对接收状态、接收信息清零操作)

问题2:按键响应不是很灵敏,有时候,有些按键按下了,却没有识别到(需要对接收状态、接收信息清零操作

原理图

红外遥控器的原理图设计,比较简单

如下图所示

使用STM8S003F3P6的管脚PA3进行数据监控

 软件设计

一些头文件的宏定义

//红外遥控识别码(ID),每款遥控器的该值基本都不一样,但也有一样的.
//我们选用的遥控器识别码为0
#define REMOTE_ID 0      	
#define REMOTE_IDH  0x0C
#define REMOTE_IDL  0xF3

extern u8 RmtCnt;	//按键按下的次数

void Remote_Init(void);    //红外传感器接收头引脚初始化
u8 Remote_Scan(void);	  

红外初始化函数

这里应该是最难调的地方,当时用了很多配置,都不能搞定,或者能用了,但是对红外遥控的按键指令响应不是太好

感觉遥控开关按键很难用

之后也调试了很久,可能还是针对红外的时序理解不是很深刻,这里就把实际调试的配置记录下来。

这里的核心思想就是使用定时器TIM2去捕获PA3的管脚的上升沿,这里TIM2的定时器配置,可以参考之前的开发板,结合自己的STM8S003F3P6使用时的主频进行配置,这个也很关键,如果读者想要移植到,自己的平台上,那么要着重注意这里的修改。

这里比较复杂,采用了定时器2,使用溢出中断和通道3的捕获功能,刚好对应管脚PA3

//红外遥控初始化
//设置IO以及TIM2_CH1的输入捕获
void Remote_Init(void)    			  
{		

  /* Set PA.3 TIM2_CH3 pin */
  ///GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_IN_PU_NO_IT);
  GPIO_DeInit(GPIOA);//恢复指定端口
  GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_IN_FL_NO_IT);//设置PA3为浮空输入无中断

  TIM2_DeInit();
  /* Time base configuration */      
  //TIM2_TimeBaseInit(TIM2_PRESCALER_2048, 65535);
  //TIM2_TimeBaseInit(TIM2_PRESCALER_1, 999);//2Mhz
  ///TIM2_TimeBaseInit(TIM2_PRESCALER_1, 1999);//1Mhz

  TIM2_TimeBaseInit(TIM2_PRESCALER_16, 10000 - 1);//1Mhz
  TIM2_ARRPreloadConfig(ENABLE);
  //TIM2_ClearFlag(TIM2_FLAG_UPDATE);//清除更新标志
  TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);//允许更新/溢出中断
  TIM2_Cmd(ENABLE);//开启定时器
  enableInterrupts(); //开启中断
  /* Prescaler configuration */
  ///TIM2_PrescalerConfig(TIM2_PRESCALER_2048, TIM2_PSCRELOADMODE_IMMEDIATE);
  //TIM2_ICInit(TIM2_CHANNEL_3, TIM2_ICPOLARITY_RISING, TIM2_ICSELECTION_DIRECTTI, TIM2_ICPSC_DIV1, 3);
   
  TIM2_ICInit(TIM2_CHANNEL_3, TIM2_ICPOLARITY_RISING, TIM2_ICSELECTION_DIRECTTI, TIM2_ICPSC_DIV1, 0);
  TIM2_ITConfig(TIM2_IT_CC3 , ENABLE);//中断配置与使能函数
  TIM2_ClearITPendingBit(TIM2_IT_CC3);
  TIM2_ClearFlag(TIM2_FLAG_CC3);
  //TIM2_CCxCmd(TIM2_CHANNEL_2, ENABLE);//输入捕获/比较输出使能
	
}

 定时器2的

中断溢出响应函数

定时器2的捕获响应函数

/**
  * @brief Timer2 Update/Overflow/Break Interrupt routine.
  * @param  None
  * @retval None
  */
//遥控器接收状态
//[7]:收到了引导码标志
//[6]:得到了一个按键的所有信息
//[5]:保留	
//[4]:标记上升沿是否已经被捕获								   
//[3:0]:溢出计时器
u8 	RmtSta=0;	  	  
u16 Dval;		//下降沿时计数器的值
u32 RmtRec=0;	//红外接收到的数据	   		    
u8  RmtCnt=0;	//按键按下的次数	
//定时器1溢出中断
 INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)
 {
  /* In order to detect unexpected events during development,
     it is recommended to set a breakpoint on the following instruction.
  */

  ///if(TIM2_GetITStatus(TIM2_IT_UPDATE)==SET) //溢出中断
    
  if(RmtSta&0x80)//上次有数据被接收到了
  {	
    RmtSta&=~0X10;						//取消上升沿已经被捕获标记
    if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;//标记已经完成一次按键的键值信息采集
    else
    {
      RmtSta&=~(1<<7);
      RmtSta&=0XF0;
    }
    //if((RmtSta&0X0F)<14)RmtSta++;
    //else
    //{
    //        RmtSta&=~(1<<7);//清空引导标识
    //        RmtSta&=0XF0;	//清空计数器	
    //}						 	   	
  }
  TIM2_ClearFlag(TIM2_FLAG_UPDATE);
  TIM2_ClearITPendingBit(TIM2_IT_UPDATE);  //清除中断标志位 

 }


/**
  * @brief Timer2 Capture/Compare Interrupt routine.
  * @param  None
  * @retval None
  */
 //定时器1输入捕获中断服务程序	 
 INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14)
 {
  /* In order to detect unexpected events during development,
     it is recommended to set a breakpoint on the following instruction.
  */
  BitStatus bs;
  bs = GPIO_ReadInputPin(GPIOA, GPIO_PIN_3);//读PA3的输入电平状态
  //if(TIM2_GetITStatus(TIM2_IT_CC3)==SET) //处理捕获(CC1IE)中断
  	  
  if(bs)//上升沿捕获
  {
      TIM2_OC3PolarityConfig(TIM2_OCPOLARITY_LOW);		//CC1P=1 设置为下降沿捕获
      TIM2_SetCounter(0x0000);	   	//清空定时器值
      RmtSta|=0X10;					//标记上升沿已经被捕获
  }else //下降沿捕获
  {
      Dval = TIM2_GetCounter();//读取CCR2也可以清CC2IF捕获标志位
      TIM2_OC3PolarityConfig(TIM2_OCPOLARITY_HIGH); //CC1P=0	设置为上升沿捕获
      if(RmtSta&0X10)					//完成一次高电平捕获 
      {
          if(RmtSta&0X80)//接收到了引导码
          {                      
              if(Dval>300&&Dval<800)			//560为标准值,560us
              {
                  RmtRec<<=1;	//左移一位.
                  RmtRec|=0;	//接收到0	   
              }else if(Dval>1400&&Dval<1800)	//1680为标准值,1680us
              {
                  RmtRec<<=1;	//左移一位.
                  RmtRec|=1;	//接收到1
              }else if(Dval>2200&&Dval<2600)	//得到按键键值增加的信息 2500为标准值2.5ms
              {
                  RmtCnt++; 		//按键次数增加1次
                  RmtSta&=0XF0;	//清空计时器		
              }
          }else if(Dval>4200&&Dval<4700)		//4500为标准值4.5ms
          {
              RmtSta|=1<<7;	//标记成功接收到了引导码
              RmtCnt=0;		//清除按键次数计数器
          }						 
      }
      RmtSta&=~(1<<4);
  }				 		     	    					   
  TIM2_ClearITPendingBit(TIM2_IT_CC3);  //清除中断标志位 
 }

 main函数中扫描按键值函数


//遥控器接收状态
//[7]:收到了引导码标志
//[6]:得到了一个按键的所有信息
//[5]:保留	
//[4]:标记上升沿是否已经被捕获								   
//[3:0]:溢出计时器
extern u8  RmtSta;	  	  
extern u16 Dval;		//下降沿时计数器的值
extern u32 RmtRec;	//红外接收到的数据	   		    
extern u8  RmtCnt;	//按键按下的次数	 
//处理红外键盘
//返回值:
//0,没有任何按键按下
//其他,按下的按键键值.
u8 Remote_Scan(void)
{        
  u8 sta=0;       
  u8 t1,t2;  
  if(RmtSta&(1<<6))//得到一个按键的所有信息了
  { 
      t1=RmtRec>>24;			//得到地址码
      t2=(RmtRec>>16)&0xff;	//得到地址反码 
      //if((t1==(u8)~t2)&&t1==REMOTE_ID)//检验遥控识别码(ID)及地址 
      if((t1==REMOTE_IDH)&&t2==REMOTE_IDL)
      { 
          t1=RmtRec>>8;
          t2=RmtRec; 	
          if(t1==(u8)~t2)sta=t1;//键值正确	 
       }   
      //if((sta==0)||((RmtSta&0X80)==0))//按键数据错误/遥控已经没有按下了
      {
              RmtSta&=~(1<<6);//清除接收到有效按键标识
              RmtSta&=~(1<<7);//清楚引导码标识
              RmtCnt=0;		//清除按键次数计数器
              RmtRec = 0;
      }
  }  
  return sta;
}

 实际中main函数的使用方法

扫描按键值,获取到按键值以后,进行不同按键值的处理

  key = Remote_Scan();	
    if(key)
    {	 	  
      switch(key)
      {	  
        case 0X11://开机按键
        {
          if(powerOn == 0)
          {
            powerOn = 1;
            GPIO_WriteHigh(GPIOA, GPIO_PIN_2);            
          }
          else
          {
            powerOn = 0;
            GPIO_WriteLow(GPIOA, GPIO_PIN_2);
          }
          needSend2Ctl |= 1<<1;
          break;

        }
        case 0X61:
        {
          speed++;
          if(speed > 5)
            speed = 5;
          updata();
          needSend2Ctl |= 1<<1;
          break;
        }	  
        case 0XE1:
        {
          speed--;
          if(speed < 1)
            speed = 1;
          updata();
          needSend2Ctl |= 1 << 1;
          break;
        }
        case 0XA9:
        {
          //s,模式按键

          break;
        }
        default:
          break;
      }
     }

其他

 红外遥控波形

红外传感器原理,原始信号就是我们要发送的一个数据“0”位或者一位数据“1”位,而所谓 38K 载波就是频率为 38K 的方波信号,调制后信号就是最终我们发射出去的波形。我们使用原始信号来控制 38K 载波,当信号是数据“0”的时候,38K 载波毫无保留的全部发送出去,当信号是数据“1”的时候,不发送任何载波信号。

下图为红外调制信号

NEC码的位定义:一个脉冲对应560us的连续载波,一个逻辑1传输需要2.25ms(560us脉冲+1680us低电平),一个逻辑0的传输需要1.125ms(560us的脉冲+560us低电平)。

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


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/557500.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

工作模式(3)

8bit PWM PWM模式开启时&#xff0c;计数器与比较寄存器连续比较&#xff0c;当计数值小于比较寄存器&#xff0c;输出为低&#xff0c;当计数值大于等于比较寄存器&#xff0c;输出为高&#xff0c;并且保持到计数值等于重载寄存器&#xff0c;然后计数器回到0开始重新计数&am…

【三维激光扫描】实验05:点云数据预处理操作

SiScan软件可以对三维激光扫描的点云数据进行一些列的预处理操作,如:粗差剔除、点云抽稀、点云分割、调整水平面、删除分割面等等。 粗差剔除剔除粗差点抽稀抽稀数据点云分割根据点云的三维特征进行分组调整水平面根据三个点来调整水平面分割面水平纠正根据分割面进行水平纠正…

小心你的 OpenAI Key 被盗!

公众号关注 “GitHubDaily” 设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01; 今年随着 ChatGPT 发布&#xff0c;其强悍的能力也让 GPT-3.5/4 成为炙手可热的大语言模型&#xff0c;使得不少 AI 应用接入了 OpenAI 接口。当用户使用这些应用时&#xff0c;经常需要填…

Python自动化办公对每个子文件夹的Excel表加个表头(Excel不同名)(上篇)

点击上方“Python爬虫与数据挖掘”&#xff0c;进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 含情凝睇谢君王&#xff0c;一别音容两渺茫。 大家好&#xff0c;我是皮皮。 一、前言 上一篇文章&#xff0c;我们抛出了一个问题&#xff0c;这篇文章…

工作模式(2)

输入捕捉 输入捕捉功能的主要特点&#xff1a; ⚫ 上升沿或下降沿捕捉 ⚫ 脉冲宽度捕捉或脉冲周期捕捉 ⚫ 带清零的捕捉或自由计数捕捉 ⚫ 单次捕捉或连续捕捉 捕捉模式只能工作在16bit级联模式下&#xff0c;从0开始计数。当选择上升沿捕捉周期模式时&#xff0c;电路在检测到…

chatgpt赋能Python-python_fetchone

Python fetchone方法简介 在Python编程领域中&#xff0c;fetchone()是一个经常使用的方法。fetchone()方法用于从数据库中获取单个结果&#xff0c;并将结果存储在变量中。本文将介绍fetchone()方法的详细信息&#xff0c;并探讨如何在Python中使用该方法。 什么是fetchone方…

chatgpt赋能Python-python_chariot

Python Chariot&#xff1a;一款强大的Python IDE Python Chariot是一款强大的Python IDE&#xff0c;它的特点是简单易用&#xff0c;功能齐全。该IDE适用于各种Python编程任务&#xff0c;无论是编写小型脚本还是大型项目。在本文中&#xff0c;我们将深入介绍Python Chario…

Windows本地快速搭建SFTP服务共享文件 - 外网访问【端口映射】

文章目录 1. 搭建SFTP服务器1.1 下载 freesshd服务器软件1.3 启动SFTP服务1.4 添加用户1.5 保存所有配置 2 安装SFTP客户端FileZilla测试2.1 配置一个本地SFTP站点2.2 内网连接测试成功 3 使用cpolar内网穿透3.1 创建SFTP隧道3.2 查看在线隧道列表 4. 使用SFTP客户端&#xff0…

基于SpringBoot的停车位智能管理系统的设计与实现_kaic

摘 要 随着经济与交通事业的飞速发展&#xff0c;汽车的保有量呈现上升趋势&#xff0c;公共停车位 智能化在信息时代显得尤为重要。面对有限的公共停车位与上升的汽车保有量&#xff0c; 通过合理利用公共停车位来提高车位的利用率是大势所趋。 基于上述背景&#xff0c;本论…

为生信写的Python简明教程 | 视频4

开源生信 Python教程 生信专用简明 Python 文字和视频教程 源码在&#xff1a;https://github.com/Tong-Chen/Bioinfo_course_python 目录 背景介绍 编程开篇为什么学习Python如何安装Python如何运行Python命令和脚本使用什么编辑器写Python脚本Python程序事例Python基本语法 数…

基于 Log 的通用增量 Checkpoint 在美团的进展

摘要&#xff1a;本文整理自美团计算引擎工程师王非凡&#xff0c;在 Flink Forward Asia 2022 核心技术专场的分享。本篇内容主要分为四个部分&#xff1a; 1. Log based Checkpoint 基本原理介绍 2. 美团应用场景及测试效果 3. Changelog Restore 性能优化 4. Changelog 存储…

49天精通Java,第35天,Java初始化、构造器、对象创建的过程

目录 一、初始化与清理二、用构造器保证初始化1、无参构造器2、有参构造器 三、成员初始化1、显式初始化2、隐式初始化3、初始化块 四、对象创建的过程 大家好&#xff0c;我是哪吒。 &#x1f3c6;本文收录于&#xff0c;49天精通Java从入门到就业。 全网最细Java零基础手把…

微服务开发系列 第三篇:OpenFeign

总概 A、技术栈 开发语言&#xff1a;Java 1.8数据库&#xff1a;MySQL、Redis、MongoDB、Elasticsearch微服务框架&#xff1a;Spring Cloud Alibaba微服务网关&#xff1a;Spring Cloud Gateway服务注册和配置中心&#xff1a;Nacos分布式事务&#xff1a;Seata链路追踪框架…

多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间序列预测

多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间序列预测 目录 多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间…

OSPF 邻居关系 附实验

实验目的 通过对 OSPF 邻居关系建立进行相关的实验&#xff0c;从中学习到如何调整 OSPF Hello 包间隔&#xff0c;Dead 间隔&#xff0c;以及影响 OSPF 邻居建立的因素&#xff0c;例如 RID&#xff0c;MTU&#xff0c;OSPF 认证。并且将总结 OSPF在不同网络类型上的不同行为…

FPGA纯verilog实现CameraLink视频接收和发送,附带工程源码和技术支持

目录 1、前言2、CameraLink协议基础3、目前我已有的CameraLink收发工程4、设计方案5、CameraLink解码模块详解6、CameraLink编码模块详解7、vivado工程详解8、上板调试验证9、福利&#xff1a;工程代码的获取 1、前言 FPGA实现CameraLink视频编解码目前有两种方案&#xff1a;…

C++基本介绍

文章目录 &#x1f96d;1.C基本介绍&#x1f9c2;1.1 C是什么&#x1f9c2;1.2 C发展史 &#x1f352;2. C的优势&#x1f954;2.1 语言的使用广泛度&#x1f954;2.2 C的应用领域 &#x1fad2;3. C学习计划 &#x1f96d;1.C基本介绍 &#x1f9c2;1.1 C是什么 C是一种通用…

用streamlit,几行代码就可以拥有漂亮图表!

大家注意&#xff1a;因为微信最近又改了推送机制&#xff0c;经常有小伙伴说错过了之前被删的文章&#xff0c;比如前阵子冒着风险写的爬虫&#xff0c;再比如一些限时福利&#xff0c;错过了就是错过了。 所以建议大家加个星标&#xff0c;就能第一时间收到推送。&#x1f44…

FastAPI 和 fastapi-amis-admin:强大而可扩展的后台管理解决方案!

大家好&#xff0c;我是安果&#xff01; 我们都知道 Django 生态丰富&#xff0c;功能强大&#xff0c;适用于中、大型项目&#xff0c;并且自带了后台管理系统&#xff1b;而 FastAPI 更适用于构建高性能的 API&#xff0c;后台管理系统需要另外开发 本篇文章将介绍 FastAPI…

完犊子!原单位的离职证明丢了,下周要入职了,用AI做一个行不行?

弄丢了离职证明怎么办&#xff1f; 一位网友哀叹&#xff1a; 完犊子&#xff01;原单位的离职证明丢了&#xff0c;下周要入职了&#xff0c;现在怎么办&#xff1f;用AI做一个行不行&#xff1f; 有相同经历的网友安慰他&#xff0c;离职证明没了没事&#xff0c;新公司会要求…