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

📄 com.c

📁 在DOS环境下
💻 C
字号:
/****************************************************************
程序(函数)名称:ser977
功能描述:	BBPC系列串口,除了可以调用
		bios进行通讯外,为了使用更高的串口通讯速率可以直接对串
		口硬件直接操作,例子用后一种方式编程,并使用中断方式接收,
		接收到的数据缓存在环行队列中。程序把串口波特率固定为115200,
		串口号用命令行参数传入,如:com 1为用1号串口,该例子
		能通用于1~6号串口.用中断方式编写串口程序时,在中断服务程
		序中没有特殊要求不需要用disable()、enable()关闭、打开中
		断。运行中程序会把键盘输入字符发送到相应的串口。按“ESC”
		键退出,该程序在bc45的large模式下测试通过。
参数:		串口号,1~6
作者:		周巍
****************************************************************/

#include <dos.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "COM.h"
#include "bbgui.h"

#define uchar unsigned char
#define uint unsigned int

const char str1[]={0x1a,0x2b,0x3c};
const char str2[]={0x4f,0x5e,0x6d};
/*--------------------------------------------------------------------------------*/	
uint ISA_OUT_ADDRESS = 0x1000;
uchar LED=0xff;

/***************************************************************************
主程序
****************************************************************************/
void main()
{
	UART_INT();
  outportb(ISA_OUT_ADDRESS,LED);
  delay_ms(10000);
  while(1)
  {
  	UartServer();
  	outportb(ISA_OUT_ADDRESS,LED); 		
  }
  //comm_off();
}
//-----------------------------------------------------------------------------*/
//函数:void delay_ms(uchar numb)
//功能:软件延时numb*1mS
//输入:延时倍率numb
//输出:NONE
//-----------------------------------------------------------------------------*/
void delay_ms(uint numb)
{
	uint j;
	uint i;
	for(j=numb;j>0;j--)
	{
		for(i = 1287;i>0;i--){;}
	}
}

/*****************************************************************************************
未用fifo的中断服务程序例子,例子用中断接收数据并放入缓存中。发送没有用中断实现。用户如需要
用中断发送字符,需要一个发送缓存,并把串口的发送中断打开。发送缓存的定义请参考接收缓存的定义。
在中断处理例程里面需要增加发送中断处理。在用发送中断时主程序除了需要发送的数据放入发送缓存中,
还需要判断缓存是否为空或满。当为空时必须重新启动发送否则不会产生发送中断。如缓存满时可以丢弃
或等待。
******************************************************************************************/
void far interrupt com_int(void)				
{
    unsigned char Status = 0;
    char Loop = 0;
    unsigned int reg_serv;    
    reg_serv = inport(REG_SVER);    //读取中断服务寄存器内容
   	if(((reg_serv&0x0400)!= 0) && (portbase == 0xff80))//是COM5中断
    {
    	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:				//未用fifo时处理例子
			      if (((endbuf + 1) &(SBUFSIZ - 1)) == startbuf) SError = BUFOVFL;            			
       			ccbuf[endbuf++] = inportb(portbase + RXR);//如果使用fifo必须读至激活状态
	  		    endbuf &= SBUFSIZ - 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;
	    }
    }
	  outport(ICRCPU, EOICPU);
}               

/************************************************************************
不用中断发送时的发送函数,该函数每次发送一个字节。
*************************************************************************/
int SerSend(char x )
{
	outportb(portbase + MCR,  MC_INT | DTR | RTS);
  disable();
  outportb(portbase + TXR, x);
  enable();
	return 0;
}
/************************************************************************
不用中断发送时的发送函数,该函数每次发送一个字符串。
*************************************************************************/
/* Output a string to the serial port */
SerSendStr( char *string )
{
	while (*string)
	{
	   SerSend(*string);
	   string++;
	}
	return 0;
}
/**********************************************************************
从缓存中取出一个字符,并修改指针,当缓存为空时返回-1。
***********************************************************************/
int SerRev(char *ch)
{
	if (endbuf == startbuf)
	{
		*ch = -1;
		return -1;
	}

	*ch = ccbuf[startbuf];
	startbuf++;
	startbuf %= SBUFSIZ;
	return 0;
}

