动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > C/C++教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ C/C++教程 ]的信息

本月文章推荐
.用VC++6.0的Sockets API实现一个.
.C语言EXPORT_SYMBOL_(INTERNAL a.
.C程序开发初级讲座之分支结构.
.菜鸟图解简单链表.
.数据结构C语言实现系列——线性表.
..
.Order by 的数值型灵活使用.
.多维数组.
.MIME和BASE64编码/解码程序代码.
.谈谈代码风格──谈谈缩进.
.GCC 安装.
.用Delphi实现远程屏幕抓取.
.C++/CLI思辨录之再谈继承.
.可怜的Bool——浅析程序可扩展性.
.对C++中引用的补充说明(实例).
.C++程序中导出Word文档的简易方法.
.C语言入门之数组(1).
.C语言常用的三种排序方法总结与探.
.软件许可证要求.
.实现C语言高效编程的四大秘技.

C++实现用掌上电脑遥控电视

发表日期:2008-3-8 |


1. 简介

  你是否曾想过通过你的掌上电脑上的IR端口控制你的TV、Hi-Fi或者其它视频?本文将介绍怎样使用掌上电脑中的IR端口来编程控制一台TV。
2. 背景

  我近些日子丢失了我的老式索尼TV的遥控器。这本身没有什么问题,因为我买了个新的遥控器作为代替。然而,当电视失去了它的设定的颜色时,我碰到了问题,因为它只能显示黑白色了,而新的遥控器没有颜色调整按钮。我决定在我的老式的Jornada 525掌上电脑上写一个程序使用IR端口把正确的代码发送给TV。

  共有三个主要协议可以用于发送IR代码到设备上。索尼TV使用 ’Pulse Coded’ 方法,它需要发送一个包含头(header)位的以空格隔开的’1’位和’0’位的数据流。这些位被调制成一种40KHz的载波信号。其中,头长度为2200 μs,’1’位为110 μs,’0’位为550 μs,而空格是550μs的沉默(silence)。大多数索尼设备使用12位数据,它被分离成6位的地址(设备类型)和6位命令。因此数据看起来象这个样子:hxxxxxxyyyyyy,其中h是头位,xxxxxx是6位的命令(msb first),yyyyyy是6位的地址。对此我不再细述,因为网上有很多资源描述这种协议,并列举了针对不同设备的代码。一些新的索尼设备使用19位代码,我相信另外的制造商也使用和我描述的相同的格式。还有可能为使用’Space Coded’或’Shift Coded’协议的设备写出相似的类。

  我曾使用嵌入式C++写过一个类CirPulse,它封装了从一台运行Windows CE 3.0的Jornada 525 PC上控制索尼及其相匹配设备的功能。估计它能够与其它相匹配设备和操作系统一起工作,但是你需要试验才行!

更多文章 更多内容请看C/C++技术专题  电脑配置手册  电脑维修专题专题,或
3. 实现过程分析

  这个CIrPulse类暴露了几个函数,它们使得发送IR代码尽可能轻易。在声明CIrPulse类时,你应该调用一次FindIrPort(),它返回一个描述IrDA端口的端口号的UINT,这通过搜索注册表得到。
这个端口号用于后面的调用来打开IrDA端口进行串行通讯。
UINT CIrPulse::FindIrPort()
{
 // 查询注册表中的IR端口号
 HKEY hKey = NULL;
 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("Comm\IrDA"),0, 0, &hKey) == ERROR_SUCCESS)
 {
  DWord dwType = 0;
  DWORD dwData = 0;
  DWORD dwSize = sizeof(dwData);
  if (RegQueryValueEx(hKey, _T("Port"), NULL, &dwType, (LPBYTE) &dwData, &dwSize) == ERROR_SUCCESS)
  {
   if (dwType == REG_DWORD && dwSize == sizeof(dwData))
   {
    RegCloseKey(hKey);

    return (UINT) dwData;
   }
  }
  RegCloseKey(hKey);
 }
 return 0;
}
  得到端口号后,你可以调用Open(UINT)函数,把通过调用FindIrPort()得到的端口号传递过去。这打开该端口并设置串口参数,假如成功返回true。该端口被设置为115200波特,8个数据位,2个停止位和奇偶校验位。关于如何产生载波以及为什么我使用这些设置将在本文后面介绍。
