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

📄 serial.c

📁 基于philips的lpc2148开发源代码
💻 C
字号:

#include "configLPC.h" 
#include "serial.h"
#include <stdio.h>
#include <string.h>

/*放到ConfigLPC.h
#define UART0_FIFO_LENGTH	8
#define UART1_FIFO_LENGTH	8
//以下定义的缓冲区长度为4字节的倍数,如定义160,缓冲会有160×4-24=456字节
#define UART0_RXBUF_LENGTH	160
#define UART0_TXBUF_LENGTH	160
#define UART1_RXBUF_LENGTH	160
#define UART1_TXBUF_LENGTH	160
*/

INT32U rcv_buf0[UART0_RXBUF_LENGTH];					// UART0数据接收缓冲区
INT32U snd_buf0[UART0_TXBUF_LENGTH];					// UART0数据发送缓冲区
INT32U rcv_buf1[UART1_RXBUF_LENGTH];					// UART1数据接收缓冲区
INT32U snd_buf1[UART1_TXBUF_LENGTH];					// UART1数据发送缓冲区
unsigned long int g_dwCOM1IntTmout = 10;
unsigned long int g_dwCOM1TotalTmout = 300;
unsigned long int g_dwCOM2IntTmout = 10;
unsigned long int g_dwCOM2TotalTmout = 300;



/****************************************************************************
* 名称:UART0_Exception()
* 功能:串口UART0接收中断。
* 入口参数:无
* 出口参数:无
 U0LSR   UART0线状态寄存器 0xE000C014,
 U0RBR   UART0 接收器缓存寄存器 0xE000C000,DLAB=0,只读)
 U0IER   UART0 中断使能寄存器(0xE000C004 =0)
 U0IIR   UART0 中断标识寄存器( 0xE000C008,
 U0THR   UART0 发送器保持寄存器(0xE000C000,
****************************************************************************/
void UART0_Exception(void)
{                                                      
    uint8 IIR, temp, i;                                
                                                        
    OS_ENTER_CRITICAL();                                
    while(((IIR = U0IIR) & 0x01) == 0)                  
    {													// 有中断未处理完
        switch (IIR & 0x0e)
        {
            case 0x02:									// THRE中断
                for(i = 0; i < UART0_FIFO_LENGTH; i++)	// 向发送FIFO填充数据
                {
                    if(QueueRead(&temp, snd_buf0, FALSE) == QUEUE_OK)
                    {
                        U0THR = temp;                   
                    }
                    else                               

                    {                                    
                        U0IER &= ~0x02;					// 队列空,则禁止发送中断
                    }
                }
                break;
            case 0x04:									// 接收数据可用
			 	while(U0LSR&0X01)						// 读取FIFO的数据,并清除中断标志
	               QueueWrite((void *)rcv_buf0, &U0RBR, FALSE);
                break;
            case 0x06:									// 接收线状态
                temp = U0LSR;
                break;
            case 0x0c:									// 字符超时指示
			 	while(U0LSR&0X01)						// 读取FIFO的数据,并清除中断标志
	               QueueWrite((void *)rcv_buf0, &U0RBR, FALSE);
                break;
            default :
                break;
        }
    }
    VICVectAddr = 0;									// 通知中断控制器中断结束
    OS_EXIT_CRITICAL();
}


uint8 g_byReadSer;										//用来读空串口缓冲区的数据
uint8 Uart_RecvFull(DATAQUEUE *pBuf, uint8* pData, uint8 Mod)
{
	Mod = Mod;
	g_byReadSer = *(pData);
	return 1;
}

/****************************************************************************
* 名称:UART0_SendByte()
* 功能:向串口UART0发送字节数据。
* 入口参数:data                要发送的数据
* 出口参数:无
 U0LSR   UART0线状态寄存器 0xE000C014,
 U0RBR   UART0 接收器缓存寄存器 0xE000C000,DLAB=0,只读)
 U0IER   UART0 中断使能寄存器(0xE000C004 =0)
 U0IIR   UART0 中断标识寄存器( 0xE000C008,
 U0THR   UART0 发送器保持寄存器(0xE000C000,
****************************************************************************/
void  UART0_SendByte(INT8U data)
{
    uint8 temp;
    
    OS_ENTER_CRITICAL();
    QueueWrite((void *)snd_buf0, &data, FALSE);			// 数据入队
    if((U0LSR & 0X20) != 0)
    {													// UART0发送保持寄存器空
        QueueRead(&temp, snd_buf0, FALSE);				// 发送最初入队的数据
        U0THR = temp;
        U0IER |= 0X02;									// 允许发送中断
    }
    OS_EXIT_CRITICAL();
}

/****************************************************************************
* 名称:UART0_Ini()
* 功能:初始化串口0。设置其工作模式及波特率。
* 入口参数:baud                波特率
*           set          模式设置(UARTMODE数据结构)
* 出口参数:返回值为1时表示初始化成功,为0表示参数出错

U0LCR UART0线控制寄存器( - 0xE000C00C)U0LCR决定发送和接收数据字符的格式
U0DLM UART0除数锁存 MSB 寄存器( - 0xE000C004,DLAB=1)
U0DLL UART0 除数锁存 LSB 寄存器( - 0xE000C000,DLAB=1)
U0FCR 控制 UART0 Rx和Tx FIFO的操作
****************************************************************************/
BOOLEAN  UART0_Ini(INT32U baud, UARTMODE set)
{
	extern void UART0_Handler(void);
	INT32U  bak;
	
	PINSEL0 &= 0xFFFFFFF0;
	PINSEL0 |= 0x00000005;								// 设置I/O连接到UART0
	
	/* 参数过滤 */
	if((0==baud) || (baud>115200)) return FALSE;
	if((set.datab<5) || (set.datab>8)) return FALSE;
	if((0==set.stopb) || (set.stopb>2)) return FALSE;
	if(set.parity>4 ) return FALSE;
	
	/* 设置串口波特率 */
	U0LCR = 0x80;										// DLAB位置1
	bak = (Fpclk>>4)/baud;
	U0DLM = bak>>8;
	U0DLL = bak&0xff;
	
	/* 设置串口模式 */
	bak = set.datab-5;									// 设置字长度
	if(2==set.stopb) bak |= 0x04;						// 判断是否为2位停止位
	
	if(0!=set.parity)
	{
		set.parity = set.parity-1;
		bak |= 0x08;
	}
	bak |= set.parity<<4;								// 设置奇偶校验
	
	U0LCR = bak;
	
	QueueCreate((void *)rcv_buf0, sizeof(rcv_buf0), sizeof(uint8), NULL, Uart_RecvFull);
	QueueCreate((void *)snd_buf0, sizeof(snd_buf0), sizeof(uint8), NULL, NULL);
	
	U0FCR = 0x41;										// 使能FIFO,并设置触发点为4字节
	U0IER = 0x05;										// 允许接收中断及Rx线状态中断
	
	// 设置中断允许
	VICIntSelect = 0x00000000;							// 设置所有通道为IRQ中断
	VICVectCntl4 = 0x26;								// UART0中断通道分配到IRQ slot 1
	VICVectAddr4 = (uint32)UART0_Handler;				// 设置UART0向量地址
	VICIntEnable |= 0x00000040;							// 使能UART0中断
	
	return TRUE;
}

/****************************************************************************
* 名称:UART1_Exception()
* 功能:串口UART1接收中断。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void UART1_Exception(void)
{
    uint8 IIR, temp, i;
    
    OS_ENTER_CRITICAL();
    while(((IIR = U1IIR) & 0x01) == 0)
    {                                                   // 有中断未处理完
        switch (IIR & 0x0e)
        {
            case 0x02:									// THRE中断
                for(i = 0; i < UART1_FIFO_LENGTH; i++)	// 向发送FIFO填充数据
                {
                    if(QueueRead(&temp, snd_buf1, FALSE) == QUEUE_OK)
                    {
                        U1THR = temp;
                    }
                    else
                    {
                        U1IER &= ~0x02;					// 队列空,则禁止发送中断
                    }
                }
                break;
            case 0x04:									// 接收数据可用
			 	while(U1LSR&0X01)						// 读取FIFO的数据,并清除中断标志
	               QueueWrite((void *)rcv_buf1, &U1RBR, FALSE);
                break;
            case 0x06:									// 接收线状态
                temp = U1LSR;
                break;
            case 0x0c:									// 字符超时指示
			 	while(U1LSR&0X01)						// 读取FIFO的数据,并清除中断标志
	               QueueWrite((void *)rcv_buf1, &U1RBR, FALSE);
                break;
            default :
                break;
        }
    }
    VICVectAddr = 0;            						// 通知中断控制器中断结束
    OS_EXIT_CRITICAL();
}

void  UART1_SendByte(INT8U data)
{
    uint8 temp;
    
    OS_ENTER_CRITICAL();
    QueueWrite((void *)snd_buf1, &data, FALSE);			// 数据入队
    if((U1LSR & 0X20) != 0)
    {													// UART0发送保持寄存器空
        QueueRead(&temp, snd_buf1, FALSE);				// 发送最初入队的数据
        U1THR = temp;
        U1IER |= 0X02;									// 允许发送中断
    }
    OS_EXIT_CRITICAL();
}

BOOLEAN  UART1_Ini(INT32U baud, UARTMODE set)
{
	extern void UART1_Handler(void);
	INT32U  bak;

	//PINSEL0 &= 0x0000FFFF;
	//PINSEL0 |= 0x55550000;								// 设置I/O连接到UART1
	PINSEL0 = (PINSEL0 & (~(0x0F<<16))) | (0x05<<16);		// 设置I/O连接到UART1


	/* 参数过滤 */
	if((0==baud) || (baud>115200)) return FALSE;
	if((set.datab<5) || (set.datab>8)) return FALSE;
	if((0==set.stopb) || (set.stopb>2)) return FALSE;
	if(set.parity>4 ) return FALSE;

	/* 设置串口波特率 */
	U1LCR = 0X80;										// DLAB位置1
	bak = (Fpclk>>4)/baud;
	U1DLM = bak>>8;
	U1DLL = bak&0XFF;

	/* 设置串口模式 */
	bak = set.datab-5;									// 设置字长度
	if(2==set.stopb) bak |= 0x04;						// 判断是否为2位停止位

	if(0!=set.parity)
	{
		set.parity = set.parity-1;
		bak |= 0x08;
	}
	bak |= set.parity<<4;								// 设置奇偶校验

	U1LCR = bak;
	
	QueueCreate((void *)rcv_buf1, sizeof(rcv_buf1), sizeof(uint8), NULL, Uart_RecvFull);
	QueueCreate((void *)snd_buf1, sizeof(snd_buf1), sizeof(uint8), NULL, NULL);
	
	U1FCR = 0x41;										// 使能FIFO,并设置触发点为4字节
	U1IER = 0x05;										// 允许RBR中断,即接收中断

	/* 设置中断允许 */
	VICIntSelect = 0x00000000;							// 设置所有通道为IRQ中断
	VICVectCntl5 = 0x27;								// UART1中断通道分配到IRQ slot 2
	VICVectAddr5  = (uint32)UART1_Handler;				// 设置UART1向量地址
	VICIntEnable |= 0x00000080;							// 使能UART1中断
	
	return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

BOOLEAN SerPort_Open(INT8U byComPort, INT32U lBaud, UARTMODE modSet)
{
	switch(byComPort)
	{
	case COM1:
		UART0_Ini(lBaud, modSet);
		break;
	case COM2:
		UART1_Ini(lBaud, modSet);
		//rs485_init();
		//rs485_rx();
		break;
	}
	return TRUE;
}

BOOLEAN SerPort_Close(INT8U byComPort)
{
	switch(byComPort)
	{
	case COM1:
		PINSEL0 &= 0xFFFFFFF0;							//关TXD0,RXD0
		VICIntEnable &= 0XFFFFFFBF;						// 禁止UART0中断
		U0FCR |= 0X06;									// 清FIFO
		QueueFlush((void*)rcv_buf0);
		QueueFlush((void*)snd_buf0);
		break;
	case COM2:
		PINSEL0 &= 0xFFF0FFFF;							//关TXD1,RXD1
		VICIntEnable &= 0XFFFFFF7F;						// 禁止UART1中断
		U1FCR |= 0X06;									// 清FIFO
		QueueFlush((void*)rcv_buf1);
		QueueFlush((void*)snd_buf1);
		break;
	}
	return TRUE;
}

BOOLEAN SerPort_IsOpen(INT8U byComPort)
{
	switch(byComPort)
	{
	case COM1:
		return (BOOLEAN)(PINSEL0 & 0x00000001);
	case COM2:
		//10987654321098765432109876543210
		//00000000000000010000000000000000	0X00010000
		return (BOOLEAN)(PINSEL0 & 0X00010000);
	}
	return FALSE;
}

BOOLEAN SerPort_Avail(INT8U byComPort)
{
	switch(byComPort)
	{
	case COM1:
		return (QueueNData((void*)rcv_buf0) > 0);
	case COM2:
		return (QueueNData((void*)rcv_buf1) > 0);
	}
	return FALSE;
}

