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

📄 uart.c

📁 关于ucos下的 UART串口驱动实现 硬件平台是LPC2114
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************Copyright (c)**************************************************
**--------------文件信息--------------------------------------------------------------------------------
**描        述: μCOS-II下LPC2114的UART0底层驱动 
**--------------当前版本修订------------------------------------------------------------------------------
** 修改人: 	  hongding
** 日 期: 
** 描 述:
** 08-11-16     UART1,用于 接收 GPRS AT指令返回 和 服务器桢,如果 g_GPRS_recv 为1,则接收的字符一定是AT指令返回 
** 08-12-4	    GPRS AT返回指令的接收 初步采取 查询方式接收 
** 08-12-31   	Uart1_recv 改为长度 50 服务器帧的 最大程度为50
** 09-1-08      增加 U0_Post_flag 和 g_meter_wait ; 485网络原因 连续操作两个不同的表具之间要有延时因此 增加两标识用于
**				     对 URAT0的释放进行控制 ;		在 时钟钩子函数中对其进行操作
** 09-3-1       增加 Uart0ScannerInit()函数;  g_Uart0_Func标志;           				     
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#define IN_UART0

#include "config.h"
      /*中继器运行 所需要的一些变量定义*/
static SendQueue sendQueue;
static RecvQueue recvQueue;
static RecvQueue recvQueue_U1;

static SendQueue sendQueue_U1;
	   uint8     Uart1_recv[50];

       OS_EVENT * Uart0Sem;			   /* UART0占用 此信号量在 节拍钩子函数 中进行释放 */
       OS_EVENT * Uart0recvSem;

static OS_EVENT * Uart1Sem;       
       OS_EVENT * Uart1_Mbox;          /* UATR1邮箱*/
       
volatile  uint8   g_Mbox_Complete ;    /* 标识邮箱的信息桢是否完成处理  在frameanalyse任务中被置位*/ 
   
static  uint16  UART0_OWN_Flag ;	   /* 可同时使用 UART0 的任务最多16 个*/
			
volatile  uint16  g_meter_wait  ;
volatile  uint8   U0_Post_flag  ;      /* 用于控制 UART0 的释放*/	
			/*数据接收完成?? 前面为什么不能加 volatile*/
			//uint8   rbrb,rbrc,rbrd,rbre;//测试
		/*扫描仪运行所需变量定义*/
volatile  uint8   g_Uart0_Func  ;      /* 用于标志 Uart0 的用途(连接表具 或 连接扫描仪),从而决定中断函数的执行  */
volatile  uint8   g_Eint0_Int   ;      /* 用于识别有扫描仪输入的请求 */
/*********************************************************************************************************
** 函数名称: UART0Init
** 功能描述: 初始化UART0 
** 输 入: bps:波特率
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
        uint8 UART0Init(uint32 bps)
{
    uint16 Fdiv;
/*UART0 设置*/    
    U0LCR = 0x80;                          /* 允许访问分频因子寄存器 */
    Fdiv = (Fpclk / 16) / bps;             /* 设置波特率 */
    U0DLM = Fdiv / 256;							
	U0DLL = Fdiv % 256;						
    U0LCR = 0x1b;                          /* 禁止访问分频因子寄存器 且设置为8,1,n */                                        
    U0FCR = 0x87;                          /* 初始化FIFO */
    g_Uart0_Func = 0 ;					   /* 标示用于485的操作 */
    
    
    U0IER = U0IER&(~0x07); 				 /*禁止 接收 \发送中断*/
    
/*UART0 数据资源初始化*/
    Uart0Sem = OSSemCreate(1);
    Uart0recvSem = OSSemCreate(0);
 
    if ((Uart0Sem != NULL)&&(Uart0recvSem!=NULL))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
} 
/*********************************************************************************************************
** 函数名称: UART0ScannerInit
** 功能描述: 初始化UART0  扫描仪用途
** 输 入: bps:波特率
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
	uint8 UART0ScannerInit(uint32 bps)
{
    uint16 Fdiv;
/*UART0 设置  / 可与共用 Uart0recvSem 信号量 */    
    U0LCR = 0x80;                          /* 允许访问分频因子寄存器 */
    Fdiv = (Fpclk / 16) / bps;             /* 设置波特率 */
    U0DLM = Fdiv / 256;							
	U0DLL = Fdiv % 256;						
    U0LCR = 0x03;                          /* 禁止访问分频因子寄存器 且设置为8,1,n */                                        
    U0FCR = 0x87;                          /* 初始化FIFO */
    g_Uart0_Func = 1 ;                     /* 标示用于扫描仪的操作*/
        
    U0IER = U0IER&(~0x07); 				 /*禁止 接收 \ 发送中断*/
    
    return 0 ;
} 

