⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 key.c

📁 X86平台下的串口键盘DOS驱动程序
💻 C
字号:
/****************************************************************
程序(函数)名称:串口键盘驱动程序
功能描述:

参数:
作者  林剑福
创建日期:2006-12-20
修改日期:2007-09-14
****************************************************************/

#include <dos.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "com.h"



#define NOERROR         0       		//错误标志

int            SError          = NOERROR;

int            portbase        = 0x2f8;		//串口地址
void           interrupt(*oldvects[2])();	//定义了一个中断数组,用来存放中断返回值。

unsigned char temp;   //串口接收
//unsigned char Rec_flag;

unsigned int    count          = 0;
unsigned char  LastStatus      = 0;
unsigned char  OldStatus       = 0;
unsigned char  RecStatus       = 0;
unsigned char  Rec_flag        =0;
unsigned char  CmdWord;       //接收数据包命令
unsigned char  DataWord;       //接收数据包数据
unsigned char  b_validFrame;    //帧接收标志
unsigned char  v_flag;   //电池电量标志
unsigned char  Voltage;  //电池电量


void call_int9(unsigned char scan_code)
{
  unsigned char far*pForce;

	 _AX= scan_code;
	 _BX=_AX;
	 _CX=_AX;
	 _DX=_AX;
	  _asm
	  {
		int 9h;
	  }
 	 pForce=(unsigned char far*)MK_FP(0x40, 0xCC);
  	 if(!(*pForce))
		*pForce=2;
	 return;
}


void Command_exp(void)
{
	Rec_flag=0;
	  switch(RecStatus)
		{
		  case 0:
			  if(temp != 0xeb)RecStatus = 0;
				 else  RecStatus=1;
				  break;
		  case 1:
				CmdWord = temp ;
				  RecStatus=2;
				  break;
		  case 2:
				DataWord = temp ;
				  RecStatus=3;
				  break;
		  case 3:
				if(temp == 0xfb )
				b_validFrame=1;
				else b_validFrame=0;
				  RecStatus=0;
				  break;
		  default :
			 break;					
		 }
			if(b_validFrame == 1)
			{
			  b_validFrame = 0;
			  if(CmdWord == 0x67)
				 {
					CmdWord = 0;
               call_int9(DataWord);
				 }
			  if(CmdWord == 0x69)
				 {
					CmdWord = 0;
               v_flag = 1;
               Voltage = DataWord ;
				 }

			}
	
}
/*******************************************************************************
串口中断服务程序
*******************************************************************************/
void far interrupt com_int(void)
{

	 unsigned char Status = 0;
	 char Loop = 0;
	 
	 while(Loop == 0)
	 {
		Status = inportb(portbase + IIR) & RX_MASK;
		switch(Status)
		{
			case NO_INT:
				LastStatus = 1;
				break;
		case URS_ID:
			inportb(portbase + LSR);	//撤销中断
			LastStatus = 2;
			break;
		case RX_ID:

					temp = inportb(portbase + RXR);
					
			      Rec_flag = 1;

				LastStatus = 3;
			break;
		case FDT_ID:
			inportb(portbase + RXR);	//撤销中断
			LastStatus = 4;
			break;
		case TBRE_ID:
			LastStatus = 5;
			break;
		case HSR_ID:
			inportb(portbase + MSR); 	//撤销中断
			LastStatus = 6;
			break;
		default:
				LastStatus = 7;
			break;
		}
		if((LastStatus == 1) || (LastStatus == 7)) break;
	 }
    
	 outportb(ICR, EOI);		/*中断应答*/

	 if(Rec_flag == 1)
	 Command_exp();

}


/********************************************************************************
函数功能:	设置中断向量函数,com1用中断4向量号为0xc。
		com2用中断3向量号为0xb,该中断号是固定的用户不可以修改。
函数入口:
*********************************************************************************/
void setvects(void)
{
	if(portbase == 0x3f8)
	{
		oldvects[0] = getvect(0xc);	/*保存中断4的向量,以便在退出时恢复*/
		setvect(0xc, com_int);		/*把中断4向量改为com_int*/
	}
	if(portbase == 0x2f8)
	{
		oldvects[0] = getvect(0xb);
		setvect(0xb, com_int);
	}
}

/**************************************************************************************
函数功能:	恢复原来的中断向量
函数入口:
***************************************************************************************/
void resvects(void)
{
	if(portbase == 0x3f8)
		setvect(0xc, oldvects[0]);
	if(portbase == 0x2f8)
		setvect(0xb, oldvects[0]);
}

/*******************************************************************
函数功能:	打开串口中断和系统中断。
函数入口:
********************************************************************/
void i_enable(void)
{
	int	c;
	disable();
	c = inportb(portbase + MCR) | MC_INT;
	outportb(portbase + MCR, c);
	outportb(portbase + IER, RX_INT);
	if(portbase == 0x3f8)
		c = inportb(IMR) & IRQ4;
	if(portbase == 0x2f8)
		c = inportb(IMR) & IRQ3;
	outportb(IMR, c);
	enable();
}

/*******************************************************************
函数功能:	关闭串口中断和系统中断。
函数入口:
********************************************************************/
void i_disable(void)
{
	int	c;
	disable();
	if(portbase == 0x3f8)
		c = inportb(IMR)| ~IRQ4;
	if(portbase == 0x2f8)
		c = inportb(IMR)|~IRQ3;
	outportb(IMR, c);
	outportb(portbase + IER, 0);
	c = inportb(portbase + MCR) & ~MC_INT;
	outportb(portbase + MCR, c);
	enable();
}

