接口程序。微机有两条用于串行通信的硬件中断通道IRQ3(COM2)和IRQ4(COM1),对应中断向量为OBH和OCH,可通过设置中断屏蔽寄存器(地址21H)来开放中断。置1时屏蔽该中断,否则开放中断。硬件中断例程必须在程序末尾往中断命令寄存器(地址20H)写入20H,即 MOV AL, 20H OUT 20H, AL用以将当前中断服务寄存器清零,避免中断重复响应。 每路UART有4组中断,程序可通过中断允许寄存器(3F9H)来设置开放那路中断。这4组中断的位标志如下: 第0位 1=接收到数据 第1位 1=发送保持寄存器为空 第2位 1=接收数据出错 第3位 1=MODEM状态寄存器改变 第4~7位为0 在中断例程中检查UART的中断标志寄存器(3FAH),确定是哪一组事件申请中断。该寄存器第0位为0时表示有中断申请,响应该中断并采取相应措施后,UART自动复位中断标志;第2,1位标志中断类型,其位组合格式如下:代码 中断类型 复位措施11接收出错读线路状态寄存器10接收到数据读接收寄存器01发送寄存器空输出字符至发送寄存器00MODEM状态改变读MODEM状态寄存器这4组中断的优先级为0号最低,3号最高。 在本组程序中,函数setinterrupt()和clearinterrupt()设置和恢复串行通信中断向量;cominit()初始化指定串行口并开放相应中断;sendcomdata()和getcomeomdata()用于发送和接收数据串;com1()和com2()为中断例程,二者均调用fax2()函数,fax2()函数为实际处理数据接收和发送的例程。明确了串行口的工作原理,就不难理解其具体程序。 3.结论 上述程序采用C语言编写,在BORLAND C++2.0集成环境中调试通过,为简单起见,只考虑了使用发送/接收两条信号线的情况,并未考虑使用握手信号线。 在实际应用中这两组程序尚有一些可修改之处。比如,中断接收程序中的缓冲区可改为循环表,以防数据溢出,尽可能保留最新数据。由于笔者水平所限,文中不足疏漏之处尚希行家指正。 程序1: static int receive_delay=10000; int may(unsigned par,char *comm,char *ss) {int cs=0,j=0; char *p; bioscom(0,par,0); //com1 loop:p=comm; inportb(0x3f8); //reset do{ while((inportb(0x3f8+5)&0x20)==0); outportb(0x3f8,*p++); }while(*p); //send command os=0;j=0; do{ if((inportb(0x3fd)&0x01)==0) if(os〉receive_delay) break; else { cs++; continue; } ss[j++]=inportb(0x3f8); cs=0; }while(l); ss[j]=\0; if(j) return 0; else return 1; 程序2: #include #include #include #include #inolude #define maxsize 4096 #define SEND 2 #define RECEIVE 1 #define COM1 0 #define COM2 1 static unsigned char Hardinterrupt=0; struct ComInterrupt {int portadd; int intbit; char buf[maxsize],*comm; int bufh,recount,sendcount; }com[2]={{0x3f8,0x0c,,,0,0,0}, {0x2f8,0x0b,,,0,0,0} }; void static interrupt (*old_com[2])(void); vold interrupt coml(vold); void interrupt com2(void); void fax2(int comnum); void setinterrupt(int comnum); void clearinterrupt(int comnum); void cominit(int comnum, int para, int interruptmark); void sendcomdata (int comnum,char *command); int getcomdata (int comnum, char *buf); void interrupt com1(void) {fax2(0);} void interrupt com2(void) {fax2(1);} // set cominterrupt, comnum 0=com1, 1=com2 void setinterrupt (int comnum) { old_com[comnum]=getvect(com[comnum].intbit); if (!oomnum) setvect(com[comnum].intbit,coml); //com1 else setvect(com[comnum].intbit,com2); //com2 //set hard int Hardinterrupt = inportb(0x21); if(comnum) outportb(0x21,Hardinterrupt&0xf7); //com2 ,0 else outportb(0x21,Hardinterrupt&0xef); //com1 0, } void clear interrupt(int comnum) { if(comnum) outportb(0x21,Hardinterrupt 0x08); //COM2 else outportb(0x21,Hardinterrupt0x10); //COM1 setvect(com[comnum].intbit,old_com[comnum]); for( i=0;i
|