搜索
bottom↓
回复: 40

从零开始学VC系列教程之 四.并口控制与类的使用 【恢复】

[复制链接]

出0入0汤圆

发表于 2008-11-15 19:32:25 | 显示全部楼层 |阅读模式
从零开始学VC系列教程之 四.并口控制与类的使用

课程之前:这一章让大家等很久了,一直在考虑并口操作应该怎么写.其实这是一个很简单的课题,因为是基于成熟操作类的基础上的,我们主要是学习如果使用网上查到的资料,这一点很关键,只有学会了利用各种资源,才能自主学习取得进步,同时,也可以有效的提高开发效率.

学习目标:掌握VC下并口程序的方法及类的使用.

课程详解:

参照第一章新建一个基于对话框的Vc工程,名称定义为Eg04.



图01 (原文件名:01.JPG)  

类型选基于对话框.

在本例中,我们要用到一些资源,现列出如下

WinIo.sys

WinIo.dll 这是一个动态库,与WinIo.sys完成同并口的连接.

WinIo.lib 这是为静态调用提供的引入库文件.虽然引入库文件和静态库文件都是以Lib为扩展名的,但实际上有本质的区别.

WinIo.h  这是IO操作的头文件.

ParallelPort.cpp 这是一个并口操作类,用于同WinIo接口,并定义了相关的操作函数.虽然这个类用于同WinIo的操作接口,但这个类并不是从WinIO派生的,只是一个独立的自定义类.至于类的自定义,以前我们也提到过.

ParallelPort.h   这是并口类的头文件.

这几个文件是可以从网上下载到的,并不是我做的,所以这个动态库大家就不用问我要源码了,因为我也没有.

首先,把WinIo.lib WinIo.h ParallelPort.cpp ParallelPort.h拷贝到工程目录中,后面马上就要用到.再把WinIo.Dll WinIo.sys拷贝到工程目录的Debug目录中,以后工程发布后,这两个文件要跟随工程一起.

下面添加引入库到系统中,点击[工程]->[设置]在弹出的对话框中选择[连接]标签,然后在[对象/库模块]中加入WinIo.lib完成后如下图.



图02 (原文件名:02.JPG)  

 然后加入并口操作类的头文件.一般来说,网上可以下载到的源码都是以类的形式给出的,VC的好处也在于可以把一个操作封装成类,以便在不同的工程中调用.如图,双击类管理器中的Ceg04Dlg在弹出的文件中加入#include "ParallelPort.h" //添加并口类头文件



图03 (原文件名:03.JPG)  

同时,还要定义一个类变量,用于并口类的操作. 在刚打开的类定义文件中找到CEg04Dlg类,并加入一个类变量m_Port,完成后如下图所示



图04 (原文件名:04.JPG)  

为了操行方便,把并口操作类也加入到工程中,点击[FileView]标签,标签位置在类管理类下面,见上图中的[FileVi…]然后在[Source Files]中加入ParallelPort.cpp在[Header Files]中加入ParallelPort.h这样,就可以在类管理中看到我们所用到的并口操作类了,同时也可以方便的查阅类函及成员变量.

下面在界面中加入六个按钮和两个文本编辑框,方法前面已经介绍多次.完成后如下图



图05 (原文件名:05.JPG)  

其中,各控件ID如下

上面的编辑框 IDC_EDIT_READ     用于显示收到的数据

下面的编辑框 IDC_EDIT_WRITE    用于填写要发送的数据

读数据口         IDC_BTN_DREAD         用于读取并口数据总线

写数据口         IDC_BTN_DWRITE   用于写并口数据口数据

读控制口         IDC_BTN_CREAD         用于读取并口控制总线

写控制口         IDC_BTN_CWRITE         用于写并口控制口数据

读状态口         IDC_BTN_SREAD         用于读并口状态总线

并口流水灯         IDC_BTN_LED                  用于在数据线上输出流水灯效果

先要介绍一下并口,以便理解接下来的操作是什么意思.以下一些关于并口的介绍,摘自互联网.





并口SPP模式寄存器定义

数据寄存器(基地址)

位         引脚:D-sub         信号名         信号源         是否在连接器处倒相         引脚:Centronics 

0        2        数据位0        PC        否        2

1        3        数据位1        PC        否        3

2        4        数据位2        PC        否        4

3        5        数据位3        PC        否        5

4        6        数据位4        PC        否        6

5        7        数据位5        PC        否        7

6        8        数据位6        PC        否        8

7        9        数据位7        PC        否        9

注:控制寄存器的第5位控制数据位是否能够输出。





状态寄存器(基地址+1)

位         引脚:D-sub         信号名         信号源         是否在连接器处倒相         引脚:Centronics 

3        15        nError        外设        否        32

4        13        Select        外设        否        13

5        12        Paper Out        外设        否        12

6        10        nAck        外设        否        10

7        11        Busy        外设        是        11

注:1,2位未定义。



控制寄存器(基地址+2)

位         引脚:D-sub         信号名         信号源         是否在连接器处倒相         引脚:Centronics 

0        1        nStrobe        PC        是        1

1        14        nAutoLF        PC        是        14

2        16        nInit        PC        否        31

3        17        nSelectIn        PC        是        36



注: 连接器中没有提供的附加位:

4:4:中断启用,此位为1时,IRQ从nAck送往系统的中断控制器;为0时,IRQ不送往中断控制器。

5:5:双向控制端口的方向控制位,此位为0时,输出启动;为1时,不能输出;控制端口可以读取外部逻辑电平。

6、7:未定义。



学过单片机或相关知识的应该可以看懂表格中的意思了,上面罗列的是除去电源及地线后可用到的IO口,数据口8位,由状态寄存器第五位决定能否输出,状态口共5位,控制口共4位.一般我们只用到数据口来传输数据.一般来说,并口基地址是0x378,也就是数据寄存器的地址,在并口类中默认.明白了这些以后,就可以对并口进行相应的操作了.

接下来要在程序初始化时初始化并口,在前面的操作中,定义了一个类变量m_Port,这个类变量在后面我们将多次用到.首先展开类管理器中的CEg04Dlg双击OnInitDialog()在窗口初始化中加入以下代码.

        //在这里初始化并口

        if(m_Port.InitPort()==TRUE)

        {

                SetDlgItemText(IDC_EDIT_READ,"并口初始化成功,并口地址:0x378");

        }

        else

        {

                SetDlgItemText(IDC_EDIT_READ,"并口初始化失败!");

        }

完成后如下图所示



图06 (原文件名:06.JPG)  

m_Port.InitPort()是并口操作类中的并口初始化函数,传入参数是并口地址,由于类定义时默认了0x378为并口地址,这里可以不用传参数了.如果初始化成功,传回布尔变量TRUE,运行一下,应该可以看到并口初始化成功的信息.

接下来为读数据口添加代码.

双击[读数据口]按钮,在弹出的代码中加入程序如下

void CEg04Dlg::OnBtnDread() 

{

        // TODO: Add your control notification handler code here

        BYTE nPortData=m_Port.ReadData();        //从并口读到数据

        

        CString a,b;                                        

        GetDlgItemText(IDC_EDIT_READ,b);        //获取编辑框中原有的文本

        

        a.Format("\r\n读到数据口数据:%2.2X",nPortData);

        b+=a;

        SetDlgItemText(IDC_EDIT_READ,b);   //写入文本到编辑框

        

        //以下用于将滑块自动移到最后一行

        unsigned char nLine=((CEdit*)GetDlgItem(IDC_EDIT_READ))->GetLineCount();

        ((CEdit*)GetDlgItem(IDC_EDIT_READ))->GetLineCount();

        ((CEdit*)GetDlgItem(IDC_EDIT_READ))->LineScroll(nLine);

}

完成后如图所示(图8)



图08 (原文件名:08.JPG)  

这样就可以从并口读到数据了.同样的,可以添加控制口,状态口的按钮响应代码,用于读到控制口及状态口,方法相同,这里就不再详叙了.不同的是读控制口时,用到的函数是m_Port.ReadCtrl();读状态口用到的函数是m_Port.ReadState();

再有一个问题要说一下,编辑框默认状态下是单行的,也就是说,我们的换行操作是没有用的.可以鼠标右击编辑框,在弹出的菜单中选[属性],并修改其属性如下图所示(图7)



图07 (原文件名:07.JPG)  

下面来添加写数据操作.在写数据操作中,我们要换一种方法来读写文本编辑框了.

首先鼠标右击下面的写操作编辑框,在弹出的菜单中选择[建立类向导],英文版的VC请根据翻译.



图09 (原文件名:09.JPG)  

然后会弹出一个类向导对话框, 选择[MemberVariables]标签卡后显示如下.



图10 (原文件名:10.JPG) 

 ,在ID列表中,我们可以看到窗口中为控件添加的ID号,双击[IDC_EDIT_WRITE]会弹出另一个对话框,将各框中的内容修改如下图



图11 (原文件名:11.JPG) 

第一个框中的m_WriteEdit是我们为IDC_EDIT_WRITE这个编辑器定义的一个类变量名,这个类变量会自动与编辑框IDC_EDIT_WRITE关联,在以后的操作中用到.

确定后双击[写数据口]按钮,为写数据口按钮添加代码,完成后如下

void CEg04Dlg::OnBtnDwrite() 

{

        // TODO: Add your control notification handler code here

        CString a;        

        unsigned char b=0;

        

        m_WriteEdit.GetWindowText(a);        //获取编辑框中文本

        a.MakeUpper();//全部转换为大写



        if(a=="")

        {

                MessageBox("发送内容不能为空!");

                return;

        }



        for(unsigned char i=0;i<a.GetLength();i+=3)

        {

                if(i+2>a.GetLength())

                {

                        MessageBox("数据格式填写不正确!");

                        return;                        

                }

                

                if(a.GetAt(i)>='A' && a.GetAt(i)<='Z') b=(a.GetAt(i)-55)*16; //判断填入的是字母还是数字,并把字符转换成十六进制数

                else if(a.GetAt(i)>='0' && a.GetAt(i)<='9') b=(a.GetAt(i)-0x30)*16;

                else

                {

                        MessageBox("数据格式填写不正确!");

                        return;                

                }



                if(a.GetAt(i+1)>='A' && a.GetAt(i+1)<='Z') b+=(a.GetAt(i+1)-55);

                else if(a.GetAt(i+1)>='0' && a.GetAt(i+1)<='9') b+=(a.GetAt(i+1)-0x30);

                else

                {

                        MessageBox("数据格式填写不正确!");

                        return;                

                }



                m_Port.WriteData(b);

        }

}

这里可能有点长,其实与第三章的发送是一样的,增加了一点容错处理而已.在这里,我们用m_WriteEdit.GetWindowText(a);来获取编辑框中文本, m_WriteEdit是开始时候在类向导中定义的变量,GetWindowText是一个窗口函数,因为文本编辑框也认为是窗口,所以窗口操作函数是通用的,由于m_WriteEdit与文本框IDC_EDIT_WRITE关联,获取的是文本框中的内容.同样,由于m_WriteEdit是CEdit变量,于是就可以有所有CEdit的所有属性,这与结构变量有点相似,大家可以慢慢体会.其余口的操作类似,不再重复说了.

这个并口类还有很多功能函数,这里也清一下.

#define        PIN_STROBE 1

#define PIN_AUTO   14

#define        PIN_D0           2

#define        PIN_D1           3

#define        PIN_D2           4

#define        PIN_D3           5

#define        PIN_D4           6

#define        PIN_D5           7

#define        PIN_D6           8

#define        PIN_D7           9

