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

📄 uart.c

📁 RC5000读卡芯片和LPC213X的源码参考程序 内含详细说明
💻 C
字号:
#define UART_GLOBALS
#include "config.h"

static uint8 SerLen,ExtData;
static uint8 LenSend;			//已发送的有效数据长度

/*
*********************************************************************************************************
** 函数名称:
** 函数功能:串口0中断服务程序
*********************************************************************************************************
*/
void __irq UART0_Isr(void)
{
	uint8 IIR;
	uint8 temp;

	while(((IIR = U0IIR) & 0x01) == 0x00)
	{
		switch(IIR&0x0e)
		{
//=======================================================================================================
		    case 0x06:                        // 线状态
	            temp = U0LSR;                 // 读出线状态
		        break;
		            
//=======================================================================================================		
			case 0x04:			// 接收中断
			case 0x0C:			// 超时中断
		    {
				temp = U0RBR;	// 读取数据
				
		    	if(temp == STX)
				{	//在任何时候收到STX,即可视为一帧的开始
					RcvStatus = RCVDATA;
					SerLen = 0;
					RcvDTLen = 0;
					SerTmOut = 2;			//启动超时定时器
				}
				else if(temp == ETX)
				{
					if(RcvStatus == RCVDATA)
					{	
						if(SerTmOut)		
						{					//在未超时的情况下,接收数据后又收到一个ETX,则本帧数据有效
							SerDTValid = TRUE;
						}
						RcvStatus = RCVSTX;
					}
				}
				//=======================================================================================
				else if(RcvStatus == RCVDATA)
				{					
					if((SerTmOut==0) || (temp&0x80))
						RcvStatus = RCVSTX;		//超时或数据中的bit7为1,则本帧数据作废
					else
					{
						SerTmOut = 2;		
	        			if((SerLen&0x07) == 0)
						{	
							//扩展字节
							ExtData = temp;
						}
						else
						{
							if(ExtData & 0x01)
							{
								temp |= 0x80;
							}
						SerBfr[RcvDTLen++] = temp;
						ExtData >>= 1;
						}
						
						SerLen++;
					}
				}
				
				//=======================================================================================
				if(SerDTValid)
				{
					SerDTValid = FALSE;
					if(RcvDTLen == (SerBfr[LENGTH]+6))
					{
						temp = 0;
						for(SerLen=0;SerLen<RcvDTLen;SerLen++)
							temp ^= SerBfr[SerLen];
						if(temp == 0xff)
						{
							if(SerBfr[RADDR] == MyAddr)
							{
								SerDTValid = TRUE;
							}
						}
					}
				}	
			
		      	break;
		    }
		    
//=======================================================================================================		
		    case 0x02:							// 发送中断
    		{
        		if(SendStatus == SENDSTX)
				{
					U0THR = STX;
					SendStatus = SENDDATA;		//下次中断发送数据
					SerLen = 0;
					LenSend = 0;
				}
				else if(SendStatus == SENDDATA)
				{
					if((SerLen&0x07) == 0)
					{
						ExtData = 0;
						temp = LentoSend>=7?7:LentoSend;	//计算扩展数据位长度
						do
						{
							ExtData <<= 1;
							if(SerBfr[LenSend+(temp-1)]&0x80)
								ExtData |=0x01;
								temp--; 
						}while(temp);
					
						U0THR = ExtData;			//发送扩展数据
					}
					else
					{
						U0THR = SerBfr[LenSend]&0x7f;
						LenSend++;
						LentoSend--;
						if(LentoSend == 0)
						{							//有效数据已发送完毕
							SendStatus = SENDETX;	//下次中断发送ETX
						}
					}
					SerLen++;
				}
				else if(SendStatus == SENDETX)
				{
					U0THR = ETX;					//发送ETX
					SendStatus = SENDSTOP;			//下次中断结束本次发送
				}
				else if(SendStatus == SENDSTOP)
				{
					SendFlag = FALSE;
					SendStatus = SENDIDLE;			//发送器空闲
				}
       		 	break;
   			 }

//=======================================================================================================
		    default:
		 		break;
	   	}
    }
    VICVectAddr = 0x00;			// 向量中断结束
}

/*
*********************************************************************************************************
** 函数名称:UART0_Init()
** 函数功能:串口0初始化:baud 8 1 N。
*********************************************************************************************************
*/
void UART0_Init(void)
{
	uint16 bak;

	PINSEL0 = (PINSEL0 & (~0x0F)) | 0x05;	// 管脚连接UART0
		
	VICVectCntl0 = 0x20|0x06;				// 分配UART0中断优先级
	VICVectAddr0 = (uint32)UART0_Isr;		// 设置中断服务程序地址
	VICIntEnable = 1 << 0x06;				// 使能UART0中断
	
	MyAddr = 0;
	BaudNum = 4;
		
    RcvStatus = RCVSTX;
    SerDTValid = FALSE;
    SerTmOut = 0;
    
    SendFlag = FALSE;
    SendStatus = SENDIDLE;

	U0LCR = 0x83;							// DLAB=1
	bak  = (Fpclk/16)/BaudRateTable[BaudNum];
	U0DLM = bak/256;
	U0DLL = bak%256;
	U0LCR = 0x03;
	U0IER = 0x07;							// 允许发送和接收中断
}

/*
*********************************************************************************************************
** 函数名称 :UART0_SendByte()
** 函数功能 :向串口发送字节数据。
** 入口参数 :dat	要发送的数据
** 出口参数 :无
*********************************************************************************************************
*/
void UART0_SendByte (uint8 dat)
{
    while((U0LSR & 0x20) == 0);		// 等待发送保持寄存器空
    U0THR = dat;                   	// 发送一字节数据
}

/*
*********************************************************************************************************
** 函数名称:Ser_Send(0
** 函数功能:发送从机地址,计算校验和(从RAddr开始至应用层信息Info的最后一字节相异或后取反)
*********************************************************************************************************
*/
uint8 Ser_Send(uint8 SlvAddr)
{
    uint8 i;
     
    if(SendStatus == SENDIDLE)
	{
		SerBfr[RADDR] = SlvAddr;  //从机地址
     	SerBfr[SADDR] = MyAddr;
     	
	    LentoSend = SerBfr[LENGTH]+5;
	    SerBfr[LentoSend] = 0;		// 用于存放校验和
	    for(i=0;i<LentoSend;i++)
	    {
	        SerBfr[LentoSend] ^= SerBfr[i];	// 异或校验
	    }
	    SerBfr[LentoSend] = ~SerBfr[LentoSend];	// 取反
	    LentoSend++;
	    
		SerLen = 0;
		LenSend = 0;
		SendStatus = SENDDATA;		// 下次中断发送数据
		
		UART0_SendByte(STX);		// 发送数据,产生发送中断

	    return TRUE;
	}
	else
		return FALSE;		
}

⌨️ 快捷键说明

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