【STM32】STM32之红外接收

本篇博文最后修改时间:2017年04月04日,12:48。


一、简介

本文介绍如何在STM32上使用红外接收头接收红外信号

其中,红外协议采用为最常见的NEC协议


二、实验平台

库版本:STM32F10x_StdPeriph_Lib_V3.5.0

编译软件:MDK4.53

硬件平台:STM32开发板(主芯片stm32f103c8t6)

仿真器:JLINK


版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.NET/feilusia

联系方式:[email protected]

香瓜BLE之CC2541群:127442605

香瓜BLE之CC2640群:557278427

香瓜BLE之Android群:541462902

香瓜单片机之STM8/STM32群:164311667
甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

四、 实验前提
1、在进行本文步骤前,请先 阅读 以下博文:
1)《STM8L之红外发射》:http://blog.csdn.net/feilusia/article/details/53305956

2、在进行本文步骤前,请先 实现 以下博文:
1)《STM32之系统滴答定时器》 :http://blog.csdn.net/feilusia/article/details/52835711

五、基础知识

1、硬件原理

答:

1)接收管元器件

【STM32】STM32之红外接收_第1张图片

上图的引脚从左到右依次为:OUT(空闲时为高电平,接收到载波时为低电平)、GND、VCC。

电压范围为2.7V~5.5V。


附淘宝链接:

https://detail.tmall.com/item.htm?spm=a1z10.3-b.w4011-3079905380.37.ZS9LXo&id=14265901312&rn=9fa50b1d19ad40efa6f149c454e32cfa&abbucket=14


2)硬件原理图

【STM32】STM32之红外接收_第2张图片

如上图,红外接收引脚接到PB3,PB3为JTAG使用引脚,因此在代码中要注意将引脚功能切换回普通IO口。


2、本文中红外接收的流程是如何的?

答:

1)配置红外接收引脚PB3为IO上拉中断方式。

2)当红外接收头接收到红外遥控器发出的载波信号时,PB3被拉低,代码进入中断服务函数,并依次判断时序是否满足:引导码、用户码、用户反码、键码、键码反码、停止位。

如果时序正确,则获得键值。如果时序不正确,则将此数据过滤。


六、实验步骤

注:下面的步骤为主要步骤,并不是所有步骤,编译有错误的地方请自行修改。

1、编写并添加红外接收的驱动

1)编写驱动GUA_Infrared_Receiver.c(存放在“……\HARDWARE”)

//******************************************************************************              
//name:             GUA_Infrared_Receiver.c             
//introduce:        红外传感器接收驱动      
//author:           甜甜的大香瓜                     
//email:            [email protected]         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2016.12.29      
//******************************************************************************   
#include "stm32f10x.h" 
#include "GUA_Infrared_Receiver.h"
#include "GUA_SysTick.h"

/*********************宏定义************************/
#define TRUE			0
#define FALSE			1

//红外接收引脚
//IO
#define GUA_INFRARED_RECEIVER_PORT               GPIOB
#define GUA_INFRARED_RECEIVER_PIN                GPIO_Pin_3
#define GUA_INFRARED_RECEIVER_RCC                RCC_APB2Periph_GPIOB

//中断
#define GUA_INFRARED_RECEIVER_EXTI_LINE          EXTI_Line3
#define GUA_INFRARED_RECEIVER_PORTSOURCE         GPIO_PortSourceGPIOB
#define GUA_INFRARED_RECEIVER_PINSOURCE          GPIO_PinSource3 
/*********************外部变量************************/
GUA_U32 gGUA_InfraredReceiver_Data = 0;

/*********************内部函数************************/ 
static void GUA_Infrared_Receiver_IO_Init(void);
static GUA_U16 GUA_Infrared_Receiver_GetHighLevelTime(void);
static GUA_U16 GUA_Infrared_Receiver_GetLowLevelTime(void);

//******************************************************************************        
//name:             GUA_Infrared_Receiver_IO_Init        
//introduce:        红外接收的IO初始化     
//parameter:        none       
//return:           none      
//author:           甜甜的大香瓜             
//email:            [email protected]         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2016.12.29      
//******************************************************************************  
static void GUA_Infrared_Receiver_IO_Init(void)
{	
	//IO结构体
	GPIO_InitTypeDef GPIO_InitStructure;

	//失能JTAG和SWD在PB3上的功能使用
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
	
	//时钟使能
	RCC_APB2PeriphClockCmd(GUA_INFRARED_RECEIVER_RCC | RCC_APB2Periph_AFIO, ENABLE); 	
	
	//红外接收IO配置
	GPIO_InitStructure.GPIO_Pin = GUA_INFRARED_RECEIVER_PIN;  		
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
	GPIO_Init(GUA_INFRARED_RECEIVER_PORT, &GPIO_InitStructure);	
}

//******************************************************************************            
//name:             GUA_Infrared_Receiver_Exti_Init           
//introduce:        红外接收的IO中断初始化         
//parameter:        none                 
//return:           none         
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.12.29                  
//******************************************************************************
static void GUA_Infrared_Receiver_Exti_Init(void)
{	
	EXTI_InitTypeDef EXTI_InitStructure;

	//中断配置
	EXTI_ClearITPendingBit(GUA_INFRARED_RECEIVER_EXTI_LINE);
	GPIO_EXTILineConfig(GUA_INFRARED_RECEIVER_PORTSOURCE, GUA_INFRARED_RECEIVER_PINSOURCE);  

	EXTI_InitStructure.EXTI_Line = GUA_INFRARED_RECEIVER_EXTI_LINE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
}

//******************************************************************************        
//name:             GUA_Infrared_Receiver_Init        
//introduce:        红外接收初始化     
//parameter:        none       
//return:           none      
//author:           甜甜的大香瓜             
//email:            [email protected]         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2016.12.29     
//******************************************************************************  
void GUA_Infrared_Receiver_Init(void)
{
  //初始化IO
  GUA_Infrared_Receiver_IO_Init();

  //初始化中断配置
	GUA_Infrared_Receiver_Exti_Init();	
}

//******************************************************************************        
//name:             GUA_Infrared_Receiver_GetHighLevelTime        
//introduce:        红外接收获取高电平维持时间   
//parameter:        none       
//return:           nNum:返回20us的个数      
//author:           甜甜的大香瓜             
//email:            [email protected]         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2016.12.29      
//****************************************************************************** 
static GUA_U16 GUA_Infrared_Receiver_GetHighLevelTime(void)
{
	GUA_U16 nGUA_Num = 0;
	
	//判断是否一直为高电平
	while(GPIO_ReadInputDataBit(GUA_INFRARED_RECEIVER_PORT, GUA_INFRARED_RECEIVER_PIN) == Bit_SET)
	{
		//超时超时溢出
		if(nGUA_Num >= 250) 
		{
			return nGUA_Num;
		}
	
		//计延时20us的次数
		nGUA_Num++;
		
		//延时
		GUA_Delay_Us(17);			
	}
	
	return nGUA_Num;
}