/*********************************************************************************************************
** 函数名称: UART0_PostFlag
** 功能描述: 功能 对UART0 占用标识UART0_PEND_Flag  释放
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_PostFlag(uint8 Taskprio)
{
	OS_ENTER_CRITICAL() ;
	UART0_OWN_Flag &= ~ Task_Mask[Taskprio] ;
	OS_EXIT_CRITICAL() ;
}

/*********************************************************************************************************
** 函数名称: UART0_PendFlag
** 功能描述: 功能 对UART0 占用标识UART0_PEND_Flag  置位
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_PendFlag(uint8 Taskprio)
{
	OS_ENTER_CRITICAL() ;
	UART0_OWN_Flag |= Task_Mask[Taskprio] ;
	OS_EXIT_CRITICAL() ;
}

/*********************************************************************************************************
** 函数名称: IS_PendFlag
** 功能描述: 功能 对UART0 占用标识UART0_PEND_Flag  判断
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8 IS_PendFlag(uint8 Taskprio)
{
	if(UART0_OWN_Flag & Task_Mask[Taskprio]){
		return 1 ;
	}else{
		return 0 ;
	}
}
/*********************************************************************************************************
** 函数名称: UART0_SendQ
** 功能描述: 发送一组数据(若用于向扫描仪发送数据 则只需 设置前两个参数  即 DQ_head  和 DataN )
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/

	void UART0_SendQ(const void * DQ_head, uint16 DataN, void * RBuff ,uint8 Taskprio)
	{
		uint8 err;

		if(0 == g_Uart0_Func){	// 当用于485用途时 才需竞争Uart0 
			OSSemPend(Uart0Sem ,0 ,&err);
			
			UART0_PendFlag(Taskprio); 		/*此处可以看到当前 UART0 正在被哪个任务使用 
																可用于任务等待超时后的判断*/
			IO0SET = R485;    				/*准备485发送,并挂上发送队列和接收队列*/
			OSTimeDly(6);
		}		
		OS_ENTER_CRITICAL();      		                                     
		
		sendQueue.DQ_head = (QUEUE_DATA_TYPE *)DQ_head;   	 //设置发送队列
		sendQueue.pData =  (QUEUE_DATA_TYPE *)DQ_head;
		sendQueue.DataNum = DataN;
		
		if(0 == g_Uart0_Func){
			recvQueue.RBuff = (QUEUE_DATA_TYPE *)RBuff;       	 //当用于485用途时 设置接收队列
			recvQueue.pData = recvQueue.RBuff;
			recvQueue.DataNum = 0;
			recvQueue.start = 0;		
		}
							
		OS_EXIT_CRITICAL();
		
		U0THR = 0xFE;
		U0THR = 0xFE;                                   	/*启动THR中断 需前导字节初始化 FIFO*/
		U0IER = U0IER | 0x02;                            	/*使能发送中断*/	
	}