/********************************************************************************
设置中断向量函数,com1用中断4向量号为0xc,com2用中断3向量号为0xb,该中断号是固定的
用户不可以修改。
*********************************************************************************/
void setvects(void)
{
		old_handler = getvect(INTVECT);	/*保存中断向量,以便在退出时恢复*/
		setvect(INTVECT,com_int);		    /*把中断向量改为com_int*/
}
/**************************************************************************************
恢复原来的中断向量。在编写中断程序时,需要在程序结束时恢复原来的中断向量,原来的向量一般
指向系统默认中断处理程序。以避免该硬件产生中断时跑飞,造成死机。
***************************************************************************************/
void resvects(void)
{
	 setvect(INTVECT, old_handler);
}
/*******************************************************************
打开中断函数i_enable,功能是打开串口中断和系统中断。
********************************************************************/
void i_enable(void)
{
    int                c;
    disable();
    c = inportb(portbase + MCR) | MC_INT;
    outportb(portbase + MCR, c);
    outportb(portbase + IER, RX_INT);
					 c = inportb(IMR) & COMMC;
    outportb(IMR, c);
    enable();
}

/*******************************************************************
关闭中断函数i_disable,功能是关闭串口中断和系统中断。
********************************************************************/
void i_disable(void)
{
    int                c;
    disable();
		c = inportb(IMR)| ~COMMC;
    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;
    c = inportb(portbase + MCR) | DTR | RTS;
    outportb(portbase + MCR, c);
}

/************************ Go off-line ******************************/
void comm_off(void)
{
	resvects();
 	if(VID && portbase==0xff10)
 	{
 		comm_on();
 		i_enable();
 	}
}
/****************************************/
void OpenSer(void)
{
    endbuf = startbuf = 0;
    setvects();
    comm_on();
}
/*******************************************************************
设置通讯波涛率参数子函数SetSpeed,由SerInit调用。
设置波涛率时需要保证DLAB=1
********************************************************************/
int SetSpeed(unsigned long int Speed)
{
    char		c;
    unsigned int		divisor;

    if (Speed == 0)            /* Avoid divide by zero */
        return (-1);
    else
      divisor = (unsigned int)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);
}

/*******************************************************************
设置通讯参数子函数SetOthers,由SerInit调用。
********************************************************************/
int 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;
    if(StopBit == 1)
	    Setting |= 0x00;
    else
	    Setting |= 0x04;

    Setting |= Parity;

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

    return (0);
}

/***************************************************************************
串口初始化函数SerInit
入口参数:	Port 串口地址如0x3f8;Speed 速率 如115200
		Parity 奇偶效验NO_PARITY无,EVEN_PARITY偶效验,ODD_PARITY奇效验
		Bits 数据位数如8,StopBit 停止位如1。
****************************************************************************/
SerInit(unsigned int Port, unsigned long int Speed, int Parity, int Bits, int StopBit)
{
	int flag = 0;
	portbase = Port;
	if (SetSpeed(Speed))
	  flag = -1;
	if (SetOthers(Parity, Bits, StopBit))
	  flag = -1;
	/***************************************************
	用户如需要打开FIFO请在这加入设置代码。
	****************************************************/
	if (!flag)
	   OpenSer();
	return flag;
}
/***************************************************************************
串口初始化程序
****************************************************************************/
void UART_INT(void)
{
	speed    = 115200L;	/*波特率参数*/
	parity   = NO_PARITY;		/*奇偶效验*/
	bits     = 8;			/*数据位数*/
	stopbits = 1;			/*停止位数*/

	SError = 0;
  portbase = COM5BASE;	
  startbuf = 0;	
  endbuf = 0;
  LastStatus = 0;
  COMMC=COM5MC;
	INTVECT=0x14;	     
  TXR=TXRCPU;       /*  Transmit register (WRITE) */
	RXR=RXRCPU;       /*  Receive register  (READ)  */
	IER=IERCPU;       /*  Interrupt Enable          */
	IIR=IIRCPU;       /*  Interrupt ID              */
	LCR=LCRCPU;       /*  Line control              */
	MCR=MCRCPU;       /*  Modem control             */
	LSR=LSRCPU;       /*  Line Status               */
	MSR=MSRCPU;       /*  Modem Status              */
	DLL=DLLCPU;       /*  Divisor Latch Low         */
	DLH=DLHCPU;
	IMR=IMRCPU;
	speed    = F115200;
	i_enable();
	SerInit(portbase, speed, parity, bits, stopbits);

}
/***************************************************************************
串口服务程序
****************************************************************************/
void UartServer(void)
{
	char c;
	
	if(SerRev(&c)!= -1)
  	{
  		SerSend(c);  //显示接收到的字符
  		switch(c&0x01)
  		{
  			case 0: SerSendStr((char*)str1);
  				LED=c;
  				break;
  			case 1: SerSendStr((char*)str2);
  				LED=c;
  				break;
  			default:
  				LED=0x00;
  				break;			
  		}  		
  	}
}

⌨️ 快捷键说明

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