/*******************************************************************
函数功能:	打开串口(打开RTS,与DTS)。
函数入口:
********************************************************************/
void comm_on(void)
{
	int	c;

	i_enable();
	c = inportb(portbase + MCR) | DTR | RTS;
	outportb(portbase + MCR, c);
}

/*******************************************************************
函数功能:	关闭串口。
函数入口:
********************************************************************/
void comm_off(void)
{
	i_disable();
	outportb(portbase + MCR, 0);
	resvects();
}

void OpenSer(void)
{
	
	setvects();
	comm_on();
}


 /************************************************************************
不用中断发送时的发送函数,该函数每次发送一个字节。
*************************************************************************/
int SerSend(char x )
{
	 long int           timeout = 0x0000FFFFL;

	 outportb(portbase + MCR,  MC_INT | DTR | RTS);

	 timeout = 0x0000FFFFL;

	 /* Wait for transmitter to clear */
	 while ((inportb(portbase + LSR) & XMTRDY) == 0)
		  if (!(--timeout))
			return -1;

	 disable();
	 outportb(portbase + TXR, x);
	 enable();
	return 0;
}

/***************************************************************************
函数说明:	串口初始化函数SerInit
入口参数:	Port 串口地址如0x3f8;Speed 速率 如115200
		Parity 奇偶效验NO_PARITY无,EVEN_PARITY偶效验,ODD_PARITY奇效验
		Bits 数据位数如8,StopBit 停止位如1。
****************************************************************************/
SerInit(int Port, unsigned long int Speed, int Parity, int Bits, int StopBit)
{
	int flag = 0;
	int Setting = 0;
	char c;
	int divisor;

//波特率计算公式:BRD=1843200/16*波特率=115200/波特率
//		    表 波特率除数
//	位速率		BRDH		BRDL
//	50		09h		00h
//	110		04h		17h
//	300		01h		80h
//	1200 		00h		60h
//	2400 		00h		30h
//	4800		00h		18h
//	9600		00h		0Ch
//	19200		00h		06h
//	115200		00h		01h
	if (Speed == 0)            				//避免除数为零
			flag = -1;
	else
			divisor = (int) (115200L/Speed);

	portbase = Port;
	if (portbase == 0)					//避免端口地址为零
			flag = -1;

	if (Bits < 5 || Bits > 8)				//避免数据位错
		flag = -1;

	if (StopBit != 1 && StopBit != 2)			//避免停止位错
		flag = -1;

	if (Parity != NO_PARITY && Parity != ODD_PARITY && Parity != EVEN_PARITY)
		flag = -1;

	disable();						//屏蔽中断
	c = inportb(portbase + LCR);				//读出控制寄存器
	outportb(portbase + LCR, (c | 0x80)); 			//打开除数寄存器
	outportb(portbase + DLL, (divisor & 0x00FF));		//初始化波特率
	outportb(portbase + DLH, ((divisor >> 8) & 0x00FF));	//初始化波特率
	outportb(portbase + LCR, c);         			//关闭除数寄存器
	enable();						//开放硬件中断

	Setting  = Bits-5;				//得到位数
	if(StopBit == 1)				//得到停止位
		Setting |= 0x00;
	else
		Setting |= 0x04;
	Setting |= Parity;				//得到校验位

	disable();
	outportb(portbase + LCR, Setting);
	enable();

	if (!flag)
		OpenSer();
	return flag;
}


void  interrupt    volt_int()
{
    if(v_flag == 1)
	 {
	 _AX= Voltage;
	 _BX= 1;
	 _CX= _AX; 
	 v_flag = 0;
	 }
    asm
	       { 
	        mov ss:[bp+12],CX;
	        MOV ss:[bp+14],BX;
			  }
}


int main(int argc, char * argv[])

{

	unsigned long	speed    = 9600;	/*波特率参数*/
	int        	parity   = NO_PARITY;	/*奇偶效验*/
	int        	bits     = 8;		/*数据位数*/
	int        	stopbits = 1;		/*停止位数*/
	
	unsigned    BuzzerFlag = 0;
	
	 if(argc != 3)
	 {
      printf("example:comkey 1/2 -on/off ");
		  return 0;				/*命令行参数*/
	 }
    switch(atoi(argv[1]))
    {
        case 1:
             portbase = 0x3f8;
             break;
        case 2:
             portbase = 0x2f8;
             break;
        default:
			printf("example:comkey 1/2 -on/off");
					 return 0;

    }
    
    
	 if(*argv[2]=='-'  &&*(argv[2]+1)=='o' &&*(argv[2]+2)=='n' )
		     {
			    BuzzerFlag=1;
		     } 
			
	      	else if(*argv[2]=='-' &&*(argv[2]+1)=='o' &&*(argv[2]+2)=='f' &&*(argv[2]+3)=='f')
		      {
			     BuzzerFlag=0;
		      }	
		
   

	SerInit(portbase, speed, parity, bits, stopbits);

	  if(BuzzerFlag ==1 )  //Buzzer is on
	  	{
	  		  SerSend(0xeb);
          SerSend(0x66);
          SerSend(0x01);
          SerSend(0xfb);
	  		}
	  		else    //Buzzer is off
	  			 {
	  			 	  SerSend(0xeb);
              SerSend(0x66);
              SerSend(0x00);
              SerSend(0xfb);
	  			 	}

	setvect(0x65,volt_int);
	keep (0,(*(unsigned far*) MK_FP(_psp-1, 3)) + 2);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -