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

📄 a0acd09115c5001d1a38f54921afee39

📁 基于FREERtos和LPC2468的程序。里面实现了串口通信
💻
字号:
/*****************************************************************************
 *   uart.c:  UART API file for NXP LPC23xx/24xx Family Microprocessors
 *
 *   Copyright(C) 2006, NXP Semiconductor
 *   All rights reserved.
 *
 *   History
 *   2006.07.12  ver 1.00    Prelimnary version, first Release
 *
******************************************************************************/

// modified by Martin Thomas
// - const BYTE in send
#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"
#include "LPC23xx.h"                        /* LPC23xx/24xx definitions */
#include "type.h"
#include "target.h"
#include "irq.h"
#include "uart.h"
#include "string.h"
//#include "portmacro.h"

#define UART_RATE_BASE  ( ( portTickType ) 20 )    // UART's base tick is 20ms
#define UART_STACK_SIZE		configMINIMAL_STACK_SIZE
/* UART0 interrupt service routine handler. */
void vUART_ISR_Handler( void );
/* Queues used to hold received characters, and characters waiting to be
transmitted. */
static xQueueHandle xRxedChars; 
static xQueueHandle xCharsForTx; 
static volatile portLONG lTHREEmpty;
void PushACharIntoRcvBuffer(unsigned char rChr);
/*-----------------------------------------------------------*/



#define BUFSIZE UART_BUFSIZE
volatile DWORD UART0Status, UART1Status;
volatile BYTE UART0TxEmpty = 1, UART1TxEmpty = 1;
volatile BYTE UART0Buffer[BUFSIZE], UARTTxBuffer[BUFSIZE];
volatile DWORD UART0Count = 0, UARTTxCount = 0,UARTTxOffset=0;

/* 
 * The queues are created in serialISR.c as they are used from the ISR.
 * Obtain references to the queues and THRE Empty flag. 
 */
void vSerialISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, xQueueHandle *pxCharsForTx, portLONG volatile **pplTHREEmptyFlag );
extern void IntDisable(void)  ;
extern void IntEnable(void) ;
extern void myuart_irq(void);



void UART0Handler (void) __irq //__attribute__((naked))
{
	
	IntDisable();
	//portSAVE_CONTEXT();
	UART0_Handler();
	//portRESTORE_CONTEXT();
	IntEnable();
}

/*-----------------------------------------------------------*/
void vSerialISRCreateQueues(	unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, 
								xQueueHandle *pxCharsForTx, portLONG volatile **pplTHREEmptyFlag )
{
	/* Create the queues used to hold Rx and Tx characters. */
	xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
	xCharsForTx = xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );

	/* Pass back a reference to the queues so the serial API file can 
	post/receive characters. */
	*pxRxedChars = xRxedChars;
	*pxCharsForTx = xCharsForTx;

	/* Initialise the THRE empty flag - and pass back a reference. */
	lTHREEmpty = ( portLONG ) pdTRUE;
	*pplTHREEmptyFlag = &lTHREEmpty;
}

/*----------------------------------------------------  */
#define recv_ok			0x05
#define err_bcc 		0x01
#define err_busy 		0x02
#define err_cmd 		0x03
#define err_flag 		0x04

/*----------------------------------------------------  */
#define ERROR_INIT		0x05		//初始值
#define ERROR_ID        0x03        //错误ID
#define ERROR_CMD		0x03        //无此命令
#define ERROR_TOO_LONG  0x03		//数据太长
#define ERROR_ETX		0x03        //标志位错
#define ERROR_BCC       0x01		//校验码错
#define EEROR_OVER_TIME 0x04        // 超时
#define ERROR_SUCCESS	0x00		//接收成功

#define MKD_ID			0x2c

#define RCV_STX				0x01
#define RCV_ID				0x02
#define RCV_LENGTH			0x03
#define RCV_CMD_CODE		0x04
#define RCV_ETX				0x05
#define RCV_BCC				0x06
#define RCV_IDLE			0x00
#define FINISH				0x01
#define WAITTINGDATA		0x00
#define STX					0X02
#define ETX					0X03
/*----------------------------------------------------  */

