因为网上资料很多,本人在这里只是记录自己学习的过程。具体内容可以参考其他大神的文章。

红外的收发其实和光耦原理差不多。发射端收到数据,发红外光,接收端收到光信号也开始导通,采集Rx信号即可知道发来的数据。电路原理图如下:

红外解码协议有好多种:有ITT协议、NEC协议、NokiaNRC协议、Sharp协议、SonySIRC协议、PhilipSRC-5协议、PhilipsRC-6协议,等等,此处使用NEC协议。

简单介绍NEC协议;

数据1是560us的低电平,然后再1680us的高电平,周期是2.24ms。数据0是560us的低电平,然后再560us的高电平,周期是1.20ms;

引导码:9ms的低电平,然后在4.5ms的高电平。  重复发数据:9ms的低电平,然后在2.25ms的高电平

NEC的数据格式如下:1、引导码(9+4.5ms);2、地址码;3、地址反码;4、数据码;5、数据反码;6、结束码(可以加可以不加)

为了说明清楚,用简易的图片来描述,A之间的距离大小对应是发送0,还是发送1.(其实阴影部分的时间都是一样的,0和1取决于剩下的部分),发送和接收的电平状态是反着的。与原理图可知。接收解析时只需要关心 B的大小即可区分0还是1。即在捕获电平时只需要捕获高电平即可。

NEC原理简单介绍完了。讲下程序的工作原理。

利用两个定时器,TIM3用来产生PWM,用来做红外的发送载波,一般用38khz, TIM5用来捕获TIM3产生的“”波形”.并从中解析收到的数据。

为什么用38khz,市面上卖的红外接收头大部分是接收38KHZ红外信号的,还有就是38KHZ的940nm波长的红外线可以很好的避免其他光的干扰。

产生38khz的方波就需要配置定时器周期为26us(f=1/T,剩下自己算,注意单位转换)。 TIM_SetCompare4(TIM3,9)//占空比1/3。

发送逻辑0和1,需要us定时器,我用的是TIM2。

void Delay_Timer_Init(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Down;TIM_TimeBaseInitStruct.TIM_Period = 100 - 1;TIM_TimeBaseInitStruct.TIM_Prescaler = (84 - 1);TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);while ((TIM2->SR & TIM_FLAG_Update) != SET);TIM2->SR = (uint16_t)~TIM_FLAG_Update;
}
void Delay_us(uint32_t us_cnt)
{TIM2->CNT = us_cnt - 1;TIM2->CR1 |= TIM_CR1_CEN;while ((TIM2->SR & TIM_FLAG_Update) != SET);TIM2->SR = (uint16_t)~TIM_FLAG_Update;TIM2->CR1 &= ~TIM_CR1_CEN;}

用示波器测试过,10us有3us的误差。所以在接收载波的解析时,判断是逻辑0和1,判断高电平的时间要增大范围。

#define NO_CARRIER() TIM_SetCompare4(TIM3,0)
#define NEC_HEAD        (u16)(4500) //引导码
#define NEC_ZERO        (u16)(560)  //代表0
#define NEC_ONE         (u16)(1680) //代表1
#define NEC_CONTINUE    (u16)(2500)#define NEC_HEAD_MIN (u16)(NEC_HEAD*1.0f) //4500
#define NEC_HEAD_MAX (u16)(NEC_HEAD*1.4f) //6300#define NEC_ZERO_MIN (u16)(NEC_ZERO*0.7f)
#define NEC_ZERO_MAX (u16)(NEC_ZERO*1.5f)#define NEC_ONE_MIN (u16)(NEC_ONE*0.7f)
#define NEC_ONE_MAX (u16)(NEC_ONE*1.3f)

附上一张定时器配置通道和引脚分布的截图

数据解析原理:在定时器中断里面检测是否有捕获中断,(定时器初始化时候设置为上升沿触发),当捕获到上升沿时,做标记,清定时计数,然后设置为下降沿,当再次捕获到数据时,读出计数器的值。同时设置为上升沿,为下次捕获高电平做准备。计数器的值就是两次捕获到的一个高电平的时间,通过前面手绘那个图,捕获到到的高电平的时间就是B的长度,根据NEC协议,由时间长短来判断捕获到的是引导码还是逻辑0还是逻辑1.(接收到的逻辑0和1的时间和发送的相反,切记),只有在收到引导码的前提下,才能对数据的内容解析,要不然解析的也是错的。解析完数据,还要解析到结束码,如果没有解析到结束码,这个数据可能是错的,结束码是这一帧数据全部收到的标志(有点像是CRC校验和)。

