Embedded 版 (精华区)

发信人: snows (花自飘零水自流), 信区: Embedded
标  题: Wince编程经验17(ZZ)
发信站: 哈工大紫丁香 (2004年03月14日09:38:54 星期天), 站内信件

COM在WinCE串口通信中的应用


1.PC和Windows CE的通信系统
  Win32的通信系统 Win32提供给用户一个模块化的32位的保护模式的通信系统。在
Win32中,各种通信资源的函数做了很大的改进和标准化,使得它们的操作就如同文件的
操作一样。
  在串口读写操作中,Win32引入了超时概念。超时直接影响读写操作行为。当超过预
先设定的超时间隔时间,ReadFile、WriteFile操作仍未结束,那么将无条件结束读写操
作,而不论是否已读出或写入指定数量的字符。
  Windows CE的通信系统 Windows CE将驱动程序分为两种:本地设备驱动程序和流设
备驱动程序。本地设备驱动程序,也称为“内置驱动程序”,这些设备驱动程序是一些
硬件所必需的,是由原始设备制造商创建的,用以驱动如键盘、触摸屏、音频设备等,
往往在设备售出后就不会再更换。另一方面,流接口设备驱动程序(指可安装的启动程
序)可以由第三方生产商提供,以支持添加到系统中的设备。Windows CE下的设备驱动
程序在与应用程序相同的保护级上工作。当系统启动时,大多数驱动程序是由设备管理
进程(DEVICE.EXE)加载的,所有的这些驱动程序将共享同一个进程地址空间。
  本地设备驱动程序一般都被紧紧地限制在Windows CE的操作系统中,往往在设备售
出后就不会再更换。因为Windows CE没有像ISA或PCI那样的用于附加插卡的总线,附加
的硬件通常是通过PCMCIA或“小型快闪槽”安装的,例如串口2是通过PCMCIA卡实现的。
观察注册表中的HKEY_LOCAL_MACHINE下的\Drivers\Active键中的内容,可以了解在Win
dows CE中加载了什么驱动程序。 
  通信过程 包括(1)打开通信资源。在进程使用串口之前,首先应使用CreateFile
函数打开通信资源,返回一个标识该资源的句柄。在CreateFile函数打开串口通信资源
时,系统将根据上次打开资源时的数值初始化和配置资源;(2)读写串口资源。通过R
eadFile和WriteFile函数来读写串口。读和写的超时时间由SetCommTimeouts函数设置;
(3)关闭通信资源。在使用通信资源结束后,应调用CloseHandle函数来关闭通信句柄
,释放资源。
2.控件的设计与实现
  控件的设计 一般的掌上电脑只配备了串口1,而串口2则需要外接适配卡。本文主要
是针对长白公司生产的蓝天LT-90-1机型提供辅助的功能,所以本控件默认使用串口1。
由于掌上电脑的资源比较少,为了尽量减少CPU的占用,本控件采用了每一定时间间隔对
串口进行采样的方案,对串口的每一次读写采取了限时的方法,保证控件可以在较短的
时间结束调用,用牺牲一定的成功率来实现调用的效率,避免无限时的对串口操作的等
待而引起的待机。控件的设计包括:
  控件目的:提供对串口通信的打开、关闭和读写的控制。
  控件设计的主要部分是与使用者之间交互的过程,即控件提供给使用者的函数和通
过事件来通知使用者做出相应的处理。下面是本控件所实现的事件和方法。
  控件触发的事件:在串口通信的过程中,控件通过如下的两个事件来通知使用者做
出处理。
  NewData:当此事件被触发时,表示在串口收到新的数据,此时程序应对该事件做出
反应,及时收取数据。
  WriteError:当此事件被触发时,表示对串口的写操作失败了,此时程序应对错误
进行处理。
  控件实现的方法:控件提供了四个方法供使用者调用,使用者在得到控件指针后,
通过这四个函数来完成对串口的打开、关闭和读写。Open:无参数。在第一次使用时,
应调用此函数,对串口进行初始化。默认串口的参数为9600波特率、8位字符、一位校正
位、奇偶校验。当初始化成功时返回TRUE,失败时返回FALSE。Read:参数ReadBuffer和
ReadSize,ReadBuffer是一个读入字符缓冲区。在NewData事件的响应函数内部,使用R
ead来读取从串口输入的字符。成功时函数返回TRUE,ReadSize返回读出的字节个数,R
eadBuffer返回读出的字符;失败时,函数返回FALSE。Write:参数WtiteBuffer和Writ
eSize,WriteBuffer是想要写入串口的字符。此函数可在任何时候调用。如果函数返回
FALSE,则表示输入的参数有错误;如果函数返回TRUE,则表示输入参数正确。如果在传
输的过程中出现了错误,则控件将引发WriteError事件,通知应用程序写操作失败,并
由应用程序做出相应的处理。Close:无参数。在串口使用结束后,请调用此函数,它将
释放由控件打开的串口资源,以便其他的程序继续使用该资源。
  基本的串行通信编程 串行设备被视为用于打开、关闭、读和写串口的常规、可安装
的流设备。Win32 API提供了一组通信函数,Windows CE支持了其中的大多数通信函数。

  打开和关闭串行端口:在所有的流设备都可以使用CreateFile来打开串行端口设备
。一般的调用方法如下:
hSer=CreateFile(TEXT(“COM1:”),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXIST
ING,0,NULL);
  由于Windows CE不支持设备的重叠I/O,因此不能传递FILE_FLAG_OVERLAPPED标志。
当不成功时,返回句柄INVALILD_HANDLE_value,反之返回打开的串行端口句柄。
  调用CloseHandle可以关闭一个串行端口:
   CloseHandle(hSer);
  读写串行端口:可以使用ReadFile和WriteFile来读写串行端口。从串口读出数据只
需如下调用:
int rc;
DWORD cBytes;
BYTE ch;
rc=ReadFile(hSer,&ch,1,&cBytes,NULL);
  调用成功,则变量ch将读入一个字节,cBytes将被设置为读取的字节的数量。
  从串口写入数据只需如下调用:
int rc;
DWORD cBytes;
BYTE ch;
ch=TEXT(‘A’);
rc=WriteFile(hSer , &ch , 1 , &cBytes , NULL );
  上面的代码将字母A写入已经打开的端口,成功的话,ReadFile和WriteFile都将返
回TRUE。
  控件的调试 由于本控件的开发平台的特点,使得程序的调试有所不同。在程序编译
后,Visual C++使用同步服务器将程序传输到掌上电脑中,此时,掌上电脑与主机之间
使用了串口1,如果不关闭同步服务器的话,那么在掌上电脑使用控件对串口1进行初始
化时,将会失败。因此,必须在程序传输到掌上电脑后,将与主机的连接关闭,同时要
在主机上关闭同步服务器,否则服务器将不停地向掌上电脑发送同步信号。由于关闭了
串口,则无法使用Visual C++提供的调试功能,只有在程序中自己输出调试信息,并改
正程序。基本的调试手段是在程序需要查看变量的地方,用AfxMessageBox函数将变量的
内容输出,或者在程序的对话框中添加一个文本编辑控件,来输出程序的信息。
  控件的台式机版的实现 在实现了一个Windows CE的控件后,开发者将会面临一个问
题,当你想在你的应用程序中使用该控件的时候,你在台式机的注册表中找不到你设计
的控件,因而也无法在Visual C++中或Visual Basic中使用。这是因为CE版的Active X
控件被注册在相应的Windows CE的设备的注册表中,而没有在台式机上注册。
  为了解决这个问题,你必须实现两个版本的CE控件。版本1注册在你的Windows CE的
设备上,版本2注册在你开发应用程序的台式机的注册表中。第二版本的控件实现了在W
indows CE上控件的外壳,即提供了控件的所有方法和事件,但没有具体的函数的实现。
它仅用来提供应用程序到控件的所有连接。
  3.结束语
  本文讨论了基于Windows CE平台的COM应用开发,提出了一个串口通信控件的实现以
作为示例。该控件可以嵌入到大部分的Windows CE的程序中,很好地完成现串口通信的
基本任务。
  目前,COM还处在不断发展的阶段中,新的技术不断出现。分布式组件对象模型(简
称为DCOM)把COM的位置透明特性扩展到不同的计算机上。COM+则扩展了中间组件,以便
其支持成百上千的同时访问。COM+组件服务为组件开发者经常需要的服务提供了标准的
服务实现,从而解放了开发者,使之能够把精力集中在商务处理问题上。而微软的Wind
ows DNA(Windows Distributed Internet Application Architecture),是Windows平台
应用程序基于COM开发的又一模式,它使得客户机和服务器方的开发更加专一和简化。这
些新的技术,必然会给Windows CE平台的应用开发带来更大的活力。相信Windows CE的
明天会更加灿烂 。


自己动手在CE下实现打印功能
撰写: 作者:clm 成都电子研究所
(仅为存档侵机即删)
为了实现打印你需要了解以下几个问题:
一、打印机不论是激光、喷墨还是喷墨必须带标准并口;
二、了解打印机接口结构,以下对25针打印机并口作个简单介绍:
从接口向打印机方向的信号分为两组:一组是数据线8位;另一组是联络与控制信号线,
其中从接口发向打印机的信号从功能上看有“数据选通”、选择输入、自动输纸、初试
化打印机”,而从打印机发向接口的信号则有“回执、打印机忙、无打印纸、打印机在
线、打印机出错”。在大多设备上为打印并口分配的端口地址是一样的(可在BIOS中查
看):数据输出378H, 控制输出37AH,状态输入379H。操作打印机
实际上就是操作这这三个端口地址,以下用378H~37AH为例用一些汇编语言来描操作过程
:
1 对地址378H执行OUT指令,将把AL中字符ASCII代码送入接口的数据锁存器等待有“选
择输入”或“数据选通”信号的到来。
2 对地址37AH执行OUT指令把预置与AL中的控制代码送到接口的控制锁存器,该控制字节
各位应以以下约定排列:
位0:控制发数据选通信号,有效极性为正脉冲,所以位0的初始状态应为0。要产生一次
选通信号的就要执行两次OUT指令:先向37AH地址发出的OUT指令输出的字节0位为1,接
着再发出一条OUT指令,输出的字节0位为0,这样把已等在数据线上的数据置入打印机。

位1:控制发出自动输纸信号,有效极性为正脉冲。该位为0将不自动输纸;为1,在执行
输出指令把控制字节置入控制所存器后,每遇“回车”字符代码送入打印机后即自动输
纸。
位2:发出打印机初始化控制信号,有效极性为负脉冲。该位为1表示不初始化即平时状
态。初始化打印机,就要连续执行两条指令,第一条是该位置0,第二条是该位置1。
位3:发送选择输入信号,通常该位置1,让打印机能接受数据与控制信号
位4:中断控制位,决定打印机的工作方式:查询(置0)或中断方式(置1)。查询方式
是指在发出打印命令位之前,先查询打印机是否忙碌
;中断方式是利用打印机向接口发送“回执”信号形成一个中断请求信号,加到中断控
制器8259的IRQ7(系统总线上),CPU响应中断进入中断服务子程序,向打印口发送字符
代码。
位5~7无意义。
3 、对地址执行IN指令,将从接口线上取回打印机状态信息入AL,各位意义如下:
位3 为0表打印机有故障
位4 为1表打印机在线联接
位5 为1表打印机无纸
位6 为0是打印机已发“回执”信号
位7 为0表示打印机正在“忙”,不可用选通信号向打印机送新字符代码。
位0~2 无意义,实际上你也可对378H、37AH执行IN指令,读回上次向这两个端口输出的
字节
如果你觉得还不够清楚,可以看接口技术相关书籍. 在第二部分我将分析出一段简单的
代码并通过对它的修改来实现CE下打印.
有了第一部分的知识后,请看如下使用查询方式操作打印机的汇编代码代码(摘自一本很
老的书了)
PRINT PROC NEAR
PUSH AX
PUSH DX
MOV DA,378H //输出字符代码
OUT DX,AL
MOV DX,379H
WAIT:
IN AL,DX
TEST AL, 80H //检查、等待打印机空闲
JZ WAIT
MOV DX,37AH
MOV AL,0DH //输出控制字节00001101
OUT DX,AL
MOV AL,0CH
OUT DX,AL //输出控制字节00001100,在选通信号上产生正方波
POP DX
POP AX
RET
PRINT ENDP
对这段代码的分析已给出,接下来我所要做的就是把它移置到EVC中
第一步:在CE中要直接操作I/O地址必须对要操作的地址进行虚地址映射(参见PB HELP中
的VirtualCopy,VirtualAlloc等函数用法)
第二步:很简单了就是修改原代码
在EVC环境下,设备PB4.1 net
#include
#include "pkfuncs.h"
#pragma comment(lib,"ceddk的LIB")
int WINAPI WinMain(...)
{
.... //虚地址映射
...
//输出"CLM"并换1行
char str[]="CLM\n";
int i=0;
#if defined(x86)
__asm {
push ax
push dx
}
for(i=0;i<4;i++)
{
char str1=str[i];
__asm{
mov dx, 0x378
mov al, str1
out dx, al
mov dx, word ptr 0x379
}
wait:
__asm{
in al, dx
test al,0x80
jz wait
mov dx, 0x37A
mov al, 0x0D
out dx, al
mov al, 0x0C
out dx, al
}
}//for
_asm{
pop dx
pop ax
}
#endif
//如果你习惯用outp、inp这些DOS下的API操作端口地址
//你可以把WRITE_PORT_UCHAR(...),READ_PORT_UCHAR(...)这些函数封装成你自己的AP
I
//照样实现以上的汇编的功能
}//WinMain
总结:
虽然该代码实现的打印功能很简单还有许多值得完善的地方如打印字符,设置字体,中
断调用等,但是我认为该方法对那些对打印还很不熟悉的朋友们多少有一点启示的,该
方法一个最大特点就是很低层可以说只要掌握的够全面、够深入那么不管是那种型号的
打印机,只要带有标准的并口你都有可以随心所遇的使用它。但是要做到以上还是需要
很大功夫的,毕竟直接用打印机驱动程序的接口监视函数来开发打印驱动
要简单多(可惜我发现似乎这些函数对大多数打印机根本不起作用,经测试只有某些型号
的HP打印机才能使用,这是令我们最头痛的事了)。

--
-
 ╭────────────────────────────╮
 │   风萧传瑟声,叶落根深处,青阶入野无归途,他乡不知顾   │
 │   泣下问和谁,叹者行已暮,寒眉傲骨今尚在,奈何入凡土   │
 ╰────────────────────────────╯
                                                                             

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.229.154]
※ 修改:·snows 於 03月14日09:42:40 修改本文·[FROM: 202.118.229.154]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:7.110毫秒