struct CmdRcv CmdRcvIrq;
/*----------------------------------------------------  */
void PushACharIntoRcvBuffer(unsigned char rChr)
{
	
			switch(CmdRcvIrq.rcvflg)
			{
				case RCV_STX:
					if(rChr==STX)
					{
						CmdRcvIrq.rcvflg=RCV_ID;						
						CmdRcvIrq.bcc=CmdRcvIrq.bcc^rChr;
						CmdRcvIrq.time_flag=1;
					}
					break;
					
				case RCV_ID:
				
					if(rChr!=MKD_ID)				//如果ID错误,放弃接收后面字节,返回ERROR_ID
					{
					   CmdRcvIrq.errcode=ERROR_ID;
					   CmdRcvIrq.cResult=FINISH;
					   CmdRcvIrq.rcvflg=RCV_IDLE;
					}else
					{
						CmdRcvIrq.bcc=CmdRcvIrq.bcc^rChr;
						CmdRcvIrq.rcvflg=RCV_LENGTH;
					}
					CmdRcvIrq.time_flag=1;
					break;
					
				case RCV_LENGTH:
				
					CmdRcvIrq.len=rChr;
					if(CmdRcvIrq.len>MAX_RCV_LENGTH_CMD_MKD)	//数据长度超出范围
					{
						CmdRcvIrq.errcode=ERROR_TOO_LONG;		//接收结果为真,返回ERROR_TOO_LONG
						CmdRcvIrq.cResult=FINISH;
						CmdRcvIrq.rcvflg=RCV_IDLE;
					}else
					{
						CmdRcvIrq.bcc=CmdRcvIrq.bcc^rChr;
						CmdRcvIrq.offset=0;
						CmdRcvIrq.rcvflg=RCV_CMD_CODE;
					}
					CmdRcvIrq.time_flag=1;
					break;	
				case RCV_CMD_CODE:
					CmdRcvIrq.buffer[CmdRcvIrq.offset]=rChr;
					CmdRcvIrq.bcc=CmdRcvIrq.bcc^rChr;
					CmdRcvIrq.offset++;
					if(CmdRcvIrq.offset==CmdRcvIrq.len)
					{
						CmdRcvIrq.rcvflg=RCV_ETX;
					}
					CmdRcvIrq.time_flag=1;
					break;
					
				case RCV_ETX:
				
					if(rChr!=ETX)
					{
					   CmdRcvIrq.errcode=ERROR_ETX;
					   CmdRcvIrq.rcvflg=RCV_IDLE;
					}else
					{
						CmdRcvIrq.bcc=CmdRcvIrq.bcc^rChr;
						CmdRcvIrq.rcvflg=RCV_BCC;
					}
					CmdRcvIrq.time_flag=1;
					break;			
				case RCV_BCC:
				
					CmdRcvIrq.cResult=FINISH;			//接收完一次,需要回复消息
					CmdRcvIrq.rcvflg=RCV_IDLE;	
					CmdRcvIrq.time_flag=0;
					//if((CmdRcvIrq.bcc==rChr)&&(CmdRcvIrq.errcode==0x00))
					{
							CmdRcvIrq.errcode=ERROR_SUCCESS;
					}
					//else if(CmdRcvIrq.bcc!=rChr)
					{
							//CmdRcvIrq.errcode=ERROR_BCC;
					}
					break;
				case RCV_IDLE:
				default:
			    	
					break;	
			}
}
/*****************************************************************************
** Function name:		UART0Handler
**
** Descriptions:		UART0 interrupt handler
**
** parameters:			None
** Returned value:		None
** 
*****************************************************************************/
void UART0_Handler (void)
{
    BYTE IIRValue, LSRValue;
    volatile BYTE Dummy = Dummy;
	 signed portCHAR cChar;
	//portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
   //portENTER_CRITICAL();
    IIRValue = U0IIR;
    IIRValue >>= 1;			/* skip pending bit in IIR */
    IIRValue &= 0x07;			/* check bit 1~3, interrupt identification */
    if ( IIRValue == IIR_RLS )		/* Receive Line Status */
    {
		LSRValue = U0LSR;
		/* Receive Line Status */
		if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
		{
	    	/* There are errors or break interrupt */
	    	/* Read LSR will clear the interrupt */
	    	UART0Status = LSRValue;
	    	Dummy = U0RBR;		/* Dummy read on RX to clear 
								interrupt, then bail out */
	    	//IDISABLE;
	    	VICVectAddr = 0;		/* Acknowledge Interrupt */
	    	return;
		}
		if ( LSRValue & LSR_RDR )	/* Receive Data Ready */			
		{
	    	/* If no error on RLS, normal ready, save into the data buffer. */
	    	/* Note: read RBR will clear the interrupt */
	    	cChar = UART0_RBR;
	    	PushACharIntoRcvBuffer(cChar);
	    	//xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );
		}
    }
    else if ( IIRValue == IIR_RDA )	/* Receive Data Available */
    {
		/* Receive Data Available */
		cChar = UART0_RBR;
		PushACharIntoRcvBuffer(cChar);
		//xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );
    }
    else if ( IIRValue == IIR_CTI )	/* Character timeout indicator */
    {
		/* Character Time-out indicator */
		UART0Status |= 0x100;		/* Bit 9 as the CTI error */
    }
    else if ( IIRValue == IIR_THRE )	/* THRE, transmit holding register empty */
    {
		/* THRE interrupt */
		LSRValue = U0LSR;		/* Check status in the LSR to see if
								valid data in U0THR or not */
		//UARTTxCount=0;
		if ( LSRValue & LSR_THRE )
		{
	    	UART0TxEmpty = 1;
	    	if(UARTTxOffset <UARTTxCount)
	    	{
	    		U0THR=UARTTxBuffer[UARTTxOffset];
	    		UARTTxOffset++;
	    	}else
	    		{
	    			UARTTxOffset=0;
	    			UARTTxCount=0;
	    		}
		}
		else
		{
	    	UART0TxEmpty = 0;
		}
		
    }
    VICVectAddr = 0;		/* Acknowledge Interrupt */
   // portEXIT_CRITICAL();
  
}



