【【51单片机11.0592晶振红外遥控】】

51单片机11.0592晶振红外遥控

红外遥控,51单片机完结

在这里插入图片描述
这是初步实现的架构
怎么实现内部的详细逻辑
我们用状态机的方法

0状态时一个空闲状态 当它接收到下降沿开始计时然后转为1状态
1状态下 寻找start 或者repeat的信号 再来下降沿读出定时器的值 如果是start 那就进入2状态开始译码
如果repeat 那么重发标志位 重新切回去
我每次进入2状态会连续进行32次计算出 0 1 之间的时间差
存到data变量缓存区告诉指示我们存到了第几位 每存一次我们需要去判断
然后验证
最后收到数据 切换回 0

Delay.c

void Delay(unsigned int xms)
{unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}
}

Delay.h

#ifndef __DELAY_H__
#define __DELAY_H__void Delay(unsigned int xms);#endif

Int0.c

#include <REGX52.H>/*** @brief  外部中断0初始化* @param  无* @retval 无*/
void Int0_Init(void)
{IT0=1;IE0=0;EX0=1;EA=1;PX0=1;
}/*外部中断0中断函数模板
void Int0_Routine(void) interrupt 0
{}
*/

Int0.h

#ifndef __INT0_H__
#define __INT0_H__void Int0_Init(void);#endif

IR.c

#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"unsigned int IR_Time;
unsigned char IR_State;unsigned char IR_Data[4];
unsigned char IR_pData;unsigned char IR_DataFlag;
unsigned char IR_RepeatFlag;
unsigned char IR_Address;
unsigned char IR_Command;/*** @brief  红外遥控初始化* @param  无* @retval 无*/
void IR_Init(void)
{Timer0_Init();Int0_Init();
}/*** @brief  红外遥控获取收到数据帧标志位* @param  无* @retval 是否收到数据帧,1为收到,0为未收到*/
unsigned char IR_GetDataFlag(void)
{if(IR_DataFlag){IR_DataFlag=0;return 1;}return 0;
}/*** @brief  红外遥控获取收到连发帧标志位* @param  无* @retval 是否收到连发帧,1为收到,0为未收到*/
unsigned char IR_GetRepeatFlag(void)
{if(IR_RepeatFlag){IR_RepeatFlag=0;return 1;}return 0;
}/*** @brief  红外遥控获取收到的地址数据* @param  无* @retval 收到的地址数据*/
unsigned char IR_GetAddress(void)
{return IR_Address;
}/*** @brief  红外遥控获取收到的命令数据* @param  无* @retval 收到的命令数据*/
unsigned char IR_GetCommand(void)
{return IR_Command;
}//外部中断0中断函数,下降沿触发执行
void Int0_Routine(void) interrupt 0
{if(IR_State==0)				//状态0,空闲状态{Timer0_SetCounter(0);	//定时计数器清0Timer0_Run(1);			//定时器启动IR_State=1;				//置状态为1}else if(IR_State==1)		//状态1,等待Start信号或Repeat信号{IR_Time=Timer0_GetCounter();	//获取上一次中断到此次中断的时间Timer0_SetCounter(0);	//定时计数器清0//如果计时为13.5ms,则接收到了Start信号(判定值在12MHz晶振下为13500,在11.0592MHz晶振下为12442)if(IR_Time>12442-500 && IR_Time<12442+500){IR_State=2;			//置状态为2}//如果计时为11.25ms,则接收到了Repeat信号(判定值在12MHz晶振下为11250,在11.0592MHz晶振下为10368)else if(IR_Time>10368-500 && IR_Time<10368+500){IR_RepeatFlag=1;	//置收到连发帧标志位为1Timer0_Run(0);		//定时器停止IR_State=0;			//置状态为0}else					//接收出错{IR_State=1;			//置状态为1}}else if(IR_State==2)		//状态2,接收数据{IR_Time=Timer0_GetCounter();	//获取上一次中断到此次中断的时间Timer0_SetCounter(0);	//定时计数器清0//如果计时为1120us,则接收到了数据0(判定值在12MHz晶振下为1120,在11.0592MHz晶振下为1032)if(IR_Time>1032-500 && IR_Time<1032+500){IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8));	//数据对应位清0IR_pData++;			//数据位置指针自增}//如果计时为2250us,则接收到了数据1(判定值在12MHz晶振下为2250,在11.0592MHz晶振下为2074)else if(IR_Time>2074-500 && IR_Time<2074+500){IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));	//数据对应位置1IR_pData++;			//数据位置指针自增}else					//接收出错{IR_pData=0;			//数据位置指针清0IR_State=1;			//置状态为1}if(IR_pData>=32)		//如果接收到了32位数据{IR_pData=0;			//数据位置指针清0if((IR_Data[0]==~IR_Data[1]) && (IR_Data[2]==~IR_Data[3]))	//数据验证{IR_Address=IR_Data[0];	//转存数据IR_Command=IR_Data[2];IR_DataFlag=1;	//置收到连发帧标志位为1}Timer0_Run(0);		//定时器停止IR_State=0;			//置状态为0}}
}

