您的位置: 嵌入式在线 > 技术中心 > X86 > TurboC在嵌入式PC/104系统中的应用

TurboC在嵌入式PC/104系统中的应用

2007-10-17      嵌入式在线      收藏 | 打印

        本文介绍了TurboC在嵌入式程序设计中的特点,并结合TurboC实例,详细介绍了PC/104系统中,应用中断完成数据采集、处理及显示的方法和技巧。

       1  引言
   

       随着电子技术的高速发展,嵌入式计算机已得到了广泛的应用。PC/104就是专门为嵌入式控制而定义的工业控制总线,它是一种优化的、小型、堆栈式结构的嵌入式控制系统,其有效信号线和控制线完全与PC和PC/AT兼容。

       在PC/104系统中,一般的硬盘是不适用的,常使用Flash EEPROM固态电子盘,其存储空间一般较小,无法使用Windows下的编程语言,而汇编语言的执行速度虽快,但移植性较差,调试较复杂,不宜在复杂系统中使用。TurboC则既有低级语言的直接控制硬件的能力,又有高级语言的灵活性,易于维护,是目前嵌入式PC/104系统中应用较广泛的编程语言。在我们所设计的国产某型大气数据计算机的外场检测仪就是TurboC与PC/104的结合。

       2  用TurboC编写中断服务程序
   

       所谓中断是指CPU在正常运行程序时,由于程序的预先安排或内外部事件,引起CPU中断正在运行的程序,而转到为预先安排的事件或外部事件服务的程序中去。由于我们的检测仪要求实时地检测并显示大气机输出的各种参数,在时间上又不是非常精确,为了实现这一任务,我们利用了中断向量表中类型码为1CH的定时器中断。它以每秒18.2次的频率进行时钟硬中断(使用中断请求IRQ0),即执行8号中断。这个中断周而复始的在运行,在它的中断服务程序中除了进行日时钟计数和磁盘驱动器超时检测控制外,接着又进行0x1C的软中断调用,0x1C软中断只有一条返回指令,它不做什么事情,因而我们利用这一特点,修改该向量使其在中断时指向我们自己定义的中断服务程序的入口,完成特定的工作,使我们的数据采集在“后台”工作,而数据处理及显示在“前台”工作。所要注意的是,我们所编制的中断服务程序的执行周期应小于原有中断的执行周期(1/18.2秒),以免造成系统崩溃。

       一般地讲,编写这类程序应首先定义一个中断类型的句柄:
       void interrupt for handler( );
       然后将我们所编制的中断服务程序安装在所要替代的中断INTERRUPT上。
       oldhandler=getvect(INTERRUPT);
       setvect(INTERRUPT,handler);
       注意应将中断INTERRUPT保存在oldhandler中,以便在程序结束时恢复,恢复时用setvect(INTERRUPT,oldhandler)完成。

       3  系统简介
       3.1 系统硬件构成
   

       由于我们所要检测的大气机输出三种类型的数据,即模拟量、开关量和串行数字量,我们采用了CPU卡配套数据采集卡的模式,使用的是Advantech公司生产的PCM-3350CPU模块、PCM-3718HG可编程12位数据采集卡(带16位DI/DO)和PCM-3610串口通讯卡,系统构成如图1。

                                                                     图1

       其中转换电路主要完成对大气机输出的模拟量和开关量的电平转换。由于PCM-3718HG的电压检测范围最多可设定为+/-10V,所以对大气机输出的部分电压(如24V、+15V、-15V等),要进行一定的衰减,将其规约到+/-10V范围,以便PCM-3718HG能正常地采集。

       3.2 系统软件结构
   

       该系统的软件部分分为几个模块:
   

       ①数据采集模块:完成对模拟量、开关量及串行数字量的采集,均在后台中断程序中完成;
   

       ②数据处理模块:完成对各种类型数据的转换,如二进制数根据各位的权值转换为对应的十进制数,数字转换为字符串等;
   

       ③数据显示模块:将转换后的各种数据以约定的字符格式显示在液晶模块上。

       4  具体实现实例
    完整的中断服务程序如下:
void interrupt far handler( )
{
  Gather_3718_Scatter( );  /*采集离散量*/
  Gather_3718_Analog( );   /*采集模拟量*/
  if (value_3718_scatter[15]==0) Gather_3610_Number( ); /*通过一个开关量决定是否采集数字量,以节省系统资源*/
  oldhandler( );
}
       4.1模拟量的采集处理
    PCM-3718HG提供了16个通道的单端(或8个通道的差分)模拟量输入,A/D转换的完成可通过参数初始化后,调用板卡的相应功能函数即可。为了PCM-3718HG能正常工作,需要先对它进行初始化,然后才能使用。相应的初始化程序及采集处理程序如下:
void PCM3718_Initial()/*PCM-3718HG初始化函数*/
{
  dat = data;
  param[0]  = 0;            /*板卡号*/
  param[1]  = 0x220;        /*板卡基地址*/
  param[5]  = 50;           /*采样速率=1M/(50*100)=200Hz*/
  param[6]  = 100;
  param[7]  = 0;            /*触发方式为0(步进触发)*/
  param[10] = FP_OFF(dat);  /*A/D数据缓冲区A的偏移量*/
  param[11] = FP_SEG(dat);  /*A/D数据缓冲区A的段地址*/
  param[12] = 0;            /*A/D数据缓冲区B的偏移量、段地址,若未使用,必须设为0*/
  param[13] = 0;
  param[14] = 16;           /*A/D转换次数*/
  param[15] = 0;            /*A/D转换开始通道*/
  param[16] = 15;           /*A/D转换停止通道*/
  param[17] = 8;            /*电压量程代码为8表示+/-10V*/
  param[27] = FP_OFF(dat);  /*D/I数据缓冲区A的偏移量*/
  param[28] = FP_SEG(dat);  /*D/I数据缓冲区A的段地址*/
  param[29] = 0;            /*D/I数据缓冲区B的偏移量、段地址,若未使用,必须设为0*/
  param[30] = 0;
  param[31] = 16;           /*D/I数据号*/
  param[32] = 0;            /*D/I数据口*/
  param[33] = FP_OFF(dat);  /*D/O数据缓冲区A的偏移量*/
  param[34] = FP_SEG(dat);  /*D/O数据缓冲区A的段地址*/
  param[35] = 0;            /*D/O数据缓冲区B的偏移量、段地址,若未使用,必须设为0*/
  param[36] = 0;
  param[37] = 16;           /*D/O数据号*/
  param[38] = 0;            /*D/O数据口*/
  pcm3718(3, param);/*功能3:硬件设备初始化*/
  if (param[45] != 0)
    {
      printf( DRIVER INITIALIZATION FAILED !);
      exit(1);
    }
  pcm3718(4, param);/*功能4:A/D初始化*/
  if (param[45] != 0)
    {
      printf( A/D INITIALIZATION FAILED !);
      exit(1);
    }
  pcm3718(20, param);/*功能20:数字输入D/I初始化*/
  if (param[45] != 0)
    {
      printf( DIGITAL INPUT INITIALIZATION FAILED !);
      exit(1);
    }
  pcm3718(28, param);/*功能20:数字输出D/O初始化*/
  if (param[45] != 0)
    {
      printf( DIGITAL OUTPUT INITIALIZATION FAILED !);
      exit(1);
    }
}
void Gather_3718_Analog( )/*模拟量采集函数*/
{
  pcm3718(5,param);/*调用PCM-3718HG的功能5,依次进行16个通道的A/D触发*/
}
void Data_Change_3718_Analog( )/*模拟量处理函数*/
{ int i;
  for (i=0;i<16;i++)/*依次处理16个通道采集到的模拟量*/
{
 DataBuf=data[i] & 0xFFF;/*取低12位*/
 DataBuf=((10-(-10))*DataBuf/4096)+(-10);/*将低12位二进制数转换为对应的电压值*/
 value_3718_analog[i]=DataBuf;
}
}
    注:PCM-3718HG在使用之前,还需先行安装,为避免每次进入系统时手动安装的麻烦,可修改系统的批处理文件autoexec.bat,比如在其中加入C:PCM-3718.EXE,该可执行文件可在Advantech公司提供的配套光盘上找到,将其拷贝到相应目录。另外在该检测系统的头文件定义之后加入语句
extern pcm3718(int,unsigned int *);
extern用于告诉编译程序,在其后的变量类型和名称在别的文件中说明。

       4.2 开关量的采集处理
   

       PCM-3718HG提供了2个8位的数字输入/输出(DI/DO)通道,而DI/DO均是TTL电平级,对应的口地址分别为BASE+3和BASE+11,所以在中断程序中,我们只需读出对应口地址的数据,在其数据处理函数中将口地址的数据分别进行处理即可。
