📄 key.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 + -