自制电脑红外遥控接收器 PC软解码
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
网上有很多介绍红外遥控接收器制作的文章,但其中大部分是用单片进行红外解码,然后再通过串口或USB把解码后的按键信息传入到PC的。这样的电路制作起来,不仅造价相对偏高,而且需要对单片编程,这会令大部分软件开发爱好者望而却步。
最近看到一篇仅需要7个简单元器件的红外接收器,只需拿起烙铁,不需硬件编程就可以制作完成,原理图如下:
由原理图我们可知,红外接收头把接收的红外信号转换为高低电平通过串口的DSR管脚传入到PC,PC软件通过对DSR高低电平信号的时间曲线进行分析,从而获得相对应的按键信息。
红外遥控器一般采用脉宽调制的串行码,经38kHz的载频把红外信号发射出去。其编码信息一般由三部分组成:引导码、地址码和数据码。一般信号长度大约100ms左右,持续按键则重复发送(中间会有10ms以上的间歇)。
常态下,红外接收头的输出(OUT)都是高电平,引导码信号首先会令红外接收头输出一个大约10ms左右的低电平(不同遥控器有不同的时延),这可令接收设备从容判定信号的到来,而后面的地址码和数据码其电平高低变化就相对较快了,大概在几十或几百个微秒之间。
PC红外遥控软件一般选用Girder,在使用之前需要安装“SFH-56 plugin for Girder”这个插件(文件名"igor SFH-56P lug.dll"),否则不能正常处理我们这种电路的红外接收器信号。可悲的是我至今没找到这个插件,网上提供的很多链接都是坏的。
即使找到了这个插件,要想在我们自己编写的程序中使用也是困难的,因为Girder并没有为我们开发者提供API接口。
既然Girder能用软件实现红外解码,我们为什么不能呢?凡事都要开动大脑,积极行动才对,下面就是我自己焊接的一个红外接收器(元器件是在中发买的,一共不到10元钱,还富裕好多电阻、电容!)
(图下方的红外遥控器的接收器是基于USB的,仅支持Vista以上版本,并且不支持个人开发,不过今天它终于发挥了它应有的作用。当然用电视或VCD遥控器也是可以的)
硬件有了,但程序该从何编起呢?
1、由于接收到的红外信号在微秒级别中变化,对系统实时性要求较高,所以具备垃圾回收功能,实时性没有保证的C#,似乎完不成这种信号的接收功能,所以我们选择的是VC,由它实现高优先级的线程去进行信号接收。
2、由于红外遥控信号是脉宽调制的串行码,所以我们需要采集信号的宽度,显然采用一般的时钟函数来获取时间间隔是不可行的,因为精度太低,所以我们需用采用多媒体时钟和高精度计时的API函数。
3、一般我们按键持续时间为几秒钟,并且由于按键发出前有一个10ms左右的引导信号,所以我们的程序很容易判断出信号起始点,这样我们一次仅需要接收一定量的原始数据就可以完成初步信号采集工作。
4、对于我们的红外接收程序来说并不需要实际解码出红外信号到底包含了那些具体的信息,只要其能够区分出红外遥控上的各个按键就行。
5、由于红接收器是通过串口RTS管脚供电,且通过DSR传递红外信号的,所以我们的程序即使不接收数据,也要打开串口,不过仅需要处理RTS和DSR管脚的信号即可。
好了,动手去做,下面是用VC实现的一个DLL,其功能就是接收并记录红外信号的持续时间。核心代码如下:
DWORD WINAPI ThreadProc(LPVOID pParam)
{
LARGE_INTEGER litmp;
LONGLONG QPart1,QPart2;
double dfFreq;
int iTime=0; //微秒
// 获得计数器的时钟频率
QueryPerformanceFrequency(&litmp);
dfFreq = (double)1000000.0/litmp.QuadPart;
DWORD ModemState,oldModemState=MS_DSR_ON;
//EV_BREAK or EV_CTS or EV_DSR or EV_ERR or EV_RING or EV_RLSD or EV_RXCHAR or EV_RXFLAG or EV_TXEMPTY
//SetCommMask(HSC_COM_Handle,EV_DSR);
//DWORD EvtMask,dwError;
//COMSTAT cs;
while(HSC_Thread_RunFlag)
{
//等待DSR信号发生变化
//WaitCommEvent(HSC_COM_Handle,&EvtMask,&HSC_Ovread);
//ClearCommError(HSC_COM_Handle,&dwError,&cs);
//获得DSR的状态
GetCommModemStatus(HSC_COM_Handle,&ModemState);
ModemState = (ModemState & MS_DSR_ON);
if(ModemState == oldModemState) continue;
oldModemState=ModemState;
//清计数
InterlockedExchange(&HSC_NUM,0);
//开始接收数据
if(HSC_State == 0 && ModemState == 0)
{
QueryPerformanceCounter(&litmp);
QPart1 = litmp.QuadPart;
HSC_State=1;
//复位计数
InterlockedExchange(&HSC_NUM,0);
InterlockedExchange(&HSC_Index,0);
//开启定时器
HSC_TimerID = timeSetEvent(10,HSC_Accuracy,MMTimer,NULL,TIME_PERIODIC);
continue;
}
//接收数据状态
if(HSC_State == 1)
{
QueryPerformanceCounter(&litmp);
QPart2 = litmp.QuadPart;
//--
if(ModemState == 0)
{
iTime = (int)((QPart2-QPart1)*dfFreq);
}
else
{
iTime = (int)((QPart1-QPart2)*dfFreq);
}
if(HSC_Index < HSC_BufferSize)
*(HSC_Buffer+HSC_Index) = iTime;
InterlockedIncrement(&HSC_Index);
//--
QPart1=QPart2;
}
}
return STILL_ACTIVE;
}
如果采用WaitCommEvent函数,你会发现CPU使用时间会很低,不过它会让接收程序无法正常退出,所以只好注释掉该函数了,此时你会发现CPU使用时间会很高。
原始数据一旦采集完毕,剩下的就由C#程序大显身手吧。
C#中DLL的接口函数如下:
const string DllPath = @"YFHSCollect.dll";
[DllImport(DllPath)]
public static extern Int32 HSCStart(Int32 COM, Int32 delay, Int32 BufferSize);
[DllImport(DllPath)]
public static extern Int32 HSCEnd();
[DllImport(DllPath)]
public static extern Int32 HSCData(int[] intData);
我封装了一个类,一旦有按键信息,就会触发一个Click事件。此外程序还具备自学习功能,并且可以把学习后的结果序列化到一个XML文件中去,这样下次再按键就可以识别出键名了。
主程序中测试代码如下:
public partial class frmMain : Form
{
YFHWCollect hw =null;
int[] hwData = null;
public frmMain()
{
InitializeComponent();
hw = new YFHWCollect(this, 1);
hw.Click += new YFHWCollect.HWEventHandler(hw_Click);
}
void hw_Click(object sender, HWEventArgs e)
{
string strInfo = "";
for (int i = 0; i < e.lstData.Count; i++)
{
for (int j = 0; j < e.lstData[i].Length; j++)
{
strInfo += e.lstData[i][j].ToString() + " ";
}
strInfo += "/r/n";
}
txtInfo.Text = strInfo;
lblKeyName.Text = e.KeyName+ " (" + (e.Interval /10).ToString() + "ms)";
hwData = e.Data;
picBar.Refresh();
}
private void btnCommand_Click(object sender, EventArgs e)
{
if (btnCommand.Text == "开始")
{
btnCommand.Text = "停止";
hw.Start();
}
else
{
btnCommand.Text = "开始";
hw.End();
}
}
private void btnStudy_Click(object sender, EventArgs e)
{
hw.Study(txtKeyName.Text);
}
private void picBar_Paint(object sender, PaintEventArgs e)
{
int width = picBar.Width, height = picBar.Height;
e.Graphics.DrawLine(new Pen(Color.Gray), 0, height / 2, width, height / 2);
if (hwData != null)
{
float Len=0;
foreach(int l in hwData)
{
Len+=l;
}
float dx = width / Len,DX=0;
Pen p = new Pen(Color.Green);
float Y=0, Y1=height/4,Y2=(float)(height*3.0/4.0);
float X=0;
for(int i=0;i<hwData.Length;i++)
{
Y = ((i % 2)==0 ? Y2:Y1);
DX = hwData[i] * dx;
e.Graphics.DrawLine(p, X, Y, X + DX, Y);
X += DX;
e.Graphics.DrawLine(p, X, Y1, X, Y2);
}
}
}
}
测试程序运行结果如下:
(上面显示的数据为高电平和低电平的持续时间(低高低高…),单位为1/10毫秒)
注意事项:
1、红外遥控器按键偶数次和奇数次的编码是不同的,程序需要学习两次,才能正常识别按键信息。
2、普通的USB转串口由于仅连接了2、3、5管脚,所以不能正常使用,对比较好的USB转串口(比如Moxa的三百多一根),虽然所有的管脚都引出了,但是由于是通过USB转换的,所以响应时间很是问题,我就因为这个差一点功亏一篑,幸好把程序又在PC机跑了一遍。
//获得DSR的状态
GetCommModemStatus(HSC_COM_Handle,&ModemState);
上面的指令如果采用的是USB转串口,运行时间会是7ms左右,而用主板自带串口仅是几个微秒,相差实在太大了。所以上面的红外接收器程序在没有自带串口的笔记本上是无法正常工作的。
源码下载地址:http://www.sky-walker.com.cn/yefan/SourceCode/YFHSCollectTest.rar
给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
![](/assets/blank.gif)
自制电脑红外遥控接收器 PC软解码相关推荐
- 自制电脑红外遥控接收器(PC软解码)
网上有很多介绍红外遥控接收器制作的文章,但其中大部分是用单片进行红外解码,然后再通过串口或USB把解码后的按键信息传入到PC的.这样的电路制作起来,不仅造价相对偏高,而且需要对单片编程,这会令大部分软 ...
- 即插即用的PC红外遥控接收器
文章原标题<基于V-USB制作的电脑红外遥控接收器> 已刊登在<无线电>杂志2014年12期 点此购买淘宝套件 基于V-USB制作的电脑红外遥控接收器 文 / 任鹏 ...
- “硬解码”与“软解码”的区别
关于"硬解码"与"软解码" 忧蓝 发布于: 2010-08-02 11:03 由于高清视频的分辨率远远高于一般格式视频,使得高清视频的码率非常高.再加上VC-1 ...
- 手机视频硬解码和软解码的区别
在手机评测视频播放能力的时候经常会提到"硬解码"和"软解码",但是很多人不太明白是什么意思,其实问题很简单.大家都知道PC都有CPU和GPU(显卡),在手机上也 ...
- 软解码与硬解码区别linux,软解码和硬解码哪个好 软解码和硬解码有什么区别
喜欢用手机看视频的同学应该都会接触到这样一个概念,手机软解码和硬解码.虽然这两个选项在播放器中再常见不过.不过还是很多机友不知道两者的区别再哪里.就针对这个问题百事网小编给大家普及一下相关的软解和硬解 ...
- HEVC的软解码和硬解码
1.概念 从数字视频诞生以来,硬解码和软解码的说法一直伴随着它的发展.数字视频的软解码是指在通用CPU上通过专门的播放软件解码并播放视频:而硬解码则是指在专用的硬件解码模块解码视频,然后将解码数据送至 ...
- 关于“硬解码”与“软解码”
由于高清视频的分辨率远远高于一般格式视频,使得高清视频的码率非常高.再加上VC-1和H.264编码的压缩率很高,解码运算的运算量很大.因此常规地直接用CPU解码(即常说的"软解") ...
- 红外遥控器快速编码解码(NEC)
红外遥控器快速编码解码 NEC编解码模块 红外遥控简介 NEC编码 红外编解码模块 接线说明 串口查看数据 数据验证 总结 原文链接:https://www.yourcee.com/newsinfo/ ...
- Android多媒体添加软解码
1 软解码加载简介 1.1 编解码器信息与配置导入 android中decoder的管理是以plugin的模式,其控制是在OMXMaster内完成的. OMXMaster是在omx被创建时就创建了 O ...
最新文章
- Q+会带来什么样的互联网时代?
- 皮一皮:女友在意的点....是包子!
- fpga电平约束有什么作用_FPGA时序约束有什么样的作用
- Qt / 动态的切换控件样式的方法
- 简单io应用—流水灯控制_制作简单有趣的可调速流水灯
- IDEA破解 2017 IDEA license server 激活(可用)
- mysql优化之连接优化
- OpenStack精华问答 | OpenStack的目标是什么?
- 相对于其他框架的离子应用开发:它被炒作了吗?
- Xtreme ToolkitPro 编译选项
- 【mysql】使数据表ID连续的两个方法
- 笔记本电脑系统怎么重装,笔记本重装系统
- FANUC机器人示教器介绍
- 维刻柠檬鲜果冰怎么样?
- Oracle RAC原理
- C++ requires a type specifier for all declarations
- (转)Django新手需要注意的10个要点
- 资源共享——FTP服务
- xp电脑怎样连接无线网络连接服务器,xp笔记本电脑怎么连接无线网wifi呢
- JL-03-Q9 自动气象站 常见气象9参数 空气温湿度 风速风向 雨量光照 大气压力 土壤温湿度
热门文章
- vue报错 运行npm run dev报cjs.js缺失
- 新基建形势下安全公共服务平台建设机遇
- Codeforces Round #142 Div.2 题解
- Android webView滑动实现沉浸式标题栏效果切换
- linux挂载本地iso镜像
- PostgreSQL外部表应用
- 如果你是团队里的“C位”,这10个建议很值得一听
- 笔记本电池怎样使用问题
- plt.grid()、plt.scatter()、plt.plot()、plt.arrow()、plt.text()函数讲解
- 你第一篇SCI写了几个月?