IR.h

#ifndef __IR_H__
#define __IR_H__#define IR_POWER		0x45
#define IR_MODE			0x46
#define IR_MUTE			0x47
#define IR_START_STOP	0x44
#define IR_PREVIOUS		0x40
#define IR_NEXT			0x43
#define IR_EQ			0x07
#define IR_VOL_MINUS	0x15
#define IR_VOL_ADD		0x09
#define IR_0			0x16
#define IR_RPT			0x19
#define IR_USD			0x0D
#define IR_1			0x0C
#define IR_2			0x18
#define IR_3			0x5E
#define IR_4			0x08
#define IR_5			0x1C
#define IR_6			0x5A
#define IR_7			0x42
#define IR_8			0x52
#define IR_9			0x4Avoid IR_Init(void);
unsigned char IR_GetDataFlag(void);
unsigned char IR_GetRepeatFlag(void);
unsigned char IR_GetAddress(void);
unsigned char IR_GetCommand(void);#endif

LCD1602.c

#include <REGX52.H>//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0//函数定义:
/*** @brief  LCD1602延时函数,12MHz调用可延时1ms* @param  无* @retval 无*/
void LCD_Delay()
{unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i);
}/*** @brief  LCD1602写命令* @param  Command 要写入的命令* @retval 无*/
void LCD_WriteCommand(unsigned char Command)
{LCD_RS=0;LCD_RW=0;LCD_DataPort=Command;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief  LCD1602写数据* @param  Data 要写入的数据* @retval 无*/
void LCD_WriteData(unsigned char Data)
{LCD_RS=1;LCD_RW=0;LCD_DataPort=Data;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief  LCD1602设置光标位置* @param  Line 行位置,范围:1~2* @param  Column 列位置,范围:1~16* @retval 无*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{if(Line==1){LCD_WriteCommand(0x80|(Column-1));}else if(Line==2){LCD_WriteCommand(0x80|(Column-1+0x40));}
}/*** @brief  LCD1602初始化函数* @param  无* @retval 无*/
void LCD_Init()
{LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动LCD_WriteCommand(0x01);//光标复位,清屏
}/*** @brief  在LCD1602指定位置上显示一个字符* @param  Line 行位置,范围:1~2* @param  Column 列位置,范围:1~16* @param  Char 要显示的字符* @retval 无*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{LCD_SetCursor(Line,Column);LCD_WriteData(Char);
}/*** @brief  在LCD1602指定位置开始显示所给字符串* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  String 要显示的字符串* @retval 无*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=0;String[i]!='\0';i++){LCD_WriteData(String[i]);}
}/*** @brief  返回值=X的Y次方*/
int LCD_Pow(int X,int Y)
{unsigned char i;int Result=1;for(i=0;i<Y;i++){Result*=X;}return Result;
}/*** @brief  在LCD1602指定位置开始显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:0~65535* @param  Length 要显示数字的长度,范围:1~5* @retval 无*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');}
}/*** @brief  在LCD1602指定位置开始以有符号十进制显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:-32768~32767* @param  Length 要显示数字的长度,范围:1~5* @retval 无*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{unsigned char i;unsigned int Number1;LCD_SetCursor(Line,Column);if(Number>=0){LCD_WriteData('+');Number1=Number;}else{LCD_WriteData('-');Number1=-Number;}for(i=Length;i>0;i--){LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');}
}/*** @brief  在LCD1602指定位置开始以十六进制显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:0~0xFFFF* @param  Length 要显示数字的长度,范围:1~4* @retval 无*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i,SingleNumber;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){SingleNumber=Number/LCD_Pow(16,i-1)%16;if(SingleNumber<10){LCD_WriteData(SingleNumber+'0');}else{LCD_WriteData(SingleNumber-10+'A');}}
}/*** @brief  在LCD1602指定位置开始以二进制显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:0~1111 1111 1111 1111* @param  Length 要显示数字的长度,范围:1~16* @retval 无*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');}
}

LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);#endif

main.c

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"unsigned char Num;
unsigned char Address;
unsigned char Command;void main()
{LCD_Init();LCD_ShowString(1,1,"ADDR  CMD  NUM");LCD_ShowString(2,1,"00    00   000");IR_Init();while(1){if(IR_GetDataFlag() || IR_GetRepeatFlag())	//如果收到数据帧或者收到连发帧{Address=IR_GetAddress();		//获取遥控器地址码Command=IR_GetCommand();		//获取遥控器命令码LCD_ShowHexNum(2,1,Address,2);	//显示遥控器地址码LCD_ShowHexNum(2,7,Command,2);	//显示遥控器命令码if(Command==IR_VOL_MINUS)		//如果遥控器VOL-按键按下{Num--;						//Num自减}if(Command==IR_VOL_ADD)			//如果遥控器VOL+按键按下{Num++;						//Num自增}LCD_ShowNum(2,12,Num,3);		//显示Num}}
}

Timer0.c

#include <REGX52.H>/*** @brief  定时器0初始化* @param  无* @retval 无*/
void Timer0_Init(void)
{TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;		//设置定时器模式TL0 = 0;		//设置定时初值TH0 = 0;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 0;		//定时器0不计时
}/*** @brief  定时器0设置计数器值* @param  Value,要设置的计数器值,范围:0~65535* @retval 无*/
void Timer0_SetCounter(unsigned int Value)
{TH0=Value/256;TL0=Value%256;
}/*** @brief  定时器0获取计数器值* @param  无* @retval 计数器值,范围:0~65535*/
unsigned int Timer0_GetCounter(void)
{return (TH0<<8)|TL0;
}/*** @brief  定时器0启动停止控制* @param  Flag 启动停止标志,1为启动,0为停止* @retval 无*/
void Timer0_Run(unsigned char Flag)
{TR0=Flag;
}

Timer0.h

#ifndef __TIMER0_H__
#define __TIMER0_H__void Timer0_Init(void);
void Timer0_SetCounter(unsigned int Value);
unsigned int Timer0_GetCounter(void);
void Timer0_Run(unsigned char Flag);#endif

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

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

相关文章

UE4/5C++多线程插件制作(十八、Graph线程封装,以及宏的设置)

目录​​​​​​​ 什么是Graph线程? MTPThreadGraphManage.h MTPThreadInterface.h MTPThreadGraphManage.h MTPManage.cpp void FMTPThreadGraphManage::Wait(const FGraphEventRef& EventRef)</

QT 常用数据结构整理

目录 QString篇 QString篇 //初始化bool bOk false;QString str "sd";QString strTemp(str);str QString("%1,%2").arg("11").arg("-gg");qDebug()<<str;str.sprintf("%s %d","ni",1);qDebug()<<…

网安笔记2

一、实例对象 1.对象是单个实物的抽象&#xff0c;是一个容器&#xff0c;封装了属性和方法 2.构造函数&#xff0c;构造函数就是一个普通的函数&#xff0c;但具有自己的特征和用法。 var Vehicle function () { this.price 1000; }; 上面代码中&#xff0c;Ve…

前端(Electron Nodejs)如何读取本地配置文件

使用electron封装了前端界面之后&#xff0c;最终打包为一个客户端&#xff08;exe&#xff09;。但是&#xff0c;最近项目组内做CS&#xff08;c开发&#xff09;的&#xff0c;想把所有的配置都放进安装目录的配置文件中&#xff08;比如config.json&#xff09;。这做法&am…

M 芯片的 macos 系统安装虚拟机 centos7 网络配置

centos 安装之前把网络配置配好或者是把网线插好 第一步找到这个 第二步打开网络适配器 选择图中所指位置 设置好之后 开机启动 centos 第三步 开机以后 编写网卡文件保存 重启网卡就可以了&#xff0c;如果重启网卡不管用&#xff0c;则重启虚拟机即可 “ ifcfg-ens160 ” 这…

黑苹果如何在macOS Sonoma中驱动博通网卡

准备资源&#xff08;百度&#xff1a;黑果魏叔 下载&#xff09; 资源包中包含&#xff1a;AirportBrcmFixup.kext/IOSkywalkFamily.kext/IO80211FamilyLegacy.kext/OpenCore-Patcher 使用方法&#xff1a; 1.将 csr-active-config 设置为 03080000 全选代码 复制 2.在 …

c++数据锁链

题目描述&#xff1a; 创建一个结构体为Node&#xff0c;具有value , next 两个属性&#xff1b; value为整型&#xff0c;用来储存结构体数值&#xff1b; next为Node类型指针&#xff0c;用来指向下一组数据地址&#xff1b; 第1组数据value 5&#xff1b; 第2组数据value …

php查询数据(日期查询)和fastadmin的日期查询

当前月查询 要在 PHP 中查询数据库中当前月份的数据&#xff0c;需要使用 SQL 查询语句来筛选出符合条件的数据。首先&#xff0c;确保数据库中有一个日期或时间类型的字段用于存储记录的日期信息。 假设你的数据库表名为 my_table&#xff0c;其中有一个名为 date_column 的…

MATLAB RANSAC平面拟合 (29)

MATLAB RANSAC平面拟合 (29) 一、算法简介二、函数介绍三、算法实现四、效果展示一、算法简介 将一个平面与一个从内点到平面的最大允许距离的点云相匹配。该函数返回描述平面的几何模型。该函数采用 M- 估计量样本一致性(MSAC)算法求解平面。MSAC 算法是随机样本一致性(RAN…

【C++】STL——list的介绍和使用、list增删查改函数的介绍和使用、push_back、pop_back

文章目录 1.list的使用2.list的增删查改函数&#xff08;1&#xff09;push_front 在list首元素前插入值为val的元素&#xff08;2&#xff09;pop_front 删除list中第一个元素&#xff08;3&#xff09;push_back 在list尾部插入值为val的元素&#xff08;4&#xff09;pop_ba…

常用的一些蓝图(持续更新)

文章目录 ADEIPS A Apply Damage: 对指定的actor应用伤害。 Add Mapping Context: 添加控制映射上下文。 D Do Once: 仅在第一次命中节点时触发&#xff0c;但可以重置。 Delay: 延迟执行。 Destroy Actor: 销毁指定的actor。 E Enhanced Input Local Player Subsystem: 从玩家…

Elasticsearch 分片策略

文章目录 分片索引设置分片获取索引分片信息示例 分片分配集群级分片分配索引级分片分配索引级分片筛选每个节点的分片总数索引恢复优先级节点掉线时延时分配 分片 和数据库中的表空间类似&#xff0c;不过分片是为每个索引设置&#xff0c;一个索引可以有多个分片&#xff0c…

TCP三次握手/四次挥手

三次握手 三次握手过程 TCP服务器进程先创建传输控制块TCB&#xff0c;时刻准备接受客户进程的连接请求&#xff0c;此时服务器就进入了LISTEN&#xff08;监听&#xff09;状态&#xff1b;TCP客户进程也是先创建传输控制块TCB&#xff0c;然后向服务器发出连接请求报文&…

【QT 网络云盘客户端】——登录界面功能的实现

目录 1.注册账号 2.服务器ip地址和端口号设置 3. 登录功能 4.读取配置文件 5.显示主界面 1.注册账号 1.点击注册页面&#xff0c;将数据 输入 到 用户名&#xff0c;昵称&#xff0c;密码&#xff0c;确认密码&#xff0c;手机&#xff0c;邮箱 的输入框中&#xff0c; 点…

【C语言学习——————动态内存管理】

文章目录 一、什么是动态内存管理二、动态内存函数的介绍 1.malloc函数的介绍2.calloc函数的介绍3.realloc函数的介绍三、free函数的介绍 一.什么是动态内存管理 我们知道数据都是在内存中进行储存的&#xff0c;但是如果我们需要调用内存&#xff0c;我们可以通过定义一个变量…

HTML <p> 标签

实例 以下代码标记了一个段落&#xff1a; <p>This is some text in a very short paragraph</p> &#xff08;在页面下部&#xff0c;您可以找到更多实例。&#xff09; 浏览器支持 元素ChromeIEFirefoxSafariOpera<p>YesYesYesYesYes 所有主流浏览器都…

网络安全系统中的守护者:如何借助威胁情报 (TI) 提高安全性

在这篇哈巴尔网站上的推文中&#xff0c;我们将解释 TI 缩写背后的含义、为什么需要它、Positive Technologies 收集哪些网络威胁数据以及如何帮助企业预防网络威胁。我们将以四种情况为例&#xff0c;说明公司如何使用 PT Threat Intelligence Feeds 来发现恶意活动并预防攻击…

TCP四次握手为什么客户端等待的时间是2MSL

目录 什么是MSL从第三次握手开始分析总结 什么是MSL MSL是Maximum Segment Lifetime英文的缩写&#xff0c;中文可以译为“报文最大生存时间”&#xff0c;他是任何报文在网络上存在的最长时间&#xff0c;超过这个时间报文将被丢弃。 从第三次握手开始分析 第三次握手服务端…

uniapp跳转到外部链接

// 一、先配置页面 {"path": "pages/webview/webview","style": {"navigationBarTitleText": ""} } // 二、编写页面 <template><web-view :src"src" /> </template><script> export def…

vue3+ts+elementui-plus二次封装树形表格

复制粘贴即可&#xff1a; 一、定义table组件 <template><div classmain><div><el-table ref"multipleTableRef" :height"height" :default-expand-all"isExpend" :data"treeTableData"style"width: 100%…