INT16S SerPort_BuffedLen(INT8U byComPort, UARTBUF enWhichBuf)
{
	switch(byComPort)
	{
	case COM1:
		if(enWhichBuf == enTxBuf)
		{
			return (QueueNData((void*)snd_buf0));
		}
		else
		{
			return (QueueNData((void*)rcv_buf0));
		}
		break;
	case COM2:
		if(enWhichBuf == enTxBuf)
		{
			return (QueueNData((void*)snd_buf1));
		}
		else
		{
			return (QueueNData((void*)rcv_buf1));
		}
		break;
	}
	return 0;
}

BOOLEAN SerPort_IsTxIdle(INT8U byComPort)
{
	switch(byComPort)
	{
	case COM1:
		if((U1LSR & 0X20) != 0)
			return TRUE;
		else
			return FALSE;
	case COM2:
		if((U1LSR & 0X20) != 0)
			return TRUE;
		else
			return FALSE;
	}
	return FALSE;
}

void SerPort_Clear(INT8U byComPort, UARTBUF enWhichBuf)
{
	switch(byComPort)
	{
	case COM1:
		if(enWhichBuf == enTxBuf)
		{
			U0FCR |= 0X04;								// 清TX FIFO
			QueueFlush((void*)snd_buf0);
		}
		else
		{
			U0FCR |= 0X02;								// 清RX FIFO
			QueueFlush((void*)rcv_buf0);
		}
		break;
	case COM2:
		if(enWhichBuf == enTxBuf)
		{
			U1FCR |= 0X04;								// 清TX FIFO
			QueueFlush((void*)snd_buf1);
		}
		else
		{
			U1FCR |= 0X02;								// 清RX FIFO
			QueueFlush((void*)rcv_buf1);
		}
		break;
	}
}

INT16S SerPort_SendBuf(INT8U byComPort, INT8U *pcBuf, INT16U nSize)
{
	INT16U wLoop;

	switch(byComPort)
	{
	case COM1:
		rs485_tx(COM1);
		for(wLoop=0; wLoop<nSize; wLoop++)
		{
			UART0_SendByte(*(pcBuf+wLoop));
		}
		rs485_rx(COM1);
		break;
	case COM2:
		rs485_tx(COM2);
		for(wLoop=0; wLoop<nSize; wLoop++)
		{
			UART1_SendByte(*(pcBuf+wLoop));
		}
		rs485_rx(COM2);
		break;
	}
	return ((INT16S)nSize);
}

INT16S SerPort_SendByte(INT8U byComPort, INT8U c)
{
	switch(byComPort)
	{
	case COM1:
		UART0_SendByte(c);
		break;
	case COM2:
		UART1_SendByte(c);
		break;
	}
	return 1;
}

INT16S SerPort_RecvBuf(INT8U byComPort, INT8U *pcBuf, INT16U nSize, INT16U nTickCnt)
{
	INT16U wRecLen=0;

	ULONG dwStartTime = OSTime;
	switch(byComPort)
	{
	case COM1:
		//Led_Ctl(LED_232, LED_ON);
		while((dwStartTime + nTickCnt) > OSTime)
		{
			for(; wRecLen<nSize; wRecLen++)
			{
				if(QueueRead(pcBuf+wRecLen, (void*)rcv_buf0, TRUE) != QUEUE_OK)
					break;
			}
			
			if(wRecLen >= nSize)
			{
				break;
			}
			OSTimeDly(1);//延时
		}
		return wRecLen;
	case COM2:
		Led_Ctl(LED_485, LED_ON);
		while((dwStartTime + nTickCnt) > OSTime)
		{
			for(; wRecLen<nSize; wRecLen++)
			{
				if(QueueRead(pcBuf+wRecLen, (void*)rcv_buf1, TRUE) != QUEUE_OK)
					break;
			}
			
			if(wRecLen >= nSize)
			{
				break;
			}
			OSTimeDly(1);//延时
		}
		return wRecLen;
	}
	return wRecLen;
}

INT16S SerPort_RecvByte(INT8U byComPort, INT8U *pc)
{
	switch(byComPort)
	{
	case COM1:
		if(QueueRead(pc, (void*)rcv_buf0, TRUE) == QUEUE_OK)
			return 1;
		else
			return 0;
	case COM2:
		if(QueueRead(pc, (void*)rcv_buf1, TRUE) == QUEUE_OK)
			return 1;
		else
			return 0;
	}
	return 1;
}

⌨️ 快捷键说明

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