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

📄 uart0.c

📁 基于ARM7处理器的中断与串口在ucos下切换的演示程序
💻 C
字号:
/* ----------------------------------------------------
   模块名: Uart0.c:
   描  述: 串口0接口函数  
--------------------------------------------------------*/
#include "config.h"


#define USE_SEMAPHORE_RX   1       /* 打开后不稳定问题解决 */

static OS_EVENT *Uart0TxSem;

#if USE_SEMAPHORE_RX
static OS_EVENT *Uart0RxSem;
#else
volatile uint8   inbufsign;          /* 接收缓冲区非空标志-有=1 */
#endif

uint32 errorcount0[10] = {0,0,0,0,0,0,0,0,0,0};

volatile char  Uart0RxBuf[LenRxBuf0];
volatile int  rxHead0;         /* 收发缓冲区读写指针 */
volatile int  rxTail0;
volatile int   nUart0RxLen;

volatile char  Uart0TxBuf[LenTxBuf0]; /* 收发缓冲区实体 */
volatile int  txHead0;         /* 收发缓冲区读写指针 */
volatile int  txTail0;
volatile int  nUart0TxLen;	

//OS_STK uart0Stack[64];
extern OS_STK  taskUartStack[];

void uart0RecvTask(void* para );


void UART0_data_transfer(void*);

/*------------------------------------------------------------
** 函数名称: UART0_Ini
** 功能描述: 初始化串口0。设置其工作模式及波特率。
** 输   入: set  模式设置(UARTMODE数据结构)
** 输   出: 无
** 返    回: 0-成功设置        
------------------------------------------------------------*/
uint8  UART0_Ini(UARTMODE *set)
{  
	uint32  bak;

    VICIntEnClr = 1 << 6; // 禁止uart0中断
    
    /* 参数过滤 */
    if((0 == set->baudrate)||(set->baudrate > 115200) ) return(0);
    if((set->datab < 5)||(set->datab > 8) ) return(0);
    if((0 == set->stopb)||(set->stopb > 2) ) return(0);
    if( set->parity > 2 ) return(0);

    /* 设置I/O连接到UART0 */
    PINSEL0 = (PINSEL0 & 0xfffffff0) | 0x05;

    /* 设置串口波特率 */
    U0LCR = 0x80;                    // DLAB位置1
    bak   = (FPCLK>>4)/set->baudrate;
    U0DLM = bak>>8;
    U0DLL = bak&0xff;
    
    /* 设置串口模式 */
    bak = set->datab - 5;            // 设置字长度
    if(2 == set->stopb) bak |= 0x04; // 判断是否为2位停止位  
    if(0 != set->parity) 
    {
		if(set->parity == 1)
		{
            bak |= 0x08;             // 设置为奇校验
		}
		else
		{
			bak |= 0x18;             // 设置为偶校验
		}
    }
	
    U0LCR = bak;

    //U0FCR = 0x01;                    // 每接收到一个字符就产生一次中断
    //U0FCR = 0x41;					 // 4 个中断
	//U0FCR = 0x81;						// 收到8字节产生一次中断
	U0FCR = 0xc1;						// 收到14字节产生一次中断
    
    U0IER = 0x03;                    // 允许RBR和THRE中断,即收发中断
    
    /* 初始化串口所用到的全局变量 */   
    //inTxBuf=TxBuf;outTxBuf=TxBuf;
    //inRxBuf=RxBuf;outRxBuf=RxBuf;
	nUart0RxLen = 0;
    rxHead0 = 0;
    rxTail0 = 0;

	nUart0TxLen = 0;
    txHead0 = 0;
    txTail0 = 0;
    memset((char *)Uart0TxBuf, 0, sizeof(Uart0TxBuf) );
	
    Uart0TxSem = OSSemCreate(1);     // 信号量用于发送缓冲区满后等待发送

#if USE_SEMAPHORE_RX
    Uart0RxSem = OSSemCreate(0);     // 信号量用于等待串口接收字符中断
#else
    inbufsign = 0;
#endif
    
    //VICIntEnable = 1 << 6;           // 允许uart0中断
    OSTaskCreate( uart0RecvTask, NULL, &taskUartStack[TASK_UART_STK_SIZE-2], TASK_UART_PRIO);
    
    return 0;
}

//
// 向硬件发送一个字节
//
void uart0PhySend(void)
{
	//char c;
	//if(FALSE==uart0_rts_judge())
	//	return;
	
    if( nUart0TxLen )
	{      	
		if( txHead0 == LenTxBuf0)
		{
			txHead0 = 0;
		}
		
		OS_ENTER_CRITICAL();
		if( LSR_TEMT & U0LSR )
		{
			U0THR = Uart0TxBuf[txHead0++] ;
			nUart0TxLen--;
		}
	    OS_EXIT_CRITICAL();	
	}
    
    // 设置UART0的CTS为有效
    
}

