C语言接口编程技术_第1页
C语言接口编程技术_第2页
C语言接口编程技术_第3页
C语言接口编程技术_第4页
C语言接口编程技术_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第二节C语言接口编程技术一、C语言特点C语言以其简洁、灵活、表达能力强、产生的目标代码质最高、可移植性好为其基本特点而著称于世,详细归纳起来,它具有以下几个特点:C语言兼容了其他计算机语言的一些优点,其程序结构紧凑、简洁、规整,表达式简练、灵活、实用。用C语言编写的程序可读性强、编译效率高。C语言具有丰富的数据类型。在系统软件中,特别是操作系统中,对计算机的所有软件、硬件资源要实施管理和调度,这就要求有相应的数据结构作为操作基础。C语言具有5种基本的数据类型和多种构造数据类型(数组、结构、联合、枚举)以及复杂的导出类型。C语言还提供了与地址密切相关的指针及其运算符。C语言具有丰富的运算符,多达

2、科种。丰富的数据类型与丰富的运算符相结合,使C语言具有表达灵活和效率高等特点。语言是一种结构化程序设计语言,特别适合于大型程序的模块化设计:C语言是处于汇编语言和高级语言之间的一种中间型程序设计语言,它既具有高级语言面向用户、可读性强、容易编程和维护等特点,又具有汇编语言面向硬件和系统,可以直接访问硬件的功能,C语言的运行效率可以与汇编语言媲美。C语言具有较高的可移植性。在C语言的语句中,没有依赖于硬件的输人输出语句,程序的输人输出功能是通过调用输人输出函数实现的,而这些函数是由系统提供的独立于C语言的程序模块。从而便于硬件结构不同的计算机之间实现程序的移植。二、C语言端口操作编程利用C语言进

3、行计算机的接口编程,主要是利用C语言对端口输人输出操作的支持,PC/XT/AT微型计算机上运行的几种C语言版本,都支持对端口的输人输出操作。C语言对这些端口的输人输出函数以库函数的形式进行了封装,这些库函数实际上调用了汇编语言中的INIUT指令,开发者不必自己开发C语言的接口函数,简化了开发难度。端口操作函数C程序为了要访问端口(即口地址),专门设计了端口输人输出函数,它们是intinport()intinpartb()intoutport()intoutportb()这四个函数的函数原型都在函数库dos.h中,所以在使用这四个函数之前,需要在程序中包含进库函数dos.ho端口读函数C语言中的

4、读端口的函数有两个:inport()和inportb()。他们都是从指定的端口读人数据。其调用形式为:intinpart(intportintinportb(intport)inport()函数从指定的端口port读人一个字长的值,其长度为16位;inportb()函数从指定的端口part读人一个字节,其长度为8位。如:下列语句将从口地址2F0H中得到一个字长的数:unsignedintc;c=import(Ox2f0);端口写函数C语言中向端口输出数据的函数有两个:outport()和outportb()o他们都是向指定的端口输出数据。其调用形式为:voidoutport(intport。i

5、ntworn)voidoutportb(intpeat,charbyte)outport()函数向指定的端口art输出一个字长值word,其长度为16位;outportb()函数向指定的端口port输出一个字节值byte,其长度为8位。如:下列语句将数4095送往口地址为2F2H和2F3H的接口中去:outport(Ox2f2,4095);数据发送时.程序将4095转变为二进制数,低8位送2F2H,高8位送2F3H端口访问实例(1)微机发声在PC机主板内装有定时器与计数器(CTC),芯片为8253-5。其中1号计数器定期向4个DMA通道请求一次I/O传送;0号计数/本时器为通用的计数器,实现日

6、时钟;2号计数/定时器支持扬声器的声调发生器。上述CTC的口地址已由机器内部译码,口地址为4Q-43H。主机板上还安装有8255并行接口,其口地址为60-63H,已由机上译码。用CTC配合8255产生声音的原理如图9一1所示。由图9一1可知.C程序实现发声喇叭,应分别访问42H,43H,61H,并在次产生友声顿率访问61H时将原输人的字节的bit0和bit1置1才能使喇叭发声。面我们列出发声程序,主要为了理解上述端口操作函数的应用二该程序运行时。可在屏幕上显示由随机数得到的频率数,同时发出相应的声音二由于声音是断续的(开与关8255),同时频率数是随机的,所以使人得到一种似乎是旧式科学幻想电影

7、中的音乐效果。程序清单如下:#defineDELAYZUODavoidsound(unsignedintfreg);main()dodofreg=rand();while(freg5000);sound(freg);while(!kbhi();voidsound(unsignedintfreg)unsignedunionlongdivisor;unsignedcharc2;count;unsignedcharp;count.divisor=119328O/freg;outportb(Ox43,Oxc6);outpartb(0 x42,count.c0);?转换完成后,将转换结果用函数inpar

8、tb()采集到计算机内并进行处理。所采集到的8个通道数据,是十进制数0一2.55。我们暂不作工程量转换,只是原理性地将它们在屏幕上轮流显示。上述ALE,START,OE等信号,主要采用类似于汇编语言中的累加器输人输出方法,即采用inpartb()和outpartb()函数。作为外设的口地址,需A9?l,故选用2F0H,2F1H,2F2H,这很方便地可由A0-A9地址线输人进行译码。全部用C语言写出的数据采集系统的清单如下:main()inti;unsignedcharc;unsignedchara;doa=0;dooutportb(Ox02f0,a);outportb(0 x02f1,a);/

9、*发送通道地址并启动转换*/for(i=0;i100;i+);c=inportb(Ox02f2);/*采集转换结果*/if(a=6)printf(%03d,c);elseprintf(%03dn,c);while(+a=7)for(i=0;i=10000;i+);while(!kbhit();三、中断服务程序1,中断的概念所谓的中断,是指CPU在正常运行一个程序时,由于程序中的事先安排或是由外界事件的触发,导致CPU中断了当前正在运行的程序,而转人相应的服务程序中去的过程。这些引起程序中断的事件称为中断源,程序安排的事件是指中断指令,程序执行到中断指令后,立即跳转到相应的服务程序中。中断指令可

10、以看作是计算机内部事件,而对应的外部事件则是指计算机中某些接口上的设备发出的请求中断执行的信号。这些信号称为中断请求信号。中断服务程序在执行完后,将返回原来程序中的断点处,继续执行原来的程序,这称为中断返回。有时可能同时有多个中断源产生,而CPU在响应这些中断时需按照一定的顺序进行,这称为中断的优先级,优先级高的中断首先被响应,而优先级低的中断则暂不响应,这称为挂起。也可以在程序中强迫CPU对某些中断不予响应,这称为中断屏蔽。实质上,CPU在响应中断时,是按照中断源所对应的地址,引导程序跳转到相应的服务程序中去,这个与中断源有着一一对应关系的地址称为中断向量。PC机有两种类型的中断,即软中断和

11、硬中断。软中断由执行某些指令产生;硬中断则是由接口设备引起。PC机在其内部存储了256个中断向量,每一个占用4个字节。每个中断向量用其类型码加以区别。实际执行过程中,CPU根据其类型码,将其乘以4得到中断向量的地址,即中断服务程序的入口地址。2.用TurboC编写中断程序的方法用TurboC编写中断程序可用三部分来实现:即编写中断服务程序、安装中断服务程序、激活中断服务程序,下面分述之。编写中断服务程序中断服务程序的任务是,当产生中断后,脱离被中断的程序,使系统执行中断服务的程序,它必须打断当前执行的程序,急需完成一些特定操作,因此该程序中应包括一些能完成这些操作的语句和函数,因涉及DOS的重

12、入问题,因而不应该有与DOS系统调用有关的库函数,如printf(),sprint()等。由于产生中断时,必须保留被中断程序中断时的一些现场数据,如保存断点等(这些值都在寄存器中,若不保存,当中断服务程序用到这些寄存器时,将改变它的值)、以便恢复中断时使这些值复原。从而继续执行原来中断了的程序。TurbaC为此提供了一种新的函数类型interrupt,它将保存由该类型函数参数指出的各寄存器的值,而在退出该函数,即中断恢复时,再复原这些寄存器的值,因而用户的中断服务程序必须定义成这种类型的函数。如中断服务程序名定为myp,则可将这个函数说明成这样(其中的参数将保存各寄存器值):voldinter

13、ruptmyp(unsignedbp,unsigneddi,unsignedsi,unsignedds,unsignedes。unsigneddx,unsignedcx,unsignedbx,unsignedax,unsignedip,unsignedcs,unsignedflags)若是在小模式下的程序,只有一个段,在中断服务程序中用户就可以像用无符号整数变量一样,使用这些寄存器。若中断服务程序中不使用上述寄存器,也就不会改变这些寄存器原来的值,因而也就不需保存它们,这样在定义这种中断类型的函数时,可不写这些寄存器参数.如可写成:voidinterruptmyp()对于硬中断,则在中断服务程

14、序结束前要送中断结束命令字给系统的中断控制寄存器,其口地址为。o.中断结束命令字也为ox2o,即outportb(0 x20,0 x20);在中断服务程序中,若不允许别的优先级较高的中断打断它,则要禁止中断,可用函数disable()来关闭中断。若允许中断,则可用开中断函数enable()来开放中断。安装中断服务程序定义了中断服务函数后、还需将这个函数的人口地址填人中断向量表中,以便产生中断时程序能转人中断服务程序去执行。为了防止正在改写中断向量表时,又产生别的中断而导致程序混乱,可以关闭中断,当改写完毕后,再开放中断。一般的,常定义一个安装函数来实现这些操作,如:voidinstall(vo

15、idinterrltpt(*faddr(),intinum)disable();setvect(inum,faddy);enable);其中faddy是中断服务程序的人口地址,其函数名就代表了人口地址,而inum表示中断类型号,setvect()函数就是设置中断向量的函数,上述定义的install。函数,将完成把中断服务程序入口地址填人中断向量inum中去。中断服务程序的激活当中断服务程序安装完后.如何产生中断,从而执行这个中断服务程序呢?如前所述,对硬件中断,就要在相应的中断请求线(IRQj,i=0,l,2,,7)产生一个由低到高的中断请求电平,这个过程必须由接口电路来实现,当中断产生时,便

16、会执行中断。对于软中断,有几种调用方法二由于中断类型的函数不同于用户定义的一般函数,因此也不能用调用一般函数的方法来调用它,一般软中断调用可用如下方法:使用库函数geninterrupt(中断类型号)在主函数中适当的地方,用setvect函数将中断服务程序的地址写人中断向量表中,然后在需要调用的地方用geninterrupt()函数调用。直接调用如已用setvect(类型号,mvp)设置了中断向量值,贝I可用myp()直接调用,或用指向地址的方法调用:(*myp();也可用在TurboC程序中插人汇编语句的方法来调用,如:setvect(inum,myp);通常上述的调用可定义成一个中断激活函

17、数来完成,该函数中可附加一些别的操作,主程序在适当的地方调用它就可以了。恢复被修改的中断向量这一步视情况而定,当用户采用系统己定义过的中断向量,并且将其中断服务程序进行了改写,或用新的中断服务程序代替了原来的中断服务程序,为了在主程序结束后,恢复原来的中断向量,以指向原中断服务程序,可以在主程序开始时,存下原中断向量的内容,这可以用取中断向量函数getvect(来实现,如j=(char*)getvect(Ox1c),这样j指针变量中将是0 x1c中断服务程序的人口地址由于DQS已定义了0 x1c中断的服务程序入口地址,但它是一条无作用的中断服务,因而我们可以利用d。中断来完成一些用户想执行的一

18、些操作,实际上就是用户自己的中断服务程序代替了原来的。当主程序要结束时,为了保持系统的完整性,我们可以恢复原来的中断服务人口地址,如可用以下方法实现。setvect(0 xlc,j);中断编程举例下面以采用中断方式的信号采集为例说明C语言中断编程的方法。图9-3示出了这个光电隔离信号采集电路的示意图。它采用硬中断方式,共有多路模拟信号输人通道,该电路在模拟转换部分和PC机数字输入部分之间有一光电隔离模块,使PC微机和信号现场部分进行了隔离,使得它们之间不发生电的联系,而通过光作为媒介来传递转换后的信号,这样可有效地防止一些现场电的于扰,并保护微机不受偶然事故的破坏。高心D转换开关1光存地址器二

19、制逻结束数据总线设置0 x300地址总线控制总线放大器采規N采样逋道通道号高心D转换开关1光存地址器二制逻结束数据总线设置0 x300地址总线控制总线放大器采規N采样逋道通道号0 x303I0 x305启动器JZToLtM图9-3光电隔离信号采集示意图它的工作过程是这样的,首先清AID中断寄存器.使其变低,当AID转换完成后,利用转换完成信号(EoF)将其置1,从而产生IRQ2中断请求信号,该寄存器口地址设为0 x30,利用tportb(0 x303,0)可将其清0。这样就为采样作好了准备,接着选择信号输人通道,其口地址为0 x300。若用ch表示输入通道号(0-47),则可用outporkb

20、(0 x300,ch)来选择输人通道,接下去便启动A/D开始转换,其口地址为0 x301,即outport(0 x301,1),使数模转换芯片开始进行转换,函数enairq9()完成这些任务。一旦转换完成。它便发出EOF信号,该信号将A/D中断寄存器置成高电平输出,因而产生1RQ2中断请求信号;当PC机接到该中断后,便进人中断服务程序int9()。该程序首先禁止中断,以防破坏取数。由于光电隔离的存在,将光变成PC微机一侧的数据有时间延迟。因而程序中用了无语句的for循环来进行延迟,用n控制延迟时间:由于使用PC的8位数据总线,因而对于I2位A/D转换电路,转换后的数据要分两次取走,先取低8位,

21、后取高4位,它们用了口地址Ox304和0 x305。取数用inportb()函数。12位数据取走后,中断服务程序就完成了任务,因而必须最后发送硬中断结束命令outportb(Ox20,Ox20,)为下次中断作好准备.并开中断。由于硬中断IRQ2的中断类型号为Ox0a,on_intr9(),函数用来设置中断入口地址,将中断服务程序int9的人口地址置人0 x0a指出的偏移地址中。完整的TurboG程序如下:#defineN8D#include#include#include#includeintstart,ch,flag;voidinterruptint9();voidon_intr9();vo

22、idenairq9();voiddisirq9();intad641;inti;char*ab;main()47);charc;clrscrt();47);printf(PleaseinputA/Dchannelnumber(0ch=choice_channel);on_infer();i=0;dochscr();flag=0;enairq9();to:if(flag=0)gototo;i+;adi=ab;lf(i=640)for(i=1;1=640;1+)printf(”%d,adi);i=0;printf(pressQkeytoquit);c=getch();if(c=q)break;continue;while(1);disirq9();printf(”nr);exit(0);intchoice_channel()into;staticchartem4=0,a,a,a;i=0;dotempi=getch();if(isdigit(temi)&(i=0&(cN;j+);/*时间延迟*/a=inportb(0 x304);/*取低8位数*/for(j=0;jN;j+);b=inportb(0 x305);/*取高4位数*/ab=(b

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论