/*********************************************************************************************************
** 函数名称: UART0_RecvReset
** 功能描述: 等待超时时 重置UART0
** 输 入: 
** 输 出: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_RecvReset(uint8 TaskPrio)
{

OS_ENTER_CRITICAL();
	OSSemPost(Uart0Sem);
	UART0_PostFlag(TaskPrio);
	recvQueue.RBuff = NULL;       //重置接收缓存控制结构
	recvQueue.pData = NULL;
	recvQueue.DataNum = 0;
	recvQueue.start =   0;
	U0IER &=(~0x01);			 //关接收中断
	IO0SET = R485;
OS_EXIT_CRITICAL();

}
/*********************************************************************************************************
** 函数名称: UART0_ScanRecvSet()
** 功能描述: 发送一组数据
** 输 入: 无
** 输 出: 接收到的数据
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_ScanRecvSet(void * RBuff)
{
OS_ENTER_CRITICAL();
	recvQueue.RBuff = (QUEUE_DATA_TYPE *)RBuff;       	 //当用于485用途时 设置接收队列
	recvQueue.pData = recvQueue.RBuff;
	recvQueue.DataNum = 0;
	recvQueue.start = 0;
	U0IER |= 0x01;						 //启动接收中断 		
OS_EXIT_CRITICAL();
}

/*********************************************************************************************************
** 函数名称: UART0_Exception
** 功能描述: UART0中断服务程序
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
        void UART0_Exception(void)
{
    uint8 IIR, temp , i;  
    uint16 dataNum = 0; 
    uint16 dataLen ;    // 用于计算扫描仪配置桢的数据长度
    
        OS_ENTER_CRITICAL();
        
        IIR = U0IIR;
                                             /* 有中断未处理完 */
        switch (IIR & 0x0e)
        {
            case 0x02:             		
            	dataNum=sendQueue.DataNum;            	
            	                                
             	if(sendQueue.DQ_head == NULL){
             		U0IER = U0IER&(~0x02);            		 	 /* THRE中断    */
             	}else{
             		if(!dataNum){								/*数据发送完 准备接收数据*/
             				Delay(2);
             				sendQueue.DQ_head = NULL;
             				sendQueue.pData = NULL;
             				U0IER &=(~0x02);
             				IO0CLR = R485;	                 		 /* 清零485准备接收 表具返回桢*/
             				U0IER |= 0x01;                  		 /* 发送OVER 启动RBR中断 准备接收数据*/                        
             		}
             		for(i=16;i!=0;i--)                 			 	/*如果发送允许(U0THR为空)*/
             			{
             				U0THR = *sendQueue.pData++;
							if(0==--dataNum)  break;             				
             			}
             		if(!dataNum){
             			sendQueue.DataNum = dataNum;
             				break; 							 /*此时数据还未彻底发送出去(只是把它放在了缓存里),
             				       							   等到下一次发送中断(发送缓存为空),才证明都以发送成功 */ 	
             			}else{			
             				sendQueue.DataNum = dataNum;
             			}
             	    }		
                break;
            case 0x04:                                 		 /* 接收数据可用 */
                  
                if(recvQueue.RBuff != NULL){
                   dataNum = recvQueue.DataNum;
             	   for(i=8;i!=0;i--){
						temp = U0RBR;
						if(temp == 0x68){
							recvQueue.start = 1;
							}
						if(recvQueue.start==1){
							*recvQueue.pData++ = temp;
						 	dataNum++;
						}
						if((0 == g_Uart0_Func)&&(0x16==temp)&&(*(recvQueue.RBuff+2)==(uint8)(dataNum-5))){
							OSSemPost(Uart0recvSem);			/*通知任务拿数据*/
							                    				/*释放UART0 一次帧发送和帧返回作为一次串口占用 如果 表具无响应的话
																 那么 	Uart0recvSem和 Uart0Sem 就得不到释放 所以等待超时后 先释放信号量 */
							UART0_OWN_Flag = 0 ;
							U0_Post_flag = 1   ;
							g_meter_wait = MANI_METER_WAIT ;	/*连续操作485网络 需间隔延时 在时钟钩子函数中对其进行释放*/
							
							recvQueue.RBuff = NULL;      		 //重置接收缓存控制结构
							recvQueue.pData = NULL;
							recvQueue.DataNum = 0;
							recvQueue.start =   0;
							U0IER &=(~0x01);			
								//IO0SET = R485;
							break;
							}
						if((1 == g_Uart0_Func)&&(0x16==temp)){  	 //用于扫描仪接收时的判断
							dataLen = *(recvQueue.RBuff+5)*100 + *(recvQueue.RBuff+6) ;
							if(dataLen == (dataNum-9)){
								OSSemPost(Uart0recvSem);			 /*通知任务拿数据*/
								 /*UART0_OWN_Flag = 0 ;
								U0_Post_flag = 1   ;
								g_meter_wait = MANI_METER_WAIT ;	用于扫描仪时不需要*/
								
								recvQueue.RBuff = NULL;      		 //重置接收缓存控制结构
								recvQueue.pData = NULL;
								recvQueue.DataNum = 0;

⌨️ 快捷键说明

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