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

📄 uart.c

📁 针对飞利浦LPC214x的虚拟串口程序
💻 C
字号:

/*******************************************************************
* 文 件 名:	 uart.c
*版本/时间:	 v1.10  2006/06/29
* 描    述:	 UART0/1的通讯例程,假设Fosc=12M,Fcclk=Fpclk=60M
* 作    者:	 lenglx
*-------------------------------------------------------------------
* 修改记录:
* 修改时间:
* 描    述:
* 修 改 人:
*******************************************************************/

#include <LPC214X.H>
#include "type.h"
#include "usb.h"
#include "usbcfg.h"
#include "usbhw.h"
#include "uart.h"


// 4个缓冲区,uart0接收/发送,uart1接收/发送
// 接收缓冲区的数据要等待USB读取,如果USB读取不及时,有可能丢失数据,所以缓冲区可设置稍微大点.

#define	RCV_BUF_LEN		1024
#define	SEND_BUF_LEN	512

BYTE	SendBuf0[SEND_BUF_LEN];
BYTE	RcvBuf0[RCV_BUF_LEN];
BYTE	SendBuf1[SEND_BUF_LEN];
BYTE	RcvBuf1[RCV_BUF_LEN];
DWORD	r_first0, r_first1, r_next0, r_next1;
DWORD 	s_first0, s_first1, s_next0, s_next1;


/*
	发送/接收 缓冲区是1个循环缓冲,如下图.

  图 1)
       |       |first                    |next                     |
       |  not  |                         |                         |
       +-used--+--------valid data-------+---------not used--------+
       |       v                         v                         |
       .-----------------------------------------------------------.
       |                  recive or send buffer                    |
       '-----------------------------------------------------------'


   图 2)
       |       |next                     |first                    |
       | valid |                         |                         |
       +-data--+--------not used---------+-------valid data--------+
       |       v                         v                         |
       .-----------------------------------------------------------.
       |                  recive or send buffer                    |
       '-----------------------------------------------------------'


	位于first和next之间的区域是已经接收的数据或者将要发送的数据.
	其它区域是空的区域.
	此缓冲区是1个循环缓冲区,当指针达到缓冲区的末尾,将循环到缓冲区头重新开始.
	当first==next,表示是整个缓冲区无任何数据.
	当next=first-1,表示缓冲区已满.
*/

/*******************************************************************
* 功能描述: 重置缓冲区指针	
* 参    数:
* 返    回:
* 备    注:	
*******************************************************************/

void	ResetBufferPointer(DWORD dwPortNum)
{
	if(dwPortNum==0)
	{
		s_first0 = s_next0 = 0;
		r_first0 = r_next0 = 0;
	}
	else
	{
		s_first1 = s_next1 = 0;
		r_first1 = r_next1 = 0;
	}
}
 
/*******************************************************************
* 功能描述: 	
* 参    数:
* 返    回:
* 备    注:	
*******************************************************************/
void	UartDataToHost(DWORD dwPort)
{
	BYTE tmpbuf[USB_MAX_PACKET];
	DWORD dwEp;
	DWORD next;
	DWORD first;
	BYTE * pBuf;
	DWORD i;
	DWORD dwCnt;

	// 因为此函数调用比较频繁,在没数据的时候尽量快点返回
	if( (dwPort==0 && r_next0==r_first0) || (dwPort==1 && r_next1==r_first1))
		return;
		

 	dwEp 	= dwPort==0 ? 2 : 5;
	next 	= dwPort==0 ? r_next0 : r_next1;
	first = dwPort==0 ? r_first0 : r_first1;
	pBuf = dwPort==0 ? RcvBuf0 : RcvBuf1;
 	dwCnt = USB_MAX_PACKET;
 	i=0;

	// 将接收缓冲区的数据移动到tmpbuf
	while(dwCnt--)
	{
		if(next == first)
			break;
		tmpbuf[i] = pBuf[first];
		if(++first >= RCV_BUF_LEN)
			first = 0;
		i++;
	}
	USB_WriteEP(dwEp | 0x80, tmpbuf, i);

	if(dwPort == 0)
		r_first0 = first;
	else
		r_first1 = first;
}
/*******************************************************************
* 功能描述: 将从USB来的数据发送到UART端口	
* 参    数:
* 返    回:
* 备    注:	
*******************************************************************/
void	HostDataToUart(DWORD dwPort)
{
	BYTE tmpbuf[USB_MAX_PACKET];
	DWORD dwEp 	= dwPort==0 ? 2 : 5;
	DWORD next 	= dwPort==0 ? s_next0 : s_next1;
	DWORD first = dwPort==0 ? s_first0 : s_first1;
	BYTE * pBuf = dwPort==0 ? SendBuf0 : SendBuf1;
	DWORD dwCnt	= USB_ReadEP(dwEp, tmpbuf);
	DWORD i=0;
	// 将数据移到发送缓冲区
	while(dwCnt--)
	{
		if(next == first-1)
			break;
		pBuf[next] = tmpbuf[i];
		if(++next >= SEND_BUF_LEN)	
			next = 0;
		i++;
	}

	if(dwPort == 0)
	{
		s_next0 = next;
		if(U0LSR & 0x40 && s_first0 != s_next0)	// 发送器为空,需要重新启动发送
		{
			U0THR = pBuf[s_first0];
			if(++s_first0 >= SEND_BUF_LEN)
				s_first0 = 0;
		}
	}
	else
	{
		s_next1 = next;
		if(U1LSR & 0x40 && s_first1 != s_next1)
		{
			U1THR = pBuf[s_first1];
			if(++s_first1 >= SEND_BUF_LEN)
				s_first1 = 0;
		}
	}
}