/*****************************************************************************
** Function name:		UARTInit
**
** Descriptions:		Initialize UART0 port, setup pin select,
**						clock, parity, stop bits, FIFO, etc.
**
** parameters:			portNum(0 or 1) and UART baudrate
** Returned value:		true or false, return false only if the 
**						interrupt handler can't be installed to the 
**						VIC table
** 
*****************************************************************************/
DWORD UARTInit( DWORD PortNum, DWORD baudrate )
{
    DWORD Fdiv;
    memset(&CmdRcvIrq,0x0,sizeof(CmdRcvIrq));	/* clear the struct of receive irq */
    
	if ( PortNum == 0 )
	{
		PINSEL0 = 0x00000050;       /* RxD0 and TxD0 */
    	U0LCR = 0x83;		/* 8 bits, no Parity, 1 Stop bit */
		Fdiv = ( Fpclk / 16 ) / baudrate ;	/*baud rate */
		U0DLM = Fdiv / 256;							
		U0DLL = Fdiv % 256;
		U0LCR = 0x03;		/* DLAB = 0 */
		U0FCR = 0x07;		/* Enable and reset TX and RX FIFO. */
    	if ( install_irq( UART0_INT, (void *)myuart_irq, 1 ) == FALSE )
    	{
			return (FALSE);
    	}
    	U0IER = IER_RBR | IER_THRE | IER_RLS;	/* Enable UART0 interrupt */
    	return (TRUE);
	}
	
	return( FALSE ); 
}