BOOL CIrPulse::Open(UINT uiPort)
{
 ASSERT(uiPort > 0 && uiPort <= 255);
 Close();
 //打开IRDA端口
 CString strPort;
 strPort.Format(_T("COM%d:"), uiPort);
 m_irPort = CreateFile((LPCTSTR) strPort, GENERIC_READ GENERIC_WRITE,0, NULL, OPEN_EXISTING, 0, NULL);
 if (m_irPort == INVALID_HANDLE_VALUE)
 {
  return FALSE;
 }
 //设置输入和输出缓冲区的大小
 VERIFY(SetupComm(m_irPort, 2048, 2048));
 //清除读和写缓冲区
 VERIFY(PurgeComm(m_irPort,PURGE_TXABORTPURGE_RXABORT
 PURGE_TXCLEARPURGE_RXCLEAR));
 //重新初始化所有的IRDA端口设置
 DCB dcb;
 dcb.DCBlength = sizeof(DCB);
 VERIFY(GetCommState(m_irPort, &dcb));
 dcb.BaudRate = CBR_115200;
 dcb.fBinary = TRUE;
 dcb.fParity = TRUE;
 dcb.fOutxCtsFlow = FALSE;
 dcb.fOutxDsrFlow = FALSE;
 dcb.fDtrControl = DTR_CONTROL_DISABLE;
 dcb.fDsrSensitivity = FALSE;
 dcb.fTXContinueOnXoff = FALSE;
 dcb.fOutX = FALSE;
 dcb.fInX = FALSE;
 dcb.fErrorChar = FALSE;
 dcb.fNull = FALSE;
 dcb.fRtsControl = RTS_CONTROL_DISABLE;
 dcb.fAbortOnError = FALSE;
 dcb.ByteSize = 8;
 dcb.Parity = EVENPARITY;
 dcb.StopBits = TWOSTOPBITS;
 VERIFY(SetCommState(m_irPort, &dcb));
 //为所有的读和写操作设置超时值
 COMMTIMEOUTS timeouts;
 VERIFY(GetCommTimeouts(m_irPort, &timeouts));
 timeouts.ReadIntervalTimeout = MAXDWORD;
 timeouts.ReadTotalTimeoutMultiplier = 0;
 timeouts.ReadTotalTimeoutConstant = 0;
 timeouts.WriteTotalTimeoutMultiplier = 0;
 timeouts.WriteTotalTimeoutConstant = 0;
 VERIFY(SetCommTimeouts(m_irPort, &timeouts));
 DWORD dwEvent=EV_TXEMPTY;
 SetCommMask(m_irPort,dwEvent);
 return TRUE;
}
更多文章 更多内容请看C/C++技术专题  电脑配置手册  电脑维修专题专题,或
  调用函数SetCodeSize(DWORD)来设置要传送的位数(如12位)。这可以在任何时候完成且只需要做一次。它一直保持有效,直到后面的调用改变它为止。

  最后调用SendCode(long),传递实际要发送的代码。
BOOL CIrPulse::SendCode(DWORD lValue)
{
 DWORD dwCount;
 int i=0;
 ASSERT(iDataLength>0);
 //清除传送缓冲区
 VERIFY(PurgeComm(m_irPort,PURGE_TXABORT PURGE_RXABORT PURGE_TXCLEAR PURGE_RXCLEAR));

 //每次按键设置代码6次
 for(int x=0;x<6;x++) {
  MakeStream(lValue); //发送代码
  dwCount=GetTickCount();
  while(GetTickCount()<dwCount+26) //延迟26ms
   i++;
 }
 return true;
}
  注重这个函数调用另外一个函数MakeStream(long)6次,每两次调用之间停顿26毫秒。我发现该代码必须发送好几次才能使接收设备响应,大概是为防止假行为的缘故吧。26毫秒对于接收设备登记该代码是必需的,在下一个代码出现之前。

  这个函数MakeStream(long)把字节流写入IrPort,并根据是否有起始位(1或者0)来确保发送正确的数据包长度。包含数据字节(0xdb)的缓冲区是以一个ByteArray形式存在的。

  函数Close()用于在端口使用后,自然地关闭IrPort。

更多文章 更多内容请看C/C++技术专题  电脑配置手册  电脑维修专题专题,或
  这个函数在我的ornada上运行良好。请看下面的讨论以进一步确定你要做的可能性改变。