/*******************************************************************
* 功能描述:	irq中断函数,处理UART0的字节接收/发送
* 参    数:
* 返    回:
* 备    注:	
*******************************************************************/
void	Uart0_irq(void) __irq
{
	uchar 	iir,ch;
	while(1)  // 循环处理,直到UART0中无任何挂起的中断
	{
		if((iir = U0IIR) & 1)
			break;
		switch(iir & 0x0e)
		{
		case 0x04:	// RDA.
		case 0x0c:	// CTI.
			while(U0LSR & 1)  //将fifo中的所有数据读完
			{
				ch = U0RBR;
				if(r_next0 != r_first0-1)
				{
					RcvBuf0[r_next0] = ch;
					if (++r_next0 >= RCV_BUF_LEN)
						r_next0 = 0;
				}
			}
			break;

		case 0x02:	// THR Empty.
			{
				DWORD nCnt = 16; //fifo counter
				while( s_next0 != s_first0 && nCnt--)
				{
					U0THR = SendBuf0[s_first0];
					if(++s_first0 >= SEND_BUF_LEN)
						s_first0 = 0;
				}
			}
		   	break;
		default:
			;
		}  
	} 

   	VICVectAddr=0;
}

void	Uart1_irq(void) __irq
{
	uchar 	iir,ch;
	while(1)  // 循环处理,直到UART1中无任何挂起的中断
	{
		if((iir = U1IIR) & 1)
			break;
		switch(iir & 0x0e)
		{
		case 0x04:	// RDA.
		case 0x0c:	// CTI.
			while(U1LSR & 1)  //将fifo中的所有数据读完
			{
				ch = U1RBR;
				if(r_next1 != r_first1-1)
				{
					RcvBuf1[r_next1] = ch;
					if (++r_next1 >= RCV_BUF_LEN)
						r_next1 = 0;
				}
			}
			break;

		case 0x02:	// THR Empty.
			{
				DWORD nCnt = 16; //fifo counter
				while( s_next1 != s_first1 && nCnt--)
				{
					U1THR = SendBuf1[s_first0];
					if(++s_first1 >= SEND_BUF_LEN)
						s_first1 = 0;
				}
			}
		   	break;
		default:
			;
		}  
	} 

   	VICVectAddr=0;
}


/*******************************************************************
* 功能描述:	  初始化UART0
* 参    数:
* 返    回:
* 备    注:	
*******************************************************************/
void 	InitUart (void) 
{
	// 配置UART管脚
	PINSEL0 = (PINSEL0 & (~0x0f000f)) | 0x050005;	// set p0[1..0] for uart0

	ResetBufferPointer(0);
	ResetBufferPointer(1);

	U0LCR = 0x83;			   	//  默认"9600,n,8,1"
	SET_UART0_BAUD(9600)				
	U0LCR = 0x03;
	U0IER = 0x03;				// enable rx/tx interrupt.
	U0FCR = 1 | (2<<6);			// enable fifo,8 byte

	U1LCR = 0x83;			   	//  默认"9600,n,8,1"
	SET_UART1_BAUD(9600)				
	U1LCR = 0x03;
	U1IER = 0x03;				// enable rx/tx interrupt.
	U1FCR = 1 | (2<<6);			// enable fifo,8 byte

	//设置向量中断
	VICVectAddr3 = (unsigned long)Uart0_irq;
	VICVectCntl3 = 0x20 | 6;                    
	VICIntEnable = 1 << 6 ;

	VICVectAddr4 = (unsigned long)Uart1_irq;
	VICVectCntl4 = 0x20 | 7;                    
	VICIntEnable = 1 << 7 ;
}

⌨️ 快捷键说明

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