//
// 从物理层接收, 调用时记得关中断
//
void uart0PhyRecv(void)
{
	//int i;
	char c;
	
	//
	// 因为LPC2106的DMA不可能超过16个
	//
	//for( i = 0; i < 16; i++ )
	while(1)
	{
		if( U0LSR & LSR_RDR )	// 有数据
		{
			c = U0RBR;

			OS_ENTER_CRITICAL();
			if( nUart0RxLen < LenRxBuf0 )
			{
				if( rxTail0 >= LenRxBuf0)
				{
					rxTail0 = 0;
				}
				Uart0RxBuf[rxTail0++] = c;
				nUart0RxLen++;
			}
		    OS_EXIT_CRITICAL();	
		}
		else
			break;
	}

	
	
}
/*------------------------------------------------------------
** 函数名称: Uart0_Exception
** 功能描述: 串口UART0中断函数。
** 输   入: 无
** 输   出: 无
** 返    回: 无  
------------------------------------------------------------*/
void   Uart0_Exception(void)
{
    uint8 Uart0Int;// temp;
    //char tempdata;
    //char state;
    //int  i;
      
    if(((Uart0Int = U0IIR)&0x01) == 0)
    {
        switch(Uart0Int & 0x0e)
        {
            case 0x02:            /* 发送中断处理 */
            {
                //OSSemPost(Uart0TxSem);
                uart0PhySend();
                errorcount0[0]++;
            }
            break;

            case 0x04:            /* 接收中断处理 */
            {
				uart0PhyRecv();
				if(nUart0RxLen!=1)
					//OSUntimeout(UART0_data_transfer, NULL);
				//OSTimeout(UART0_data_transfer, NULL, 1);				
                errorcount0[1]++;
            }     
            break;
            
            case 0x06:            /* 串口接收线路状态错误中断 */
            {
                Uart0Int = U0LSR; /* 一定要进行该操作,用以清除中断标志,否则串口会死掉! */       
                errorcount0[2]++;
            }
            break;
            
            case 0x0c:            /* 串口字符超时指示(CTI)中断 */
            {
            	uart0PhyRecv();

				//OSUntimeout(UART0_data_transfer, NULL);
            	UART0_data_transfer((void*)0 );
                errorcount0[3]++;
            }
            break;
            
            default:
                Uart0Int = U0LSR;
                errorcount0[4]++;
            break;
        }
    }
    
    VICVectAddr = 0x00;                          // 中断处理结束
}               

/*------------------------------------------------------------
** 函数名称: PutChar
** 功能描述: 从UART0往外发送一字节
** 输   入: 待发送数据
** 输   出: 无
** 返    回: 待发送数据 
------------------------------------------------------------*/
char PutChar(char c)
{
	UART0_PutData( &c, 1 );
    return c;
}


/*------------------------------------------------------------
** 函数名称: UART0_PutData
** 功能描述: 从UART0往外发送一指定长度字符串,
** 输   入: str 待发送数据
**           len 发送数据长度
** 输   出: 无
** 返    回: 无 
------------------------------------------------------------*/
int UART0_PutData(char *str, int len)
{
	int i;
	int nTempLen;
	//int nNeedToSend = FALSE;

	if( nUart0TxLen >= LenTxBuf0 )
		return 0;

//	led_data_set(); /* 点灯 */
	
    OS_ENTER_CRITICAL();

	//if( 0 == nUart0TxLen ) 
	//	nNeedToSend = TRUE;
	
	nTempLen = min(len, LenTxBuf0 - nUart0TxLen );
	for( i = 0; i < nTempLen; i++ )
	{
		if( txTail0 == LenTxBuf0 )
			txTail0 = 0;
		Uart0TxBuf[txTail0++] = str[i];
		nUart0TxLen ++;
	}

	//if( nNeedToSend == TRUE )
	//	uart0PhySend();
	
    OS_EXIT_CRITICAL();
    return nTempLen;
}


/*------------------------------------------------------------
** 函数名称: output
** 功能描述: 从UART0串口发送一字符串
** 输   入: buf 待发送数据
** 输   出: 无
** 返    回: 无
------------------------------------------------------------*/
void output(char* buf)
{
	OutString(buf);
}

/*------------------------------------------------------------
** 函数名称: output
** 功能描述: 从UART0串口发送一字符串
** 输   入: buf 待发送数据
** 输   出: 无
** 返    回: 无
------------------------------------------------------------*/
void OutString(char* buf)
{
	UART0_PutData( buf, strlen(buf) );
}

	

/* 修改为用来处理 AT指令的函数 这个处理速度不是很快,可以这样处理 */
void UART0_data_transfer(void* p)
{	
	OSSemPost(Uart0RxSem);	
}


// 第二个输入参数暂时没用
int uart0_read_data(char* buffer, int limit, int timeout)
{	
	int 	templen;
	//UBYTE   err;
	int     i;

	/*if( !nUart0RxLen )
	{
		OSSemPend( Uart0RxSem, timeout, &err);
		if( err != OS_NO_ERR )
			return 0;
	}
	*/
	OS_ENTER_CRITICAL();
	templen = min(limit, nUart0RxLen);
	for( i = 0; i < templen; i++ )
	{
		if( rxHead0 == LenRxBuf0 )
			rxHead0 = 0;
		buffer[i] = Uart0RxBuf[rxHead0++];
		nUart0RxLen--;
	}
	OS_EXIT_CRITICAL();
	
     
	if(templen)
//		led_data_set(); /* 有数据才点灯 */
;
	return templen;	
	
}

//
// 读取一个字节
// 
char GetChar( int timeout )
{
	char c;
	int  times = 0;
	int  i;

	#if 0
		if( uart0_read_data( &c, 1, timeout ) )
			return c;
		else
			return -1;

	#else
		if(timeout==0)
		{
			while(1)
			{
				if( uart0_read_data( &c, 1, timeout ) )
					return c;
				else
					delay(10);
			}
		}
		else
		{
			times = timeout / 10;
			for( i = 0; i < times; i++ )
			{
				if( uart0_read_data( &c, 1, timeout ) )
					return c;
				else
					delay(10);
			}
		}

		return (char) -1;
	#endif

	
	
}

int rsRead(char * buf, int len, int timeout)
{
	return uart0_read_data( buf, len, timeout);
}

void rsWrite(char * buf, int len)
{
	UART0_PutData( buf, len );
}


//
// UART receive task 
//
void uart0RecvTask(void* para )
{
	while(1)
	{	
		uart0PhyRecv();
		uart0PhySend();
		uart1PhyRecv();
		uart1PhySend();
	}
}


⌨️ 快捷键说明

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