目录
定时输入捕获(红外遥控密码锁)
红外遥控
NEC编码
-
引导码:
- 包含一个9ms的高电平,后跟一个4.5ms的低电平。
-
数据位:
- 每个数据位由一个560µs的高电平和一个特定时长的低电平组成:
- 逻辑‘0’:560µs高电平 + 560µs低电平
- 逻辑‘1’:560µs高电平 + 1690µs低电平
- 每个数据位由一个560µs的高电平和一个特定时长的低电平组成:
-
重发码:
- 通常以约9ms的低电平 + 2.25ms高电平表示。
cubemx配置
复制工程模板,文件名尽量不取中文
打开cubemx文件并配置
更新文件 ,添加IR.h和IR.c文件
代码实现
IR.h
#ifndef __IR_H__
#define __IR_H__
#include <main.h>
#include "stdio.h"
#define IR_IN1 HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_9) // 定义宏,读取GPIOE口第9引脚的电平状态
uint8_t GetIR_DataFlag(void); // 声明函数,返回数据接收标志
uint8_t GetIR_RepeatFlag(void); // 声明函数,返回重发信号标志
uint8_t GetIR_Address(void); // 声明函数,返回红外地址
uint8_t GetIR_Command(void); // 声明函数,返回红外命令
void IR_Init(void); // 声明函数,用于初始化红外接收
#endif
IR.c
#include "IR.h"
uint8_t IR_State = 0; // 红外接收状态
uint8_t IR_Data[4]; // 存储接收到的数据
uint32_t IR_pData = 0; // 数据位计数器
uint8_t IR_DataFlag = 0; // 数据接收标志
uint8_t IR_RepeatFlag = 0; // 重发信号标志
uint8_t IR_Address = 0; // 存储红外地址
uint8_t IR_Command = 0; // 存储红外命令
extern TIM_HandleTypeDef htim1; // 定义外部定时器句柄
uint8_t GetIR_DataFlag(void) // 获取数据接收标志
{
if(IR_DataFlag) // 如果数据标志为真
{
IR_DataFlag = 0; // 重置数据标志
return 1; // 返回1表示有数据
}
return 0; // 返回0表示没有数据
}
uint8_t GetIR_RepeatFlag(void) // 获取重发信号标志
{
if(IR_RepeatFlag) // 如果重发标志为真
{
IR_RepeatFlag = 0; // 重置重发标志
return 1; // 返回1表示有重发信号
}
return 0; // 返回0表示没有重发信号
}
uint8_t GetIR_Address(void) // 获取红外地址
{
return IR_Address; // 返回当前红外地址
}
uint8_t GetIR_Command(void) // 获取红外命令
{
return IR_Command; // 返回当前红外命令
}
void IR_Init(void) // 初始化红外接收
{
HAL_TIM_Base_Start_IT(&htim1); // 启动定时器基础功能
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1); // 启动输入捕获功能
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) // 定时器输入捕获回调函数
{
uint32_t IR_Time = 0; // 存储捕获到的时间
if(htim->Instance == TIM1) // 判断是否是定时器1的外部捕获口
{
// 捕获到了上升沿
if(IR_IN1) // 如果检测到上升沿
{
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极性为下降沿捕获
__HAL_TIM_SET_COUNTER(htim, 0); // 计数清零,从头开始计
}
else // 检测到下降沿
{
IR_Time = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // 读取捕获计数,这个时间即为上升沿持续的时间
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); // 改变捕获极性为上升沿捕获
if ((IR_Time > 4300) && (IR_Time < 4700)) // 判断4.5ms引导电平
{
IR_State = 1; // 设置状态为1,表示已经接收到引导信号
}
else if (((IR_Time > 2050) && (IR_Time < 2450))) // 判断2.25ms重发电平
{
IR_RepeatFlag = 1; // 设置重发标志
}
if(IR_State) // 如果接收到引导信号
{
if (((IR_Time > 360) && (IR_Time < 860))) // 判断560us数据为0
{
IR_Data[IR_pData / 8] &= ~(0x01 << IR_pData % 8); // 清除对应位
IR_pData++; // 计数器加1
}
else if (((IR_Time > 1490) && (IR_Time < 1990))) // 判断1690us数据为1
{
IR_Data[IR_pData / 8] |= (0x01 << IR_pData % 8); // 设置对应位
IR_pData++; // 计数器加1
}
if(IR_pData >= 32) // 如果接收到32位数据
{
IR_pData = 0; // 重置数据位计数器
IR_State = 0; // 重置状态
if((IR_Data[0] == (uint8_t)~IR_Data[1]) && (IR_Data[2] == (uint8_t)~IR_Data[3])) // 校验数据
{
IR_Address = IR_Data[0]; // 存储地址
IR_Command = IR_Data[2]; // 存储命令
IR_DataFlag = 1; // 设置数据接收标志
}
}
}
}
}
}
测试,添加OLED进来验证
main.c添加头文件
#include "IR.h"
#include "OLED.h"
添加变量
uint32_t Address = 0;
uint32_t Command = 0;
初始化
OLED_Init();
OLED_Clear(0);
IR_Init();
/* USER CODE BEGIN WHILE */
while (1)
{
if(GetIR_DataFlag()|| GetIR_RepeatFlag())
{
Address = GetIR_Address();
Command = GetIR_Command();
OLED_Clear(0);
OLED_ShowNum(0,0,Address,2,16);
OLED_ShowNum(0,2,Command,2,16);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
密码锁
0-22
1-12 2-24 3-94
4-8 5-28 6-90
7-66 8-82 9-74
确认(45)-69
删除(44)-68
归零(07)-7
代码实现
while (1)
{
if(GetIR_DataFlag())//不要重发部分|| GetIR_RepeatFlag()
{
Address = GetIR_Address();
Command = GetIR_Command();
if(Command == 22)//0
{
numflag = 1;
Keynum = 0;
}
else if(Command == 12)//1
{
numflag = 1;
Keynum = 1;
}
else if(Command == 24)//2
{
numflag = 1;
Keynum = 2;
}
else if(Command == 94)//3
{
numflag = 1;
Keynum = 3;
}
else if(Command == 8)//4
{
numflag = 1;
Keynum = 4;
}
else if(Command == 28)//5
{
numflag = 1;
Keynum = 5;
}
else if(Command == 90)//6
{
numflag = 1;
Keynum = 6;
}
else if(Command == 66)//7
{
numflag = 1;
Keynum = 7;
}
else if(Command == 82)//8
{
numflag = 1;
Keynum = 8;
}
else if(Command == 74)//9
{
numflag = 1;
Keynum = 9;
}
if(numflag)//密码
{
numflag = 0;
if(count<4)
{
password *= 10;
password += Keynum%10;
count++;
}
OLED_Clear(0);
OLED_ShowString(0,0,(uint8_t *)"password",16);
OLED_ShowNum(0,2,password,4,16);
}
if(Command == 69)//确认
{
if(password==1314)//密码正确
{
password=0;
count=0;
OLED_Clear(0);
OLED_ShowCHinese(0,0,0);
OLED_ShowCHinese(16,0,1);
}
else//密码错误
{
password=0;
count=0;
OLED_Clear(0);
OLED_ShowString(0,0,(uint8_t *)"error",16);
}
}
if(Command == 68)//取消
{
password -=(password%10);
password /=10;
count--;
OLED_Clear(0);
OLED_ShowString(0,0,(uint8_t *)"password",16);
OLED_ShowNum(0,2,password,4,16);
}
if(Command == 7)//归零
{
password=0;
count=0;
OLED_Clear(0);
OLED_ShowString(0,0,(uint8_t *)"password",16);
OLED_ShowNum(0,2,password,4,16);
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}