#define PIN_ERROR  15

#define PIN_INIT   16

#define PIN_SELIN  17

#define PIN_ACK           10

#define PIN_BUSY   11

#define PIN_PE           12

#define PIN_SLCT   13

这些是对IO口的定义,用于单个IO口的操作,操作函数有以下几个

         BOOL SetPinLogic(int nPin,BOOL bLogic);

        //设置指定引脚,bLogic=1高电平,bLogic=0低电平

        BOOL GetPinLogic(int nPin);//得到指定引脚的电平

        BOOL SetPinL(int nPin);//设置指定引脚为低电平

        BOOL SetPinH(int nPin);//设置指定引脚为高电平

以上些都是这个并口类的函数了,有了这些,我想大家也就可以随便做点东西了,记得曾有过用并口直接驱动LCD的例子,建议也试一下.

最后一个按钮是流水灯,其实这个对于大家来说并不难,我们也提供一个例子.双击[并口流水灯]添加流水灯代码.IO口低电平有效.

void CEg04Dlg::OnBtnLed() 

{

        // TODO: Add your control notification handler code here

        unsigned char nDataIO=0x01;

        CString a,b;                                                



        unsigned char nCData=m_Port.ReadCtrl(); //读控制寄存器数据

        nCData&=0xDF; //保证第五位为低,使能IO输出

        m_Port.WriteCtrl(nCData); //写控制口数据



        for(char i=0;i<8;i++)

        {

                m_Port.WriteData(0xff-nDataIO);



                GetDlgItemText(IDC_EDIT_READ,b);        //获取编辑框中原有的文本

                a.Format("\r\n流水灯数据[%d]:%2.2X",i+1,0xff-nDataIO);

                b+=a;

                SetDlgItemText(IDC_EDIT_READ,b);   //写入文本到编辑框

                                //以下用于将滑块自动移到最后一行

                unsigned char nLine=((CEdit*)GetDlgItem(IDC_EDIT_READ))->GetLineCount();

                ((CEdit*)GetDlgItem(IDC_EDIT_READ))->GetLineCount();

                ((CEdit*)GetDlgItem(IDC_EDIT_READ))->LineScroll(nLine);



                nDataIO<<=1;



                Sleep(200); //延时200ms

        }

}

接上硬件可以看到,按一下出现一次流水灯效果,由于不方便按硬件,就没有试过了.

这一章就先到这里了.建议大家自己想个作品来试一下,同时也希望大家分享一下自己的学习及实验感想,把作品也发上来庆祝一下.

以下是整个工程及教程内容的下载

ourdev_500674.rar(文件大小:1.07M) (原文件名:Eg04All.rar)



从零开始学VC系列教程 一.信息显示实验

从零开始学VC系列教程 二. 对话框及常用控件实验

从零开始学VC系列教程 三. 串口通信及自定义消息

本贴被 bqmcu 编辑过,最后修改时间:2008-11-16,09:46:42.

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2008-11-15 19:54:22 | 显示全部楼层
呵呵。又坐上沙发了。

学习中。。。

出0入0汤圆

发表于 2008-11-15 20:28:41 | 显示全部楼层
错过沙发了,精品一定要顶!!!

出0入0汤圆

发表于 2008-11-15 20:43:36 | 显示全部楼层
唉,没抢到!  支持楼主。

出0入0汤圆

发表于 2008-11-15 20:45:08 | 显示全部楼层
帮你顶一下

出0入0汤圆

发表于 2008-11-15 20:54:47 | 显示全部楼层
支持!



加油。

出0入0汤圆

发表于 2008-11-15 20:58:28 | 显示全部楼层
支持

出0入0汤圆

发表于 2008-11-15 21:06:06 | 显示全部楼层
终于等到了,不得不顶啊!

出0入0汤圆

发表于 2008-11-16 00:14:25 | 显示全部楼层
先留个脚印,

出0入0汤圆

发表于 2008-11-16 01:23:40 | 显示全部楼层
下载先!现在准备学STM32了,以后有时间再学这个!

出0入0汤圆

发表于 2008-11-16 01:38:36 | 显示全部楼层
终于出4了,期待更多

出0入0汤圆

发表于 2008-11-16 09:37:27 | 显示全部楼层
建议楼主把前三章的链接也放一起来,方便大家

出0入0汤圆

发表于 2008-11-16 11:31:20 | 显示全部楼层
留着等以后看

出0入0汤圆

发表于 2008-11-16 17:43:11 | 显示全部楼层
支持一个

出0入0汤圆

发表于 2008-11-16 20:46:03 | 显示全部楼层
好东西,记号

出0入0汤圆

发表于 2008-11-17 08:40:59 | 显示全部楼层
好!

出0入0汤圆

发表于 2008-11-17 10:07:26 | 显示全部楼层
很好,论坛兄弟们的VC水平又能得到提升了

出0入0汤圆

发表于 2008-11-17 12:53:54 | 显示全部楼层
谢谢

出0入0汤圆

发表于 2008-11-17 15:11:53 | 显示全部楼层
支持,暂时没有时间学这个.

但是总要学的,非常感谢.

另,楼主位第3行,"如果"是笔误,应该是"如何".

出0入50汤圆

发表于 2008-12-13 19:59:47 | 显示全部楼层
感觉象看越狱,看完一期,就开始盼下一期...............



顶!

出0入0汤圆

发表于 2008-12-14 00:34:54 | 显示全部楼层
感觉象看越狱,看完一期,就开始盼下一期............... 



支持!

出330入0汤圆

发表于 2008-12-14 21:32:53 | 显示全部楼层
学一门上位机编程还是很有必要的,有时候去找个工具助手,冒着中病毒的危险下下来一看,是要收费的,或者功能达不到自己要求的,这个时候,就要自己动手,丰衣足食啦!

出0入0汤圆

发表于 2008-12-30 09:28:52 | 显示全部楼层
期待第五课发布

出0入0汤圆

发表于 2008-12-30 11:41:08 | 显示全部楼层
自己动手丰衣足食!

出0入0汤圆

发表于 2008-12-30 11:47:57 | 显示全部楼层
很有价值的教程!

出0入0汤圆

发表于 2009-12-20 15:34:27 | 显示全部楼层
不错。。。。  顶。。。

出0入0汤圆

发表于 2010-3-25 14:00:45 | 显示全部楼层
谢谢! 顶

出0入0汤圆

发表于 2010-12-8 23:30:33 | 显示全部楼层
MARK 一下 好找~

出0入0汤圆

发表于 2010-12-9 08:53:58 | 显示全部楼层
好。。

出0入0汤圆

发表于 2011-7-5 23:19:53 | 显示全部楼层
不错,好东西,收藏了。

出0入0汤圆

发表于 2011-7-6 00:35:30 | 显示全部楼层
vc 学习 。收藏

出0入0汤圆

发表于 2011-7-14 22:50:35 | 显示全部楼层
vc学习,收藏

出0入0汤圆

发表于 2011-7-14 23:52:45 | 显示全部楼层
很好啊

出0入0汤圆

发表于 2011-7-15 16:43:44 | 显示全部楼层
vc学习,收藏

出0入0汤圆

发表于 2011-7-16 21:49:46 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-10-6 15:50:38 | 显示全部楼层
回复【楼主位】bqmcu 哆啦A梦
-----------------------------------------------------------------------
太感谢楼主了,虽然我工作3年了,但是刚刚入这行,是个愣头青,还是VC6用的亲切,教程很好。

出0入0汤圆

发表于 2011-10-20 12:56:50 | 显示全部楼层
挺好的,原来用WINTC玩过并口流水灯,可是现在DOS环境已和消失了。。

出0入0汤圆

发表于 2012-9-25 16:02:35 | 显示全部楼层
继续收藏···
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 07:11

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表