void Gather_3718_Scatter( )/*开关量采集函数*/
{
  scatter_3=inportb(BASE_3718+3);/*读口地址BASE+3处的一个字节*/
  scatter_11=inportb(BASE_3718+11);/* 读口地址BASE+11处的一个字节*/
}
void Data_Change_3718_Scatter( )/*开关量处理函数*/
{ int i,temp;
  for (i=0;i<16;i++)/*提取出16个开关量*/
{
  if (i<8)/*提取出scatter_3的每一位*/
   { temp=1 << i;
     value_3718_scatter[i]=(scatter_3 & temp) >> i;
   }
  else /*提取出scatter_11的每一位*/
   { temp=1 << (i-8);
     value_3718_scatter[i]=(scatter_11 & temp) >> (i-8);
   }
}
}
       4.3 串行数字量的采集处理
   

       PCM-3610是带有16个字节的FIFO的RS-232串口通讯卡,而大气机依次所发出的是14个字节的串行数字量,刚好能满足我们的需求。由于大气机发送串行数字量需要我们向其先发送一个10μs的脉冲来启动,等待约40ms后,大气机发送完毕一次14个字节的串行数字量,而我们的中断服务程序每隔1/18.2秒(约55ms)执行一次,我们不能发送脉冲后,死等40ms,浪费系统资源,所以设定一个变量sign_3610,用它来控制串行数字量的采集,以使发送脉冲后,隔一次中断再采集(根据相应系统的需求,可增加或减少间隔次数)。根据该型大气机所发数字量的特点,还需要先完成PCM-3610的初始化。
void PCM3610_Initial( )/*PCM-3610初始化函数*/
{
  outportb(BASE_3610+2,0xC9);/*允许FIFO*/
  outportb(BASE_3610+3,0x80);/*设置DLAB=1*/
  outportb(BASE_3610+0,0x0C);/*设置波特率为9600bit/s*/
  outportb(BASE_3610+1,0x00);
  outportb(BASE_3610+3,0x03);/*设置数据位8位,停止位1位,无奇偶校验位*/
}
void Gather_3610_Number( )/*串行数字量采集函数*/
{ int i;
  switch(sign_3610)
  {
   case 0:{ outportb(BASE_3718+11,0x01);/*通过PCM-3718HG的D/O向大气机发送脉冲信号*/
delay(10);/*延时10ms,此时间不能过长,以免整个中断程序的执行时间超过55ms*/
sign_3610++;/*sign_3610自增,以便下次中断时进入case 1选项*/
break;
     }
   case 1:{ delay(10);
for (i=0;i<14;i++) /*依次从PCM-3610的FIFO中取出14个字节的数据*/
number_before[i]=inportb(BASE_3610);
sign_3610=0;/*取完数后,sign_3610归零,以便进入下一个采集周期*/
break;
          }
  }
}
        对串行数字量的处理,由于每个系统都有其特殊性,因此只需根据各自的特点编制数据转换函数,将接收到的二进制数据转换为对应的十进制数,在此不详述。

       4.4 数据实时显示的实现
   

       由于我们的检测仪用于外场,要求体积小,所以选用了两行显示的字符型液晶显示模块,第一行显示数字量,第二行显示模拟量,具体显示哪种类型的数据由面板上的波段开关控制,它连接到PCM-3718HG的D/I,我们通过判断哪一位为0(表示接通)来显示对应的数字量或模拟量。而且为了方便与用户打交道,把数据显示模块放在了前台运行。
   

       液晶模块的显示驱动程序在此不详述,有兴趣可参考相关书籍,要提出注意的是,液晶模块对时间的反应较敏感,在延时方面稍有不慎,则可能造成显示字符的丢失或混乱。根据系统配置的不同,延时时间上稍有差异。在本系统中,因为用到了中断,这一矛盾非常明显,经过反复调试,发现在显示之前关闭中断,显示完成后重新打开中断,继续后台采集,这样就较好地避免了这一矛盾。

       5  结束语
   

       本检测系统针对实际应用情况,阐述了DOS环境下中断的特点以及运用TurboC开发嵌入式程序的方法和思路,规划出了合理的检测流程,节约了费用,提高了检测效率,目前处于运行阶段,效果良好。

       参考文献:
       徐金捂等,TURBOC实用大全,北京,机械工业出版社,1996。

本文来源:    作者:
热点资讯(一周点击率)
热评博文
评一评已有 0 位网友对此文发表了看法。  我也来评一下

验证码:  看不清?换一张

 

快乐大本营
工程师之星
高福东
擅长嵌入式开发及单片机应用开发
  • 王波涛  熟悉单片机及其接口技术
  • 朱伟平  熟悉51单片机系统LCD驱动程序编写及调试。
热门招聘
论坛热贴