如何实现人体感应。红外接收,发射分开放置,当人靠近的时候,人把发射的信号反射到接收上面去。当接收到的数据和发射的一致,说明有人靠近了。反之,没人靠近,那就不会接收到数据。

这个项目最恶心有点是,捕获中断设置的是上升沿触发,由红外的原理图可知当没收到数据的时候采集电压那个脚一直是高电平,就会一直进入中断。造成采集高电平的时间有时会出现几us的杂波。因此还需要对这个杂波进行过滤。因为这点被卡了3天,特地写下来记录下。最后送佛送到西,附上完整程序(亲测可用)就不上传了赚积分了,不道德,省的没积分的童鞋蓝瘦。

#include "IR.h"
#include "BSP_CFG.h"
#include "Setup.h"//用到延迟函数(自己写一个吧)u8 DelayNus = 0;
#define CARRIER_38KHz() TIM_SetCompare4(TIM3,9)//设置PWM占空比.初始化周期27us。//第二个参数是输出PWM的高电平的时间  第4通道  PB1输出高电平9us。f=1/T= 0.0370。//周期转化为秒也就是37khz
#define NO_CARRIER()    TIM_SetCompare4(TIM3,0)
#define NEC_HEAD        (u16)(4500) //引导码
#define NEC_ZERO        (u16)(560)  //代表0
#define NEC_ONE         (u16)(1680) //代表1
#define NEC_CONTINUE    (u16)(2500)#define NEC_HEAD_MIN (u16)(NEC_HEAD*1.0f) //4500
#define NEC_HEAD_MAX (u16)(NEC_HEAD*1.4f) //6300#define NEC_ZERO_MIN (u16)(NEC_ZERO*0.7f)
#define NEC_ZERO_MAX (u16)(NEC_ZERO*1.5f)#define NEC_ONE_MIN (u16)(NEC_ONE*0.7f)
#define NEC_ONE_MAX (u16)(NEC_ONE*1.3f)#define NEC_CONTINUE_MIN (u16)(NEC_CONTINUE*1.0f)
#define NEC_CONTINUE_MAX (u16)(NEC_CONTINUE*1.3f)#define  NEC_RX_RCC      RCC_APB2Periph_GPIOA
#define  NEC_TX_RCC      RCC_APB2Periph_GPIOA#define  NEC_RX_PIN      GPIO_Pin_2//检测电平输入
#define  NEC_TX_PIN      GPIO_Pin_1//电平输出#define  NEC_RX_PORT     GPIOA
#define  NEC_TX_PORT     GPIOB#define NEC_TIMER3_PWM_PERIOD              (72 - 1)
#define NEC_TIMER5_PERIOD                (72 - 1)struct  NEC_DATA  NEC_Data;//输入捕获的一般配置步骤:
//初始化定时器和通道对应IO的时钟。
//初始化IO口,模式为输入,下拉模式:GPIO_Init(); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
//初始化定时器ARR,PSC:TIM_TimeBaseInit();
//初始化输入捕获通道:TIM_ICInit();
//如果要开启捕获中断:TIM_ITConfig(); NVIC_Init();
//使能定时器: TIM_Cmd();
//编写中断服务函数: TIMx_IRQHandler();
//输入捕获整体初始化函数(含步骤1-6)//**************************************接收部分**************************//
//红外遥控接收初始化 利用定时器5      PA1脚  捕获
void NEC_RX_Configuration(void)
{GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_ICInitTypeDef TIM_ICInitStructure; //输入捕获RCC_APB2PeriphClockCmd(NEC_RX_RCC, ENABLE); //使能PORT时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);  //TIM5 时钟使能GPIO_InitStructure.GPIO_Pin = NEC_RX_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;        // 下拉输入:平时就是0GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(NEC_RX_PORT, &GPIO_InitStructure);    //PA1--CH2//初始化定时器5 TIM5TIM_TimeBaseStructure.TIM_Period = 50000; //设定计数器自动重装值 最大50ms溢出TIM_TimeBaseStructure.TIM_Prescaler = NEC_TIMER5_PERIOD;    //预分频器,1M的计数频率,1us加1.  记一个数的时间T=1/f=1/1M=1usTIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx//初始化TIM5输入捕获参数TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;  // 选择输入端 IC3映射到TI3上TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;    //配置输入分频,不分频 检测了几个上升沿(或者下降沿)才产生一次中断TIM_ICInitStructure.TIM_ICFilter = 0x03; //IC3F=0000 配置输入滤波器 不滤波//IC3F=0011 配置输入滤波器 8个定时器时钟周期滤波TIM_ICInit(TIM5, &TIM_ICInitStructure); //初始化定时器输入捕获通道//中断优先级在别的函数一起初始化了,需要自己移植过来TIM_ITConfig(TIM5, TIM_IT_Update | TIM_IT_CC3, ENABLE); //允许更新中断 ,使能CC2IE捕获中断TIM_ARRPreloadConfig(TIM5, ENABLE);  //重装载TIM_Cmd(TIM5, ENABLE);  //使能定时器5
}//**************************************发送部分**************************//
void NEC_TX_Configuration(void)     //红外传感器接收头引脚初始化 定时器3  PB1  CH4
{GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;             //输出比较RCC_APB2PeriphClockCmd(NEC_TX_RCC, ENABLE);          //使能PORT时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //TIM3 时钟使能GPIO_InitStructure.GPIO_Pin = NEC_TX_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     //复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(NEC_TX_PORT, &GPIO_InitStructure);TIM_Cmd(TIM3, DISABLE);TIM_ITConfig(TIM3, TIM_IT_Update | TIM_IT_CC4, DISABLE);           //关闭TIM3中断//不分频,PWM 频率=72000/1894=38Khz//设置自动重装载寄存器周期的值                                                                //当发送器发送高电平时,实际上发送的是38khz的载波,也就是周期约为26.31us 占空比为1/3(或1/4,有时候可以2/3)的波TIM_TimeBaseStructure.TIM_Period = 27; //原来27                          //设定计数器自动重装值 最大27us溢出TIM_TimeBaseStructure.TIM_Prescaler = NEC_TIMER3_PWM_PERIOD;                        //预分频器,1M的计数频率,1us加1.TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;         //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;     //TIM向上计数模式TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;             //设置PWM1模式TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输出使能TIM_OCInitStructure.TIM_Pulse = 0;   // 占空比                //设置捕获比较寄存器的值TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;     //设置有效电平为高电平TIM_OC4Init(TIM3, &TIM_OCInitStructure);                      //生效初始化设置TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);             //使能输出比较预装载TIM_Cmd(TIM3, ENABLE);
}void Delay_Timer_Init(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Down;TIM_TimeBaseInitStruct.TIM_Period = 100 - 1;TIM_TimeBaseInitStruct.TIM_Prescaler = (84 - 1);TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);while ((TIM2->SR & TIM_FLAG_Update) != SET);TIM2->SR = (uint16_t)~TIM_FLAG_Update;
}
void Delay_us(uint32_t us_cnt)
{TIM2->CNT = us_cnt - 1;TIM2->CR1 |= TIM_CR1_CEN;while ((TIM2->SR & TIM_FLAG_Update) != SET);TIM2->SR = (uint16_t)~TIM_FLAG_Update;TIM2->CR1 &= ~TIM_CR1_CEN;}void TIM5_IRQHandler(void)
{//超时没捕获到,发送中断if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)  //更新中断{GPIO_SetBits(GPIOA, GPIO_Pin_8); //led灭}if (TIM_GetITStatus(TIM5, TIM_IT_CC3) != RESET) //捕获1发生捕获事件{NEC_Data.flag = 1;if (0x00 == NEC_Data.TIM5CH1_CAPTURE_STA)          // 空闲状态{NEC_Data.TIM5CH1_CAPTURE_STA = 0x01;       //标记捕获到一个上降沿NEC_Data.TIM5CH1_CAPTURE_VAL = 0;          //计时时间清0TIM_SetCounter(TIM5, 0);TIM_OC3PolarityConfig(TIM5, TIM_ICPolarity_Falling);     //CC1P=1 设置为下降沿捕获}else if (0x01 == NEC_Data.TIM5CH1_CAPTURE_STA)   //在捕获到一个上升沿前提下,如果再捕获下降沿  ,说明捕获到了高电平{NEC_Data.TIM5CH1_CAPTURE_VAL = TIM_GetCapture3(TIM5); //获取捕获高电平时间NEC_Data.TIM5CH1_CAPTURE_STA_H = 0x01; //标记捕获到一个高电平 if(  TIM5CH1_CAPTURE_VAL>300  )TIM_OC3PolarityConfig(TIM5, TIM_ICPolarity_Rising); //CC2P=0 设置为上升沿捕获 准备捕获上升沿}}if (NEC_Data.TIM5CH1_CAPTURE_STA_H == 0x01) //如果捕获到一个高电平,判断是否前导码,是前导码。跳出去,{NEC_Data.TIM5CH1_CAPTURE_STA_H = 0x00;   //不是前导码,判断是否已经捕到前导码,是:判断数据正确性,不是,跳出去if (NEC_Data.TIM5CH1_CAPTURE_STA_Head == 0x01) //只有接收到了引导码之后得到的才是数据{if (NEC_Data.TIM5CH1_CAPTURE_VAL > NEC_ZERO_MIN && NEC_Data.TIM5CH1_CAPTURE_VAL < NEC_ZERO_MAX)  //560为标准值,560us min=392 max=728               实际值为0.68ms{//红外接收到的数据:0NEC_Data.RmtRec <<= 1;                 //左移一位.NEC_Data.RmtRec |= 0;                  //接收到0}else if (NEC_Data.TIM5CH1_CAPTURE_VAL > NEC_ONE_MIN && NEC_Data.TIM5CH1_CAPTURE_VAL < NEC_ONE_MAX)  //1680为标准值,1680us min=1.176ms max=2.148ms    实际值为1.96ms{//红外接收到的数据:1NEC_Data.RmtRec <<= 1;                 //左移一位.NEC_Data.RmtRec |= 1;                  //接收到1}else if (300 < NEC_Data.TIM5CH1_CAPTURE_VAL && NEC_Data.TIM5CH1_CAPTURE_VAL < 8800)      //得到按键键值增加的信息 2500为标准值2.5ms{NEC_Data.TIM5CH1_CAPTURE_RecFlag = 0x01;NEC_Data.TIM5CH1_CAPTURE_STA_Head = 0x00; //准备接受下一帧数据}}else if (NEC_Data.TIM5CH1_CAPTURE_VAL > NEC_HEAD_MIN && NEC_Data.TIM5CH1_CAPTURE_VAL < NEC_HEAD_MAX)       //4500为标准值4.5ms  实测5773 //4500 -6300{NEC_Data.TIM5CH1_CAPTURE_STA_Head = 0x01;  //标记成功接收到了引导码//跳出去,等待下一个高电平}NEC_Data.TIM5CH1_CAPTURE_STA = 0x00;                    //空闲状态}TIM_ClearITPendingBit(TIM5, TIM_IT_Update | TIM_IT_CC3);  //清除中断标志位
}void NEC_GetValue(u8 *addr, u16 *value)
{u8 t1, t2;*addr = 0;*value = 0;if (NEC_Data.TIM5CH1_CAPTURE_RecFlag == 0x01)    //接收到一个数据{NEC_Data.TIM5CH1_CAPTURE_RecFlag = 0x00;t1 = NEC_Data.RmtRec >> 24;             //得到地址码t2 = (NEC_Data.RmtRec >> 16) & 0xff;    //得到地址反码if (t1 == (u8)~t2)             //检验遥控识别码(ID)及地址{*addr = t1;t1 = 0;t2 = 0;}else{*addr = 0; }t1 = (NEC_Data.RmtRec >> 8) & 0xff;  //得到数据t2 = NEC_Data.RmtRec & 0xff;         //得到数据反码if (t1 == (u8)~t2)           //检验数据码及数据反码{*value = t1;}else{*value = 0; }NEC_Data.RmtRec = 0;}
}//一个逻辑0的传输需要 1.125ms(560us载波+560us空闲)。
static void NEC_Send_0(void)
{CARRIER_38KHz();    //比较值为1/3载波Delay_us(560);NO_CARRIER();   //不载波Delay_us(560);}
//一个逻辑1传输需要2.25ms(560us载波+1680us空闲)
static void NEC_Send_1(void)
{CARRIER_38KHz();    //比较值为1/3载波Delay_us(560);NO_CARRIER();   //不载波Delay_us(1680);}
//NEC协议格式://引导码:发送一个9ms载波的引导码,之后是4.5ms的空闲,
static void NEC_Send_Head(void)
{CARRIER_38KHz();Delay_us(9000);        //  实际10.56ms    10us实际13usNO_CARRIER();   //不载波            0Delay_us(4500);          // 实际接收时间在5.24ms}
//结束码(自己加的)
static void NEC_Send_Tail(void)
{CARRIER_38KHz();Delay_us(200);NO_CARRIER();Delay_us(300);    //   2.5<3ms<3.3ms}
//发送一字节数据
static void NEC_Send_BYTE(u8 value)
{u8 i;for (i = 0; i < 8; i++){if (value & 0x80){NEC_Send_1();}else{NEC_Send_0();}value <<= 1;}}
static void NEC_Send_Repeat(u8 count)
{u8 i = 0;if (count == 0)          //如果没有重复码就直接设置无载波,发射管进行空闲状态{NEC_Send_Tail();}else{for (i; i < count; i++){CARRIER_38KHz();Delay_us(9000);NO_CARRIER();Delay_us(2250);}}}
//后发送16位地址码(18ms36ms)、8位数据码(9ms18ms)以及8为数据反码。
//(第二个108ms)如果接下来发射重复的数据,可以先发送9ms载波,空闲2.5ms,
//再发射0.56ms载波即可,注意每次发射的间隔时间。
void NEC_Send(u8 addr, u8 value, u8 cnt){NEC_TX_Configuration();NEC_RX_Configuration();NEC_Send_Head();                //发送起始码NEC_Send_BYTE(addr);            //发送地址码HNEC_Send_BYTE(~addr);           //发送地址码LNEC_Send_BYTE(value);           //发送命令码HNEC_Send_BYTE(~value);          //发送命令码LNEC_Send_Repeat(cnt);           //发送重复码}
void HW_Init(void)
{NEC_TX_Configuration();NEC_RX_Configuration();
}//定时器3中断服务程序
void TIM3_IRQHandler(void)
{if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {} //更新中断TIM_ClearITPendingBit(TIM3, TIM_IT_Update | TIM_IT_CC3);  //清除中断标志位
}void  IR_Sensor(u8 Data)
{u16 data[1];u8 addr[1];NEC_Send(0xff, Data, 0);NEC_GetValue(addr, data);if (*data == Data){GPIO_ResetBits(GPIOA, GPIO_Pin_8); //led亮灯}}
#ifndef __IR_H
#define __IR_H
#include "BSP_CFG.h"//位带操作,实现51类似的GPIO控制功能
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入
#define RDATA   PAin(1)     //红外数据输入脚struct NEC_DATA
{u32 RmtRec  ;                   //红外接收到的数据
u8 TIM5CH1_CAPTURE_STA  ;         //输入捕获状态
u8 TIM5CH1_CAPTURE_STA_H  ;       //捕获到一个高电平
u8 TIM5CH1_CAPTURE_STA_Head  ;    //捕获到一个引导码
u8 TIM5CH1_CAPTURE_RecFlag ;
u16 TIM5CH1_CAPTURE_VAL;          //输入捕获值
u8 flag ;}   ;extern void IR_Sensor(u8 Data);
extern void HW_Init(void);
void Delay_Timer_Init(void);
#endif

基于STM32的利用红外收发机制的人体感应设计相关推荐

  1. 2个相同的 stm32 can通讯不成功_一文读懂,基于 STM32 和 CAN 总线的温度监控系统的设计方法...

    1 系统总体方案概述 系统总体框图如图 1 所示,本系统采用主站+从站的结构,CAN 主站主要实现温度数据的存储以及 CAN 总线协议和串口协议之间的桥接,CAN 从站主要实现温度的采集.CAN 从站 ...

  2. 基于STM32单片机智能RFID刷卡汽车位锁设计(论文

    基于STM32单片机智能RFID刷卡汽车位锁设计(论文) 摘要 在车位日益紧张的今天,如何避免私家车位被他人抢占,是令人头痛的事.日前面市的一种新型车位锁,不仅有效解决了这一问题,还可对车辆起到防盗作 ...

  3. 基于STM32单片机智能RFID刷卡汽车位锁设计(开题报告)

    基于STM32单片机智能RFID刷卡汽车位锁设计(开题报告) 文章目录 基于STM32单片机智能RFID刷卡汽车位锁设计(开题报告) 一.课题的背景及意义 二.国内外研究状况: 三.系统功能分析及体系 ...

  4. 双足竞走机器人的意义_基于STM32双足竞步机器人的研究与设计

    龙源期刊网 http://www.qikan.com.cn 基于 STM32 双足竞步机器人的研究与设计 作者:卢士林 李彩霞 张奎庆 段忠臣 来源:<智能计算机与应用> 2016 年第 ...

  5. 基于STM32蓝牙智能手环脉搏心率计步器体温显示设计

    基于STM32蓝牙智能手环脉搏心率计步器体温显示设计 本设计由STM32F103C8T6单片机核心板电路+ADXL345传感器电路+心率传感器电路+温度传感器+lcd1602电路组成. 1.通过重力加 ...

  6. 基于STM32单片机智能手环脉搏心率计步器体温显示设计

    " 基于STM32单片机智能手环脉搏心率计步器体温显示设计." (获取方式:在"智能车杂谈"微信回复:009). 01 材料准备 清单列表 1.ADXL345模 ...

  7. 基于STM32的万能红外遥控器

    本博客介绍一种基于STM32的可学习和存储已有红外发射设备的万能红外遥控器的设计思路. 一.首先需要了解设计一款这功能的遥控器需要什么硬件设备支持. 1.3.3V,5V电源模块,用作给系统模块供电和单 ...

  8. linux红外驱动程序,基于Linux操作系统和红外发射器实现系统模块的设计

    引 言 随着嵌入式系统及集成电路技术的飞速发展,针对移动手持终端的专用芯片获得了长足发展.芯片的RAM和ROM的容量越大,在上面跑操作系统也越来越容易.Linux是当今流行的操作系统之一.由于其内核健 ...

  9. 基于STM32的光敏传感器数据采集系统-嵌入式系统与设计课程设计

    目录 1 项目概述 1.1 项目介绍 1.2 项目开发环境 1.3 小组人员及分工 2 需求分析 2.1 系统需求分析 2.2 可行性分析 2.3 项目实施安排 3 系统硬件设计 3.1 系统整体硬件 ...

最新文章

  1. mysql主从复制的简单配置
  2. 强化学习(六)---基于无模型强化学习方法
  3. 人工智能与主体时代变革
  4. 破烂微软的.NET IDE环境
  5. mac系统如何进入系统偏好设置_MacOS Big Sur 系统偏好设置无法解锁Bug解决
  6. python print(len(pi_string))_Python如何从文件中读取数据
  7. thinkphp 同时更新多条数据
  8. 使用 VMware vRealize Automation 6.2.1 中的 Remote Console (VMRC) 选项连接到资源失败,并显示以下错误: 无法建立远程控制台连接
  9. java基础之ArrayLis类
  10. 哪吒2之大闹东海电影项目亮点怎么样?
  11. Java多线程,并发核心知识体系总结
  12. iOS-事件响应链、单例模式、工厂模式、观察者模式
  13. 考研英语不熟悉的词义(List1-List5)
  14. 313day(服务器的一些问题)
  15. 阿里妈妈智能诊断工程能力建设
  16. C4D R25 UV的展开与导出
  17. “穷人思维”和“富人思维”有什么区别?
  18. 计算机图形学 | 基于MFC和二维变换的画图软件
  19. Unity Animation Instancing 官方解决方案初试
  20. Java基础——Day23——Lock和TCP传输

热门文章

  1. Unity中的Shuriken粒子系统(3)
  2. Maven Plugins报红的一个重大原因可能导致无法导入依赖
  3. hoj 2662 Pieces Assignment
  4. 如何开发一个对账系统
  5. mysql doen s exist_Mysql中大小写敏感问题导致的MySql Error 1146 Tabel doen’t exist错误_MySQL...
  6. POJ-1416-Shredding Company
  7. uniapp卡片式轮播图——uView
  8. 亿级流量电商详情页系统实战-38.hystrix与高可用系统架构:资源隔离+限流+熔断+降级+运维监控
  9. 为什么32位计算机只能够使用4G内存
  10. 2019杭电多校第9场1002 Rikka with Cake HDU6681