📄 uart0.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 + -