//******************************************************************************        
//name:             GUA_Infrared_Receiver_GetLowLevelTime        
//introduce:        红外接收获取低电平维持时间   
//parameter:        none       
//return:           nNum:返回20us的个数       
//author:           甜甜的大香瓜             
//email:            [email protected]         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2016.12.29       
//****************************************************************************** 
static GUA_U16 GUA_Infrared_Receiver_GetLowLevelTime(void)
{
	GUA_U16 nGUA_Num = 0;
	
	//判断是否一直为低电平
	while(GPIO_ReadInputDataBit(GUA_INFRARED_RECEIVER_PORT, GUA_INFRARED_RECEIVER_PIN) == Bit_RESET)
	{
		//超时超时溢出
		if(nGUA_Num >= 500) 
		{
			return nGUA_Num;
		}
	
		//计延时20us的次数
		nGUA_Num++;
		
		//延时
		GUA_Delay_Us(17);			
	}
	
	return nGUA_Num;
}
//******************************************************************************            
//name:             GUA_Infrared_Receiver_Process           
//introduce:        红外接收的处理函数         
//parameter:        none                 
//return:           GUA_INFRARED_RECEIVER_OK or GUA_INFRARED_RECEIVER_ERROR         
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.12.29                   
//******************************************************************************
GUA_U8 GUA_Infrared_Receiver_Process(void)
{
	GUA_U16 nGUA_Time_Num = 0;
	GUA_U8 nGUA_Data = 0;
	GUA_U8 nGUA_Byte_Num = 0;
	GUA_U8 nGUA_Bit_Num = 0;	
	
	//接收引导码9ms的低电平,过滤无用信号>10ms或<8ms
	nGUA_Time_Num = GUA_Infrared_Receiver_GetLowLevelTime();
	if((nGUA_Time_Num >= 500) || (nGUA_Time_Num <= 400))
	{
		return GUA_INFRARED_RECEIVER_ERROR;
	}	
	
	//接收引导码4.5ms的高电平,过滤无用信号>5ms或<4ms
	nGUA_Time_Num = GUA_Infrared_Receiver_GetHighLevelTime();
	if((nGUA_Time_Num >= 250) || (nGUA_Time_Num <= 200))
	{
		return GUA_INFRARED_RECEIVER_ERROR;
	}	
			
	//接收后4字节数据
	for(nGUA_Byte_Num = 0; nGUA_Byte_Num < 4; nGUA_Byte_Num++)
	{
		//接收每字节8位数据
		for(nGUA_Bit_Num = 0; nGUA_Bit_Num < 8; nGUA_Bit_Num++)
		{
			//接收每bit的前0.56ms的低电平,过滤无用信号>1.2ms或<0.40ms
			nGUA_Time_Num = GUA_Infrared_Receiver_GetLowLevelTime();
			if((nGUA_Time_Num >= 60) || (nGUA_Time_Num <= 20))
			{
				return GUA_INFRARED_RECEIVER_ERROR;
			}	

			//接收每bit的后高电平时长:高电平数据,1.68ms(1.2ms~2.0ms),低电平数据,0.56ms(0.2ms~1ms),过滤其他无用信号
			nGUA_Time_Num = GUA_Infrared_Receiver_GetHighLevelTime();
			if((nGUA_Time_Num >=60) && (nGUA_Time_Num < 100))
			{
				nGUA_Data = 1;
			}			
			else if((nGUA_Time_Num >=10) && (nGUA_Time_Num < 50))
			{
				nGUA_Data = 0;
			}
			else
			{
				return GUA_INFRARED_RECEIVER_ERROR;
			}

			//保存数据
			gGUA_InfraredReceiver_Data <<= 1;	
			gGUA_InfraredReceiver_Data |= nGUA_Data;						
		}
	}

	return GUA_INFRARED_RECEIVER_OK;	
}
注意,“GUA_Delay_Us(17);”函数实测为20us左右,我们想要延时的就是20us,因此形参为17。

2)编写驱动头文件GUA_Infrared_Receiver.h(存放在“……\HARDWARE”)

//******************************************************************************              
//name:             GUA_Infrared_Receiver.h             
//introduce:        红外传感器接收驱动的头文件      
//author:           甜甜的大香瓜                     
//email:            [email protected]         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2016.12.29     
//******************************************************************************    
#ifndef _GUA_INFRARED_RECEIVER_H_
#define _GUA_INFRARED_RECEIVER_H_

/*********************宏定义************************/
#ifndef GUA_U8        
typedef unsigned char GUA_U8;        
#endif    

#ifndef GUA_8        
typedef signed char GUA_8;        
#endif      
      
#ifndef GUA_U16        
typedef unsigned short GUA_U16;        
#endif 

#ifndef GUA_16        
typedef signed short GUA_16;        
#endif         
      
#ifndef GUA_U32        
typedef unsigned long GUA_U32;        
#endif 