/*****************************************************************************
** Function name:		UARTSend
**
** Descriptions:		Send a block of data to the UART 0 port based
**						on the data length
**
** parameters:			portNum, buffer pointer, and data length
** Returned value:		None
** 
*****************************************************************************/
void xUARTSend(  const uint8 *BufferPtr, uint8 Length )
{
	/*
	while ( Length != 0)
	{
		  //THRE status, contain valid data 
		  while ( !(UART0TxEmpty & 0x01) );	
		  U0THR = *BufferPtr;
		  UART0TxEmpty = 0;	//not empty in the THR until it shifts out
		  BufferPtr++;
		  Length--;
	}*/

		while ( !(UART0TxEmpty & 0x01) );
		memcpy(UARTTxBuffer,BufferPtr,Length);
		UARTTxCount=Length;
		UARTTxOffset=1;	
		U0THR = *BufferPtr; 
		return;
}
/*****************************************************************************
** Function name:		UARTReceive
**
** Descriptions:		
**
** parameters:			
** Returned value:		
** 
*****************************************************************************/
int xUARTRead( const BYTE *BufferPtr, DWORD *Length )
{
		int retcode;
		if(CmdRcvIrq.cResult!=FINISH) return 0x0f;	//是否接收完一个有用的数据包
			portENTER_CRITICAL();
			if(CmdRcvIrq.errcode==ERROR_SUCCESS)		//如果接收正确
			{	
				memcpy(BufferPtr,CmdRcvIrq.buffer,CmdRcvIrq.len);
				*Length=(DWORD)CmdRcvIrq.len;
			}
			retcode=CmdRcvIrq.errcode;
			xUARTStartReceive();
			portEXIT_CRITICAL();
		return retcode;
}
/*-----------------------------------------------------------------------------------
 * **********************************************************************************
 * UART Restart.Initialize UART receive status.
 * CmdRcvIrq 是接收状态字。它表明了串口接收的状态。
 * 
 * **********************************************************************************
 * --------------------------------------------------------------------------------- */
void  xUARTStartReceive(void)
{
				portENTER_CRITICAL();				
				CmdRcvIrq.errcode=ERROR_INIT;
				CmdRcvIrq.cResult=WAITTINGDATA;
				CmdRcvIrq.rcvflg=RCV_STX;	
				CmdRcvIrq.time_flag=0x00;
				portEXIT_CRITICAL();
}
/*----------------------------------------------------------------------------------
 * function : xStartU0CHECKTasks
 * specification: 检测2个接收字节之间是否超时 , CmdRcvIrq.time_flag>2表示超时。
 * 
 * parameter : 每隔20ms检测一次
 * 
 * ---------------------------------------------------------------------------------*/
static portTASK_FUNCTION_PROTO( vU0CHECKTask, pvParameters );
void vStartU0CHECKTasks( unsigned portBASE_TYPE uxPriority )
{
	/* Create the task. */
	xTaskCreate(vU0CHECKTask,( signed portCHAR * )"U0CHECK", UART_STACK_SIZE, NULL, uxPriority, ( xTaskHandle * ) NULL );
		
}

static portTASK_FUNCTION(vU0CHECKTask, pvParameters)
{
	portTickType xUartRate, xLastUartTime;
	
	/* The parameters are not used. */
	( void ) pvParameters;
	xUartRate = UART_RATE_BASE ;
	xUartRate /= portTICK_RATE_MS;
	/* We need to initialise xLastkbdTime prior to the first call to vTaskDelayUntil(). */
	xLastUartTime = xTaskGetTickCount();
	for(;;)
	{
		/* Delay for half the flash period then turn the LED on. 	*/
		vTaskDelayUntil( &xLastUartTime, xUartRate );
		if(CmdRcvIrq.time_flag>2)
		{
			xUARTStartReceive(); 		//restart the received status
		}
	}
} 
/*-----------------------------------------------------------------------
 * 
 * 
 *     Send a byte to the upper
 * 
 * 
 * ----------------------------------------------------------------------*/

void  SendByte(BYTE chr)
{  
	//while ( !(UART0TxEmpty & 0x01) );	
   U0THR=chr;
   while( (U0LSR&0x20)==0 );         	// 等待数据发送
   //sDelayNS(2);
}           

⌨️ 快捷键说明

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