蓝宇BBPC-SOM2496嵌入式主板六串口通用测试程序

源代码在线查看: com.bak

软件大小: 224 K
上传用户: enterjqk
关键词: BBPC-SOM 2496 嵌入式主板 串口
下载地址: 免注册下载 普通下载 VIP

相关代码

				/****************************************************************
				程序(函数)名称:ser977
				功能描述:	pcm3386的com1、com2是16550硬件兼容串口,除了可以调用
						bios进行通讯外,为了使用更高的串口通讯速率可以直接对串
						口硬件直接操作,例子用后一种方式编程,并使用中断方式接收,
						接收到的数据缓存在环行队列中。程序把串口波特率固定为115200,
						串口号用命令行参数传入,如:ser977 1为用1号串口,该例子
						只能用于1/2号串口.用中断方式编写串口程序时,在中断服务程
						序中没有特殊要求不需要用disable()、enable()关闭、打开中
						断。运行中程序会把键盘输入字符发送到相应的串口。按“ESC”
						键退出,该程序在bc45的large模式下测试通过。
				参数:		串口号,1或2
				作者:		陈道理
				日期:		04-6-14 
				****************************************************************/
				
				#include 
				#include 
				#include 
				#include 
				#include "COM.h"
				#include 
				#define VERSION 0x0101
				
				#define FALSE           0
				#define TRUE           (!FALSE)
				
				#define NOERROR         0       /* No error               */
				#define BUFOVFL         1       /* Buffer overflowed      */
				
				#define ESC             0x1B    /* ASCII Escape character */
				#define ASCII           0x007F  /* Mask ASCII characters  */
				#define SBUFSIZ         0x4000  /* Serial buffer size     */
				
				unsigned int	COMMC;
				unsigned char TXR,RXR,IER,IIR,LCR,MCR,LSR,MSR,DLL,DLH;
				unsigned int	IMR;
				unsigned char	FLAG;
				unsigned char INTVECT;
				
				int            SError          = NOERROR;
				int            portbase        = COM1BASE;	
				void           interrupt(*old_handler)();
				static   char  ccbuf[SBUFSIZ];		/*接受缓存,改变SBUFSIZ来改变大小*/
				unsigned int   startbuf        = 0;	
				unsigned int   endbuf          = 0;
				unsigned char  LastStatus      = 0;
				unsigned char  OldStatus =	0;
				
				
				
				
				/*****************************************************************************************
				未用fifo的中断服务程序例子,例子用中断接收数据并放入缓存中。发送没有用中断实现。用户如需要
				用中断发送字符,需要一个发送缓存,并把串口的发送中断打开。发送缓存的定义请参考接收缓存的定义。
				在中断处理例程里面需要增加发送中断处理。在用发送中断时主程序除了需要发送的数据放入发送缓存中,
				还需要判断缓存是否为空或满。当为空时必须重新启动发送否则不会产生发送中断。如缓存满时可以丢弃
				或等待。
				******************************************************************************************/
				void far interrupt com_int(void)				
				{
				    unsigned char Status = 0;
				    char Loop = 0;
				    unsigned int reg_serv;    
				    reg_serv = inport(REG_SVER);
				    if(FLAG)
				    {
				    	if(((reg_serv&0x0400)!= 0) && (portbase == 0xff80))
				    		goto HARDINT;
				    	if(((reg_serv&0x0200)!= 0) && (portbase == 0xff10))
				    		goto HARDINT;
					 		ENTRY_SOFT_INT(old_handler)
					 	}
				    
				HARDINT:
				    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;
					 }
					 if(!FLAG)
					 outportb(ICR977, EOI977);		/*中断应答*/
					 else
					 outport(ICRCPU, EOICPU);
				}               
				
				/************************************************************************
				不用中断发送时的发送函数,该函数每次发送一个字节。
				*************************************************************************/
				int SerSend(char x )
				{
				    long int           timeout;
				
				    	outportb(portbase + MCR,  MC_INT | DTR | RTS);
				
				    /* 硬件握手,如果用三线制时,需要把串口接成硬件握手自环方式或者把下面三句注释掉。*/
						if(!FLAG)
				    { 
				    	timeout = 0x0000FFFFL;   
				    	while ((inportb(portbase + MSR) & CTS) == 0)
				        if (!(--timeout))
									return -1;
						}
				
				    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;
				}
				
				/* 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;
				
						if(!FLAG)
				    	i_enable();
				    c = inportb(portbase + MCR) | DTR | RTS;
				    outportb(portbase + MCR, c);
				}
				
				/* Go off-line */
				void comm_off(void)
				{
					if(!FLAG)
						{
				    	i_disable();
				    	outportb(portbase + MCR, 0);
				    	resvects();
				  	}
				  else
				  	{
				  		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
				    	if(!FLAG)
				        divisor = (int) (115200L/Speed);
				      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(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;
				}
				
				int main(argc,argv)
				int argc;
				char *argv[];
				{
				    /* Communications parameters */
					unsigned long int        speed    = 115200L;	/*波特率参数*/
					int        parity   = NO_PARITY;		/*奇偶效验*/
					int        bits     = 8;			/*数据位数*/
					int        stopbits = 1;			/*停止位数*/
				
					int        done  = FALSE;
					char       c;
					 if(argc != 2)
					 {
				      printf("com COM_NUMBER\nCOM_NUMBER must be 1~5.\n");
						return 0;				/*命令行参数*/
					 }
				    switch(atoi(argv[1]))
				    {
						  case 1:
								 portbase = COM1BASE;
								 COMMC=COM1MC;
								 INTVECT=0xc;
								 FLAG=0;
								 break;
						  case 2:
								 portbase = COM2BASE;
								 COMMC=COM2MC;
								 INTVECT=0xb;
								 FLAG=0;
								 break;
						  case 3:
								 portbase = COM3BASE;
								 COMMC=COM3MC;
								 INTVECT=0xe;
								 FLAG=0;
								 break;
						  case 4:
								 portbase = COM4BASE;
								 COMMC=COM4MC;
								 INTVECT=0xd;
								 FLAG=0;
								 break;
							case 5:
								 portbase = COM5BASE;
								 COMMC=COM5MC;
								 INTVECT=0x14;
								 FLAG=1;
								 break;
							case 6:
								 portbase = COM6BASE;
								 COMMC=COM6MC;
								 INTVECT=0x11;
								 FLAG=1;
								 break;
				      default:
							printf("com COM_NUMBER\nCOM_NUMBER must be 1~5.\n");
									 return 0;
				    }
				    if(!FLAG)
				    	{
				    		TXR=TXR977;       /*  Transmit register (WRITE) */
								RXR=RXR977;      /*  Receive register  (READ)  */
								IER=IER977;       /*  Interrupt Enable          */
								IIR=IIR977;        /*  Interrupt ID              */
								LCR=LCR977;      /*  Line control              */
								MCR=MCR977;        /*  Modem control             */
								LSR=LSR977;         /*  Line Status               */
								MSR=MSR977;          /*  Modem Status              */
								DLL=DLL977;         /*  Divisor Latch Low         */
								DLH=DLH977;
								IMR=IMR977;
								speed    = 115200L;
							}
						else
							{
								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;
				    	}
				  
				  if(FLAG)  	
				  	i_enable();
					SerInit(portbase, speed, parity, bits, stopbits);
				    /*
				       The main loop acts as a dumb terminal. We repeatedly
				       check the keyboard buffer, and communications buffer.
					 */
				 	do {
				        	if (kbhit())
						{
				        	    /* Look for an Escape key */
				        	    	switch (c=getch())
				        		{
				        	        	case ESC: done = TRUE;  /* Exit program */
				        	                  	break;
				
				        	        /* You may want to handle other keys here... */
						    	}
						 	if (!done)
								SerSend(c);
						}
						if(SerRev(&c)!= -1)
						{
								//if (c != -1);
								//fputc(c & ASCII, stdout);
								 printf("%c",c);
						}
						
						/*打印接收状态*/
						if((LastStatus != OldStatus) && (LastStatus != 0))
						{
							switch(LastStatus)
							{
								case 1:
									printf("NO_INT\n");
									break;
								case 2:
									printf("URS_ID\n");
									break;
								case 3:
									printf("RX_ID\n");
									break;
								case 4:
									printf("FDT_ID\n");
									break;
								case 5:
									printf("TBRE_ID\n");
									break;
								case 6:
									printf("HSR_ID\n");
									break;
								case 7:
									printf("defaut\n");
									break;
								default:
									printf("no int\n");
									break;				
							}
							OldStatus = LastStatus;		
							LastStatus = 0;
						}
				
				    	} while (!done && !SError);
				    comm_off();
				    /* Check for errors */
				    switch (SError)
				    {
					case NOERROR: printf("\nbye.\n");
									  return (0);
				
					case BUFOVFL: printf("\nBuffer Overflow.\n");
									  return (99);
				
					default:      printf("\nUnknown Error, SError = %d\n");
									  return (99);
				    }
				}
				
							

相关资源