#ifndef GUA_32        
typedef signed long GUA_32;       
#endif

#ifndef GUA_U64    
typedef unsigned long long GUA_U64;  
#endif

#ifndef GUA_64    
typedef signed long long GUA_64;  
#endif

#define GUA_INFRARED_RECEIVER_OK					0
#define GUA_INFRARED_RECEIVER_ERROR				1

#define GUA_INFRARED_RECEIVER_KEY1				0x00FF00FF
#define GUA_INFRARED_RECEIVER_KEY2				0x00FF01FE
#define GUA_INFRARED_RECEIVER_KEY3				0x00FF02FD
#define GUA_INFRARED_RECEIVER_KEY4				0x00FF03FC

/*********************外部变量************************/
extern GUA_U32 gGUA_InfraredReceiver_Data;

/*********************外部函数声明************************/  
extern void GUA_Infrared_Receiver_Init(void);
extern GUA_U8 GUA_Infrared_Receiver_Process(void);

#endif
由于发送端自定义了四个按键,因此香瓜在这里将这四个按键键值写在这里,此处可自行修改。

3)工程中添加GUA_Infrared_Receiver.c

【STM32】STM32之红外接收_第3张图片


4)在MDK设置中添加驱动源文件路径

【STM32】STM32之红外接收_第4张图片


2、设置NVIC中断优先级(GUA_NVIC.c的GUA_NVIC_Init中

	//红外接收
	GUA_NVIC_Config(NVIC_PriorityGroup_2, EXTI3_IRQn, 2, 2, ENABLE);

3、写中断服务函数(stm32f10x_it.c中)
1)添加头文件

#include "GUA_Infrared_Receiver.h"

2)编写中断服务函数

//******************************************************************************            
//name:             EXTI3_IRQHandler           
//introduce:        红外接收的处理函数        
//parameter:        none                 
//return:           none         
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.11.21                     
//******************************************************************************
void EXTI3_IRQHandler(void)
{
	//红外
  if(EXTI_GetITStatus(EXTI_Line3) != RESET)
  {
		//接收红外数据正确
		if(GUA_Infrared_Receiver_Process() == GUA_INFRARED_RECEIVER_OK)
		{
			function = FUNC_INFRARED_RECEIVER_EVENT;	
		}				
    
    //清除标志位  
    EXTI_ClearITPendingBit(EXTI_Line3);
  }
}

4、在应用层中调用

1)添加头文件(main.c中)

#include "GUA_Infrared_Receiver.h"

2) 添加驱动初始化代码(main.c的main函数中)

	//红外接收初始化
	GUA_Infrared_Receiver_Init();

3) 添加测试代码

①写红外接收处理事件(main.c的main函数中)

          //红外接收处理         
          case FUNC_INFRARED_RECEIVER_EVENT: 
          {
							//键值处理
							switch(gGUA_InfraredReceiver_Data)
							{
								//红外按键1
								case GUA_INFRARED_RECEIVER_KEY1:
								{
									break;
								}

								//红外按键2
								case GUA_INFRARED_RECEIVER_KEY2:
								{
									break;
								}
								
								//红外按键3
								case GUA_INFRARED_RECEIVER_KEY3:
								{
									break;
								}

								//红外按键4
								case GUA_INFRARED_RECEIVER_KEY4:
								{
									break;
								}	

								//其他
								default:
								{
									break;
								}									
							}
							
              //返回空闲状态
              function = FUNC_IDLE_EVENT;               
              break;               
          }

②写红外处理事件宏(main.h中)

//主轮询的宏
#define FUNC_IDLE_EVENT 		              0x00    //空闲
#define FUNC_INFRARED_RECEIVER_EVENT 	              0x16    //红外接收处理


七、注意事项

暂无。


八、实验结果

仿真并设置断点在红外接收处理事件中,全速运行。

当遥控器发送0x00FF00FF的键值时,代码会停止在断点处,并且gGUA_InfraredReceiver_Data的值为0x00FF00FF。



你可能感兴趣的:(STM32)