(2) 设置HW006的混合工作模式 void ts_config(int* fd) { … write(*fd,&SET_96,2); //设置HW006波特率为9600bps write(*fd,&SET_X1,2); write(*fd,&SET_Y1,2); write(*fd,&SET_X2,2); write(*fd,&SET_Y2,2);//设置手写区域4个角的坐标 write(*fd,&WAIT_T,2);//设置汉字识别等待时间 write(*fd,®_SCOPE,2);//设置识别范围 write(*fd,®_CAN,2);//设置识别字候选个数 … }
(3) 读串口 int ts_read(int *fd,unsigned char *buf) { int res; res=read(*fd,buf,3); return res; }
(4) 发送到有名管道 void sendFifo(unsigned char* buf,int i) { … fd=open(/dev/myfifo,O_WRONLY | O_NONBLOCK); write(fd,buf,i); close(fd); }
3.2 改写Qt/Embedded层的触摸屏API
对读到的原始数据进行处理,包括变换、校正、分发等。Qt/Embedded中提供触摸屏API的文件是qwsmouse_qws.cpp,其中的类QCalibratedMouseHandler实现了对触摸屏数据的读取及其处理。本文所用的HW006是8位的,而显示分辨率是640×480,因此在读到触摸屏数据时还要进行转换。又因为HW006工作在混合模式状态下,因此需要把所读到的坐标数据和汉字码分开,将坐标数据进行转换后送给图形界面,并将汉字码送给输入法,这涉及到了不同进程之间通信的问题。不同进程之间的通信主要有管道、共享内存、消息队列等几种方式。其中: 共享内存速度最快,在传送大量数据时比较有优势;管道最容易实现,这里需要传送的数据量不大,因此选用管道的通信方式。
在qwsmouse_qws.cpp中,定义了一个对触摸屏数据进行处理的类——QSitsangTPanelHandlerPrivate。该类继承了QCalibratedMouseHandler。在它的构造函数中,利用Linux层提供的函数打开串口,设置HW006工作模式;再利用QT特有的信号和槽机制,定义一个QSocketNotifier类把串口描述符和QSitsangTPanelHandlerPrivate类的成员函数——读触摸屏数据函数readTSData()连接起来,实现对串口数据的自动监视与读取。
部分代码如下: QSitsangTPanelHandlerPrivate::QSitsangTPanelHandlerPrivate(MouseProtocol, QString) { fd=ts_open(/dev/ttyS1); … ts_config(fd); QSocketNotifier *mouseNotifier; TS_Notifier=new QSocketNotifier(*fd, QSocketNotifier::Read, this); connect(TS_Notifier, SIGNAL(activated(int)),this, SLOT(readTSData())); } 读触摸屏数据函数readTSData()的程序流程如图3所示。

图3 读触摸屏数据函数的流程
3.3 完成手写显示和识别字显示界面
手写输入法的具体实现是在Qtopia层,利用Qtopia提供的API来完成中文手写输入法的手写显示及识别字显示。在这里利用输入法插件接口——InputMethodInterface类,通过对该类的继承以及对该类成员函数的重载,完成手写输入法,最终编译成链接库形式,被Qtopia服务器自动调用。
class QTOPIA_PLUGIN_EXPORT UniKeyboardImpl : public InputMethodInterface { public: … Q_REFCOUNT virtual QWidget*inputMethod(QWidget*parent, Qt::WFlags f); //需要重载的虚函数,在该函数中可以添加用户自定义的输入法类 … private: HandWrKeyboard *input; //HandWrKeyboard是手写输入法的类 … }; 函数virtual QWidget *inputMethod( QWidget *parent, Qt::WFlags f )重载为: QWidget *UniKeyboardImpl::inputMethod( QWidget *parent, Qt::WFlags f ) { if ( !input ) input=new HandWrKeyboard( parent, HandWriting, f ); return input; }
从功能上手写输入法软件部分可分为两种:显示笔划轨迹与显示识别候选字。 触摸屏和HW006连接部分是完全的模拟量,由于液晶逆变器高频高压的干扰,笔划轨迹变得明显,与实际所写轨迹不符。除了需要在硬件上加滤波电容外,软件中也需要进行一定的修正。这里,采用3点均值滤波的方式来减小噪声干扰的影响。
在读到第一个点时,不做处理;读到2个点时,取这2个值的平均。这样,得到的坐标数据量不会不足,而且均值滤波可以很好地消除噪声的影响。
读汉字码是通过读有名管道来实现的。经过实验,发现HW006在发送汉字码时,偶尔会出现发送的个数与所设置的不符。我们设置的识别字个数是5个,共10字节的数据。但如果所写的汉字比较简单,HW006可能识别不了5个汉字,这样发送给管道的数据不足10字节,结果会造成最终显示错误。为此,在读取汉字码的开始和结束处分别加一个起始位和结束位,这样根据读取管道得到的汉字码个数和起始位、结束位来判断识别结束,将最终得到的识别汉字正确地显示出来。
4 结论
在“PXA255+Linux+Qtopia”平台上的运行及测试结果表明手写识别率能达到95%以上。由于HW006也实现了触摸屏控制器的功能,在硬件结构上完全可以代替原来的触摸屏控制器,因此并没有增加硬件的成本和复杂度。从上面的分析可以清楚地看出,此设计方案具有实用性和普遍意义,完全可以应用于其他嵌入式平台上。

|