/*------------------------------------------------------------------*
SERIAL.CPP
The following code shows how to take advantage of some of
the Turbo C++ extensions to the C++ language to do asynchronous
communications without having to write supporting assembly-
language routines.
This program bypasses the less-than-adequate PC BIOS
communications routines and installs a serial interrupt
handler. Direct access to PC hardware allows the program to
run at faster baud rates and eliminates the need for
the main program to continuously poll the serial port for
data; thus implementing background communications. Data that
enters the serial port is stored in a circular buffer.
* Compile this program with Test Stack Overflow OFF.
*------------------------------------------------------------------*/
#include <dos.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include "serial.h"
#include "..\wba\gw\CusType.h"
#include "..\UnGetch\UnGetch.h"
#define VERSION 0x0101
#define FALSE 0
#define TRUE 1
#define NOERROR 0 /* No error */
#define BUFOVFL 1 /* Buffer overflowed */
#define ESC 0x1B /* ASCII Escape character */
#define ASCII 0x007F /* Mask ASCII characters */
#define SBUFSIZ 0x0010 /* Serial buffer size */
int SError = NOERROR;
int portbase = 0;
void interrupt(*oldvects[2])(...);
static char ccbuf[SBUFSIZ];
unsigned int startbuf = 0;
unsigned int endbuf = 0;
UINT KeyCode = 0;
/* Handle communications interrupts and put them in ccbuf */
void interrupt com_int(...)
{
disable();
/*
if ((inportb(portbase + IIR) & RX_MASK) == RX_ID)
{
if (((endbuf + 1) & SBUFSIZ - 1) == startbuf)
SError = BUFOVFL;
ccbuf[endbuf++] = inportb(portbase + RXR);
endbuf &= SBUFSIZ - 1;
}
*/
/* Put the serial code into keyboard buffer */
KeyCode = inportb(portbase + RXR);
if(KeyCode != 0x0a) //ignores the linefeed character '\n'
{
if(KeyCode == 0x0d) KeyCode = 0x1c0d;
UnGetch(KeyCode);
}
/* Signal end of hardware interrupt */
outportb(ICR, EOI);
enable();
}
/* Output a character to the serial port */
serial& serial::operator<<( char x )
{
long int timeout = 0x0000FFFFL;
outportb(portbase + MCR, MC_INT | DTR | RTS);
/* Wait for Clear To Send from modem */
while ((inportb(portbase + MSR) & CTS) == 0)
if (!(--timeout))
return *this;
timeout = 0x0000FFFFL;
/* Wait for transmitter to clear */
while ((inportb(portbase + LSR) & XMTRDY) == 0)
if (!(--timeout))
return *this;
disable();
outportb(portbase + TXR, x);
enable();
return *this;
}
/* Output a string to the serial port */
serial& serial::operator<<( char *string )
{
while (*string)
{
(*this) << *string;
string++;
}
return *this;
}
/* This routine returns the current value in the buffer */
serial &serial::operator>>( char &ch )
{
if (endbuf == startbuf)
{
ch = -1;
return *this;
}
ch = ccbuf[startbuf];
startbuf++;
startbuf %= SBUFSIZ;
return *this;
}
/* Install our functions to handle communications */
void setvects(void)
{
oldvects[0] = getvect(0x0B);
oldvects[1] = getvect(0x0C);
setvect(0x0B, com_int);
setvect(0x0C, com_int);
}
/* Uninstall our vectors before exiting the program */
void resvects(void)
{
setvect(0x0B, oldvects[0]);
setvect(0x0C, oldvects[1]);
}
/* Turn on communications interrupts */
void i_enable(int pnum)
{
int c;
disable();
c = inportb(portbase + MCR) | MC_INT;
outportb(portbase + MCR, c);
outportb(portbase + IER, RX_INT);
c = inportb(IMR) & (pnum == COM1 ? IRQ4 : IRQ3);
outportb(IMR, c);
enable();
}
/* Turn off communications interrupts */
void i_disable(void)
{
int c;
disable();
c = inportb(IMR) | ~IRQ3 | ~IRQ4;
outportb(IMR, c);
outportb(portbase + IER, 0);
c = inportb(portbase + MCR) & ~MC_INT;
outportb(portbase + MCR, c);
enable();
}
/* Tell modem that we're ready to go */
void comm_on(void)
{
int c, pnum;
pnum = (portbase == COM1BASE ? COM1 : COM2);
i_enable(pnum);
c = inportb(portbase + MCR) | DTR | RTS;
outportb(portbase + MCR, c);
}
/* Go off-line */
void serial::comm_off(void)
{
i_disable();
outportb(portbase + MCR, 0);
}
void serial::init_serial(void)
{
endbuf = startbuf = 0;
setvects();
comm_on();
}
serial::~serial()
{
comm_off();
resvects();
}
/* Set the port number to use */
int serial::SetPort(int Port)
{
int Offset, far *RS232_Addr;
switch (Port)
{ /* Sort out the base address */
case COM1 : Offset = 0x0000;
break;
case COM2 : Offset = 0x0002;
break;
default : return (-1);
}
RS232_Addr = (int far *)MK_FP(0x0040, Offset); /* Find out where the port is. */
if (*RS232_Addr == NULL) return (-1);/* If NULL then port not used. */
portbase = *RS232_Addr; /* Otherwise set portbase */
return (0);
}
/* This routine sets the speed; will accept funny baud rates. */
/* Setting the speed requires that the DLAB be set on. */
int serial::SetSpeed(int Speed)
{
char c;
int divisor;
if (Speed == 0) /* Avoid divide by zero */
return (-1);
else
divisor = (int) (115200L/Speed);
if (portbase == 0)
return (-1);
disable();
c = inportb(portbase + LCR);
outportb(portbase + LCR, (c | 0x80)); /* Set DLAB */
outportb(portbase + DLL, (divisor & 0x00FF));
outportb(portbase + DLH, ((divisor >> 8) & 0x00FF));
outportb(portbase + LCR, c); /* Reset DLAB */
enable();
return (0);
}
/* Set other communications parameters */
int serial::SetOthers(int Parity, int Bits, int StopBit)
{
int setting;
if (portbase == 0) return (-1);
if (Bits < 5 || Bits > 8) return (-1);
if (StopBit != 1 && StopBit != 2) return (-1);
if (Parity != NO_PARITY && Parity != ODD_PARITY && Parity != EVEN_PARITY)
return (-1);
setting = Bits-5;
setting |= ((StopBit == 1) ? 0x00 : 0x04);
setting |= Parity;
disable();
outportb(portbase + LCR, setting);
enable();
return (0);
}
/* Set up the port */
serial::serial(int Port, int Speed, int Parity, int Bits, int StopBit)
{
flag = 0;
if (SetPort(Port))
flag = -1;
if (SetSpeed(Speed))
flag = -1;
if (SetOthers(Parity, Bits, StopBit))
flag = -1;
if (!flag)
init_serial();
}
/* Control-Break interrupt handler */
int c_break(void)
{
i_disable();
fprintf(stderr, "\nStill online.\n");
return(0);
}
DOS系统下的串口键盘编程驱动
4星 · 超过85%的资源 需积分: 9 11 浏览量
2009-09-06
22:54:30
上传
评论
收藏 32KB RAR 举报
LovelyPenguin
- 粉丝: 16
- 资源: 38
最新资源
- 基于Matlab人脸肤色定理的教师人数统计+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于Matlab霍夫曼变换的表盘读数识别+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于Matlab火灾烟雾检测源码带GUI界面+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于Matlab的恶劣天气交通标志识别系统+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于MATLAB的霍夫曼变换的表盘示数识别+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于Matlab的车道线识别系统 +源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于MATLAB的教室人数统计系统带Gui界面+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于MATLAB的教室人数统计系统带Gui界面+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于MATLAB 的霍夫曼变换答题卡识别源码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于Matlab+bp神经网络的神经网络汉字识别系统+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