工控网首页
>

应用设计

>

Turbo C下发动机电子控制界面解决方案

Turbo C下发动机电子控制界面解决方案

2004/8/13 9:54:00
引言   在发动机的电子控制开发过程中,用得比较多的语言便是c和汇编,汇编以其速度快,响应及时而受到广大编程者的欢迎,虽然c的速度,稍逊于汇编,然而c的可读性吸引了为数不小得编程者。发动机的实时性要求很高,所以编程者们都尽可能使自己开发的程序更接近于硬件底层。本编主要介绍在Turbo C环境下的界面编程解决方案,程序运行于DOS环境,从而绕过了window的时钟延迟(delay)。在DOS下编写界面是一件很令人苦恼的事,不仅要考虑汉字显示问题而且还要考虑Turbo C下的图形显示以及各种交互动作。Turbo C是Borland公司一款经典之作,虽然Borland公司早已不再发展这个编译器,但是Turbo C编译器的小巧精致使得它在编程者的心目中的地位不曾下降过,加上大多数人都是在这款编译器的基础上开始c的编程之路,因而对Turbo C编译器更熟悉一些,在DOS下进行电子控制实时开发时更偏向于Turbo C。作者把Turbo C的界面开发分为几个关键部分:图形卡初始化;字体字库导入;交互功能实现;实现界面。 1.图形卡初始化   如果进行c语言学习,Turbo C是一个较好的编译器,在上面做软件相对visual c++等一些windows集成软件来说,是相对困难了一些,好多编程者在掌握c语言之后,便转向vc++进行软件开发,这几年,Turbo C的软件开发资料相对较少,所以开发也变得困难起来。而图形卡的初始化,在资料中也是略微提到或者忽略不提,给编程者在编程之初造成了不小的困难。   在界面开发中,程序主要都是在图形方式下运行的,Turbo C提供了丰富的图形函数,其头函数为graphics.h ,但是函数的正确使用不能光使用#include,我们需要确保有显示器图形驱动程序*.BGI,同时开发环境的Opention/Linker中的Graphics.lib选为on,这样就能正确使用图形函数了。 在DOS环境下,设Turbo C放在c盘turboc2目录下,下边是实现图形卡初始化的关键步骤: 1.将驱动程序EGAVGA.BGI转换成目标文件EGAVGA.OBJ:   C:\TURBOC2\BGI>BGIOBJ EGAVGA   按同样的办法,将字体文件*.CHR转换成目标文件*.OBJ:   C:\TURBOC2\BGI>BGIOBJ TRIP   C:\TURBOC2\BGI>BGIOBJ LITT   C:\TURBOC2\BGI>BGIOBJ SANS   C:\TURBOC2\BGI>BGIOBJ GOTH 2.将上述建立的OBJ文件加入到GRAPHICS.LIB库文件中,具体方法如下:   C:\TURBOC2\BGI>TLINK C:\TURBOC2\LIB\GRAPHICS.LIB+EGAVGA   C:\TURBOC2\BGI>TLINK C:\TURBOC2\LIB\GRAPHICS.LIB+TRIP   C:\TURBOC2\BGI>TLINK C:\TURBOC2\LIB\GRAPHICS.LIB+LITT   C:\TURBOC2\BGI>TLINK C:\TURBOC2\LIB\GRAPHICS.LIB+SANS   C:\TURBOC2\BGI>TLINK C:\TURBOC2\LIB\GRAPHICS.LIB+GOTH   也可以使用TLIB、PRJ程序代替TLINK。 3.在程序中调用initgraph()函数前,应加上如下语句:   registerbgidriver(EGAVGA-driver);   它通知连接程序把EGAVGA驱动程序装入用户的执行程序中,同样在装入字体文件之前要加上如下语句:   registerbgifont(字体文件名); 4.通过上述处理后,编译连接后的执行程序就可以在任何目录下运行了。这时,将屏幕初始化为图形模式的函数可改写为:   void InitGra(void)   {int GD=DETECT,GM;   registerbgidriver(EGAVGA_driver);   registerbgifont(triplex_font);   registerbgifont(small_font);   registerbgifont(sansserif_font);   registerbgifont(gothic_font);   initgraph(&GD,&GM,""); } 2.字体字库导入 汉字字库的加入,在交互过程中会减慢程序的响应速度,影响甚小,但是如果可以避免不用汉字的话,尽量不用汉字。然而发动机电子控制不仅要求实时,也要求有一个友好的控制界面来辅助控制。因此我们以16点阵汉字为例,在UCDOS7.0中有一个16*16的点阵汉字字库,主要用于屏幕显示。国标规定汉字用内码表示,内码为两个字节,为了保证和西文兼容,汉字系统的内码必须同时允许ASCII码和汉字内码,两者之间不应该冲突,所以目前规定每个字节只用7位,若两个字节的最高为位1,则该字符为汉字。在控制界面中写下了如下的16点阵汉字显示函数。 void Outtextxy16(int x,int y,int Wid,char *Str) { unsigned Zcode,Bcode; int i,j,k,Rec,Color,textwid=textwidth("D"); long Len; char Buf[32],s[2]; while(*Str) /* till the end of the string */ { if((*Str&0x80)&&(*(Str+1)&0x80)) /* is chinese */ { Zcode = (*Str-0xa1) & 0x07f; /* zone code */ Bcode = (*(Str+1)-0xa1) & 0x07f; /* bit code */ Rec = Zcode*94+Bcode; /* record number */ Len = Rec*32L; /* opersition in hzk16 */ fseek(fp,Len,SEEK_SET); fread(Buf,1,32,fp); /* 72 bit */ for(i=0;i<16;i++) for(j=0;j<2;j++) for(k=0;k<8;k++) if(Buf[i*2+j]>>(7-k) & 1) putpixel(x+j*8+k,y+i,YELLOW); x = x+16+Wid; Str += 2; } else { s[0]=*Str; s[1]=\0; outtextxy(x,y+4,s); x+=textwid; Str+=1; } } return; }   然而只有16点阵函数,对汉字显示来说还是不够的,我们要在程序中导入汉字字库,可以用下边的函数来打开: int OpenLIB(void) /* open 16 chinese */ { if((fp=fopen("c:\\ucdos\\hzk16","rb")) == NULL) ErrMsg(); } 3.交互功能实现   所谓交互性就是指人与计算机之间的一种交流,有两种最基本的交互设备,一是显示器,一是键盘。显示器是计算机用来与人进行交流的,计算机通过显示器来告诉人一些信息。   图形交互功能的实现是一个比较复杂的过程,在一个发动机电子控制界面上,你需要实现数据的采集的同时,又要根据数据来反馈喷射阀的喷射时刻和喷射时间,所以你用到多任务系统。机器进行另一项任务的同时,你需要修改你的各种控制参数,修改控制参数,这时需要用到空格(space),删除(backspace),回车键(return),等各种交互键,在windows集成开发软件下实现这些功能是要稍微容易点,而在DOS下,你要从基础做起,也就是编写各种交互函数,这就不是那么简单了。 1.多任务功能的实现   DOS环境是单任务环境,然而Turbo C编译器却给我们提供了按照某种算法进行多任务的虚拟实现,基本原理是运用了操作系统中的时间片轮换算法概念,在这种算法中,系统将所有的任务按顺序排成一个队列,每次调度时把CPU分配给队首的任务,并令其执行一个时间片,构成微观上轮流运行、宏观上并执行的多任务效果。首先是任务结构的编写,struct stackframe_s处理器的各寄存器存储结构,struct segdesc_s保护模式的段描述子结构,message为消息结构,程序如下: struct proc { struct stackframe_s p_reg; /* process registers saved in stack frame */ unsigned p_ldt_sel; /* selector in gdt giving ldt base and limit*/ struct segdesc_s p_ldt[2]; /* local descriptors for code and data */ unsigned *p_stguard; /* stack guard word */ int p_nr; /* number of this process (for fast access) */ int p_int_blocked; /* nonzero if int msg blocked by busy task */ int p_int_held; /* nonzero if int msg held by busy syscall */ struct proc *p_nextheld; /* next in chain of held-up int processes */ int p_flags; /* P_SLOT_FREE, SENDING, RECEIVING, etc. */ struct mem_map p_map[NR_SEGS];/* memory map */ int p_pid; /* process id passed in from MM */ long user_time; /* user time in ticks */ long sys_time; /* sys time in ticks */ long child_utime; /* cumulative user time of children */ long child_stime; /* cumulative sys time of children */ long p_alarm; /* time of next alarm in ticks, or 0 */ struct proc *p_callerq; /* head of list of procs wishing to send */ struct proc *p_sendlink; /* link to next proc wishing to send */ message *p_messbuf; /* pointer to message buffer */ int p_getfrom; /* from whom does process want to receive? */ int p_sendto; struct proc *p_nextready; /* pointer to next ready process */ sigset_t p_pending; /* bit map for pending signals */ unsigned p_pendcount; /* count of pending and unfinished signals */ char p_name[16]; /* name of the process */ };   任务结构的编写涉及了好多电脑的硬件的问题,本篇部详细讨论这些问题,但是结构弄好了,编写任务进程函数就相对简单多了,根据操作系统的时间片轮换算法概念给每一个进程分配很短一段时间,时间片一过就转化为另一个进<
投诉建议

提交

查看更多评论
其他资讯

查看更多

PLC一体机之EK温度修正使用技巧

S7-300CPU存储器介绍及存储卡使用

0.05级超高精度互感器

DC-DC转换器(电源模块)应用指南——外接滤波电容选配

施罗德最小流量阀的应用范围及优点