BOOL CIrPulse::MakeStream(DWORD lValue) {
 DWORD dwStreamLength;
 //创建开始脉冲
 dwStreamLength=iHPulse/charWidth;
 ASSERT(Write((const char *)bPulseStream.GetData(),
 dwStreamLength)==dwStreamLength);
 // ************************************
 // ***** 在下一个脉冲到来前延迟一段时间
 // ************************************
 //循环操作代码中的位来发送脉冲
 for(int i=0;i<iDataLength;i++) {
  if(lValue & 1) {
   //创建一个脉冲1
   dwStreamLength=i1Pulse/charWidth;
   ASSERT(Write((const char *)bPulseStream.GetData(),
   dwStreamLength)==dwStreamLength);
   // *********************************
   // ***在下一个脉冲到来前延迟一段时间
   // *********************************
  }
  else {
   //创建一个脉冲 0
   dwStreamLength=i0Pulse/charWidth;
   ASSERT(Write((const char *)bPulseStream.GetData(),
   dwStreamLength)==dwStreamLength);
   // ********************************
   // **在下一个脉冲到来前延迟一段时间
   // ********************************
  }
  lValue >>= 1;
 }
 return TRUE;
}
  我在所附源代码中包含了一个简单的应用程序,它使用CIrPulse来创建一台索尼TV的远距离遥控。它具有基本的频道选择、音量调整和开/关机的功能。

4. 非凡注重

  因为该CIrPort类使用一个串行端口连接到该IR端口,所以必须生成一个40KHz的载波信号,这通过从该串行端口发送恰当的字符来实现。幸好,假如我们发送字符0xdb,以115200波特,用8个数据位,2个停止位和奇偶校验,这样就能产生一种极接近38.4KHz的载波信号。我们所有的索尼设备接收这种数据是没有问题的。

  最大的问题是,如何实现间隔每次脉冲的沉默周期。不可能由串行端口来产生该沉默周期,因为就算你发送一个0x0字符,由于存在起始和停止位,你仍然在该IR上得到脉冲。我通过发送不同的字符进行试验,依据的前提是假如你不以40KHz的频率发送一个载波信号,这有可能使设备误把这个当作一个沉默。这样做的优点是你可以产生一个包含完整的代码的byteArray,以确保准确计时。但是结果并不一致,所以我拒绝使用这个方法,为的是实现在两次从串行端口发出成组的0xdb字符之间支持暂停。因为需要的延迟是以550μs的顺序;到目前为止,我还没有找到取得独立于处理器速度的暂停的方法。在我的Jornada上,是完全不必产生一个延迟的,因为每次调用Write函数看上去都使用了合适的时限。不管怎样,我担心的是,你可能胡乱产生一个可以使你的掌上电脑能工作的一个延迟。
更多文章 更多内容请看C/C++技术专题  电脑配置手册  电脑维修专题专题,或
上一篇:精华:C++编程新手错误语录(续一) 人气:376
下一篇:C宏--智者的利刃,愚者的恶梦 人气:295
浏览全部C/C++的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-9-6 Movie34电影搜索引擎 v3.0
2008-9-6 wap2.0仿帝国建站喜用 v2.0
2008-9-6 免费人才招聘网 宽屏版 v3.01
2008-9-6 喜喔喔视频采集程序 v1.0 beta
2008-9-6 ASP客户管理系统
2008-9-6 主流驿站中秋祝福程序
2008-9-6 php实现msn协议的类
2008-9-5 Coppermine Photo Gallery v1.4.
2008-9-5 清松网络日记本 v2.4
2008-8-23 Mini WinMount V0.4
2008-8-23 Vista优化大师3.11正式版
2008-8-23 Wine 1.13
2008-8-23 KlipFolio 5.0 Build 5899-80
2008-8-23 Windows Sysinternals Desktops
2008-8-23 OneTap Movies1.2破解版
2008-8-23 AnnotaterPDF阅读1.1.503 破解版
2008-8-23 SoundMeter分贝测量仪 v1.0汉化破
2008-8-23 iDrum音乐节拍1.0破解版
  发表评论
姓 名: 验证码:
内 容:
站长工具:网站收录查询 | Google PR查询 | ALEXA排名查询 | CSS在线编辑器 | 广告代码 | Html转换js | js/vbs加密 | md5加密 | 进制转换
实用工具:汉字翻译拼音 | 符号对照表 | 个税计算 | 经典小工具 | 汉字简繁转换 | 普通单位换算 | 公制单位换算 | 生辰老黄历 | 国内电话区号 国家代码与域名缩写 | 文字加密解密 | 健康查询 | 万年历 | 汉字横竖排版 | 手机号码查询 | 计算器 | ip搜索
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号