📄 serial.c
字号:
#include "configLPC.h"
#include "serial.h"
#include <stdio.h>
#include <string.h>
/*放到ConfigLPC.h
#define UART0_FIFO_LENGTH 8
#define UART1_FIFO_LENGTH 8
//以下定义的缓冲区长度为4字节的倍数,如定义160,缓冲会有160×4-24=456字节
#define UART0_RXBUF_LENGTH 160
#define UART0_TXBUF_LENGTH 160
#define UART1_RXBUF_LENGTH 160
#define UART1_TXBUF_LENGTH 160
*/
INT32U rcv_buf0[UART0_RXBUF_LENGTH]; // UART0数据接收缓冲区
INT32U snd_buf0[UART0_TXBUF_LENGTH]; // UART0数据发送缓冲区
INT32U rcv_buf1[UART1_RXBUF_LENGTH]; // UART1数据接收缓冲区
INT32U snd_buf1[UART1_TXBUF_LENGTH]; // UART1数据发送缓冲区
unsigned long int g_dwCOM1IntTmout = 10;
unsigned long int g_dwCOM1TotalTmout = 300;
unsigned long int g_dwCOM2IntTmout = 10;
unsigned long int g_dwCOM2TotalTmout = 300;
/****************************************************************************
* 名称:UART0_Exception()
* 功能:串口UART0接收中断。
* 入口参数:无
* 出口参数:无
U0LSR UART0线状态寄存器 0xE000C014,
U0RBR UART0 接收器缓存寄存器 0xE000C000,DLAB=0,只读)
U0IER UART0 中断使能寄存器(0xE000C004 =0)
U0IIR UART0 中断标识寄存器( 0xE000C008,
U0THR UART0 发送器保持寄存器(0xE000C000,
****************************************************************************/
void UART0_Exception(void)
{
uint8 IIR, temp, i;
OS_ENTER_CRITICAL();
while(((IIR = U0IIR) & 0x01) == 0)
{ // 有中断未处理完
switch (IIR & 0x0e)
{
case 0x02: // THRE中断
for(i = 0; i < UART0_FIFO_LENGTH; i++) // 向发送FIFO填充数据
{
if(QueueRead(&temp, snd_buf0, FALSE) == QUEUE_OK)
{
U0THR = temp;
}
else
{
U0IER &= ~0x02; // 队列空,则禁止发送中断
}
}
break;
case 0x04: // 接收数据可用
while(U0LSR&0X01) // 读取FIFO的数据,并清除中断标志
QueueWrite((void *)rcv_buf0, &U0RBR, FALSE);
break;
case 0x06: // 接收线状态
temp = U0LSR;
break;
case 0x0c: // 字符超时指示
while(U0LSR&0X01) // 读取FIFO的数据,并清除中断标志
QueueWrite((void *)rcv_buf0, &U0RBR, FALSE);
break;
default :
break;
}
}
VICVectAddr = 0; // 通知中断控制器中断结束
OS_EXIT_CRITICAL();
}
uint8 g_byReadSer; //用来读空串口缓冲区的数据
uint8 Uart_RecvFull(DATAQUEUE *pBuf, uint8* pData, uint8 Mod)
{
Mod = Mod;
g_byReadSer = *(pData);
return 1;
}
/****************************************************************************
* 名称:UART0_SendByte()
* 功能:向串口UART0发送字节数据。
* 入口参数:data 要发送的数据
* 出口参数:无
U0LSR UART0线状态寄存器 0xE000C014,
U0RBR UART0 接收器缓存寄存器 0xE000C000,DLAB=0,只读)
U0IER UART0 中断使能寄存器(0xE000C004 =0)
U0IIR UART0 中断标识寄存器( 0xE000C008,
U0THR UART0 发送器保持寄存器(0xE000C000,
****************************************************************************/
void UART0_SendByte(INT8U data)
{
uint8 temp;
OS_ENTER_CRITICAL();
QueueWrite((void *)snd_buf0, &data, FALSE); // 数据入队
if((U0LSR & 0X20) != 0)
{ // UART0发送保持寄存器空
QueueRead(&temp, snd_buf0, FALSE); // 发送最初入队的数据
U0THR = temp;
U0IER |= 0X02; // 允许发送中断
}
OS_EXIT_CRITICAL();
}
/****************************************************************************
* 名称:UART0_Ini()
* 功能:初始化串口0。设置其工作模式及波特率。
* 入口参数:baud 波特率
* set 模式设置(UARTMODE数据结构)
* 出口参数:返回值为1时表示初始化成功,为0表示参数出错
U0LCR UART0线控制寄存器( - 0xE000C00C)U0LCR决定发送和接收数据字符的格式
U0DLM UART0除数锁存 MSB 寄存器( - 0xE000C004,DLAB=1)
U0DLL UART0 除数锁存 LSB 寄存器( - 0xE000C000,DLAB=1)
U0FCR 控制 UART0 Rx和Tx FIFO的操作
****************************************************************************/
BOOLEAN UART0_Ini(INT32U baud, UARTMODE set)
{
extern void UART0_Handler(void);
INT32U bak;
PINSEL0 &= 0xFFFFFFF0;
PINSEL0 |= 0x00000005; // 设置I/O连接到UART0
/* 参数过滤 */
if((0==baud) || (baud>115200)) return FALSE;
if((set.datab<5) || (set.datab>8)) return FALSE;
if((0==set.stopb) || (set.stopb>2)) return FALSE;
if(set.parity>4 ) return FALSE;
/* 设置串口波特率 */
U0LCR = 0x80; // DLAB位置1
bak = (Fpclk>>4)/baud;
U0DLM = bak>>8;
U0DLL = bak&0xff;
/* 设置串口模式 */
bak = set.datab-5; // 设置字长度
if(2==set.stopb) bak |= 0x04; // 判断是否为2位停止位
if(0!=set.parity)
{
set.parity = set.parity-1;
bak |= 0x08;
}
bak |= set.parity<<4; // 设置奇偶校验
U0LCR = bak;
QueueCreate((void *)rcv_buf0, sizeof(rcv_buf0), sizeof(uint8), NULL, Uart_RecvFull);
QueueCreate((void *)snd_buf0, sizeof(snd_buf0), sizeof(uint8), NULL, NULL);
U0FCR = 0x41; // 使能FIFO,并设置触发点为4字节
U0IER = 0x05; // 允许接收中断及Rx线状态中断
// 设置中断允许
VICIntSelect = 0x00000000; // 设置所有通道为IRQ中断
VICVectCntl4 = 0x26; // UART0中断通道分配到IRQ slot 1
VICVectAddr4 = (uint32)UART0_Handler; // 设置UART0向量地址
VICIntEnable |= 0x00000040; // 使能UART0中断
return TRUE;
}
/****************************************************************************
* 名称:UART1_Exception()
* 功能:串口UART1接收中断。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void UART1_Exception(void)
{
uint8 IIR, temp, i;
OS_ENTER_CRITICAL();
while(((IIR = U1IIR) & 0x01) == 0)
{ // 有中断未处理完
switch (IIR & 0x0e)
{
case 0x02: // THRE中断
for(i = 0; i < UART1_FIFO_LENGTH; i++) // 向发送FIFO填充数据
{
if(QueueRead(&temp, snd_buf1, FALSE) == QUEUE_OK)
{
U1THR = temp;
}
else
{
U1IER &= ~0x02; // 队列空,则禁止发送中断
}
}
break;
case 0x04: // 接收数据可用
while(U1LSR&0X01) // 读取FIFO的数据,并清除中断标志
QueueWrite((void *)rcv_buf1, &U1RBR, FALSE);
break;
case 0x06: // 接收线状态
temp = U1LSR;
break;
case 0x0c: // 字符超时指示
while(U1LSR&0X01) // 读取FIFO的数据,并清除中断标志
QueueWrite((void *)rcv_buf1, &U1RBR, FALSE);
break;
default :
break;
}
}
VICVectAddr = 0; // 通知中断控制器中断结束
OS_EXIT_CRITICAL();
}
void UART1_SendByte(INT8U data)
{
uint8 temp;
OS_ENTER_CRITICAL();
QueueWrite((void *)snd_buf1, &data, FALSE); // 数据入队
if((U1LSR & 0X20) != 0)
{ // UART0发送保持寄存器空
QueueRead(&temp, snd_buf1, FALSE); // 发送最初入队的数据
U1THR = temp;
U1IER |= 0X02; // 允许发送中断
}
OS_EXIT_CRITICAL();
}
BOOLEAN UART1_Ini(INT32U baud, UARTMODE set)
{
extern void UART1_Handler(void);
INT32U bak;
//PINSEL0 &= 0x0000FFFF;
//PINSEL0 |= 0x55550000; // 设置I/O连接到UART1
PINSEL0 = (PINSEL0 & (~(0x0F<<16))) | (0x05<<16); // 设置I/O连接到UART1
/* 参数过滤 */
if((0==baud) || (baud>115200)) return FALSE;
if((set.datab<5) || (set.datab>8)) return FALSE;
if((0==set.stopb) || (set.stopb>2)) return FALSE;
if(set.parity>4 ) return FALSE;
/* 设置串口波特率 */
U1LCR = 0X80; // DLAB位置1
bak = (Fpclk>>4)/baud;
U1DLM = bak>>8;
U1DLL = bak&0XFF;
/* 设置串口模式 */
bak = set.datab-5; // 设置字长度
if(2==set.stopb) bak |= 0x04; // 判断是否为2位停止位
if(0!=set.parity)
{
set.parity = set.parity-1;
bak |= 0x08;
}
bak |= set.parity<<4; // 设置奇偶校验
U1LCR = bak;
QueueCreate((void *)rcv_buf1, sizeof(rcv_buf1), sizeof(uint8), NULL, Uart_RecvFull);
QueueCreate((void *)snd_buf1, sizeof(snd_buf1), sizeof(uint8), NULL, NULL);
U1FCR = 0x41; // 使能FIFO,并设置触发点为4字节
U1IER = 0x05; // 允许RBR中断,即接收中断
/* 设置中断允许 */
VICIntSelect = 0x00000000; // 设置所有通道为IRQ中断
VICVectCntl5 = 0x27; // UART1中断通道分配到IRQ slot 2
VICVectAddr5 = (uint32)UART1_Handler; // 设置UART1向量地址
VICIntEnable |= 0x00000080; // 使能UART1中断
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOLEAN SerPort_Open(INT8U byComPort, INT32U lBaud, UARTMODE modSet)
{
switch(byComPort)
{
case COM1:
UART0_Ini(lBaud, modSet);
break;
case COM2:
UART1_Ini(lBaud, modSet);
//rs485_init();
//rs485_rx();
break;
}
return TRUE;
}
BOOLEAN SerPort_Close(INT8U byComPort)
{
switch(byComPort)
{
case COM1:
PINSEL0 &= 0xFFFFFFF0; //关TXD0,RXD0
VICIntEnable &= 0XFFFFFFBF; // 禁止UART0中断
U0FCR |= 0X06; // 清FIFO
QueueFlush((void*)rcv_buf0);
QueueFlush((void*)snd_buf0);
break;
case COM2:
PINSEL0 &= 0xFFF0FFFF; //关TXD1,RXD1
VICIntEnable &= 0XFFFFFF7F; // 禁止UART1中断
U1FCR |= 0X06; // 清FIFO
QueueFlush((void*)rcv_buf1);
QueueFlush((void*)snd_buf1);
break;
}
return TRUE;
}
BOOLEAN SerPort_IsOpen(INT8U byComPort)
{
switch(byComPort)
{
case COM1:
return (BOOLEAN)(PINSEL0 & 0x00000001);
case COM2:
//10987654321098765432109876543210
//00000000000000010000000000000000 0X00010000
return (BOOLEAN)(PINSEL0 & 0X00010000);
}
return FALSE;
}
BOOLEAN SerPort_Avail(INT8U byComPort)
{
switch(byComPort)
{
case COM1:
return (QueueNData((void*)rcv_buf0) > 0);
case COM2:
return (QueueNData((void*)rcv_buf1) > 0);
}
return FALSE;
}
INT16S SerPort_BuffedLen(INT8U byComPort, UARTBUF enWhichBuf)
{
switch(byComPort)
{
case COM1:
if(enWhichBuf == enTxBuf)
{
return (QueueNData((void*)snd_buf0));
}
else
{
return (QueueNData((void*)rcv_buf0));
}
break;
case COM2:
if(enWhichBuf == enTxBuf)
{
return (QueueNData((void*)snd_buf1));
}
else
{
return (QueueNData((void*)rcv_buf1));
}
break;
}
return 0;
}
BOOLEAN SerPort_IsTxIdle(INT8U byComPort)
{
switch(byComPort)
{
case COM1:
if((U1LSR & 0X20) != 0)
return TRUE;
else
return FALSE;
case COM2:
if((U1LSR & 0X20) != 0)
return TRUE;
else
return FALSE;
}
return FALSE;
}
void SerPort_Clear(INT8U byComPort, UARTBUF enWhichBuf)
{
switch(byComPort)
{
case COM1:
if(enWhichBuf == enTxBuf)
{
U0FCR |= 0X04; // 清TX FIFO
QueueFlush((void*)snd_buf0);
}
else
{
U0FCR |= 0X02; // 清RX FIFO
QueueFlush((void*)rcv_buf0);
}
break;
case COM2:
if(enWhichBuf == enTxBuf)
{
U1FCR |= 0X04; // 清TX FIFO
QueueFlush((void*)snd_buf1);
}
else
{
U1FCR |= 0X02; // 清RX FIFO
QueueFlush((void*)rcv_buf1);
}
break;
}
}
INT16S SerPort_SendBuf(INT8U byComPort, INT8U *pcBuf, INT16U nSize)
{
INT16U wLoop;
switch(byComPort)
{
case COM1:
rs485_tx(COM1);
for(wLoop=0; wLoop<nSize; wLoop++)
{
UART0_SendByte(*(pcBuf+wLoop));
}
rs485_rx(COM1);
break;
case COM2:
rs485_tx(COM2);
for(wLoop=0; wLoop<nSize; wLoop++)
{
UART1_SendByte(*(pcBuf+wLoop));
}
rs485_rx(COM2);
break;
}
return ((INT16S)nSize);
}
INT16S SerPort_SendByte(INT8U byComPort, INT8U c)
{
switch(byComPort)
{
case COM1:
UART0_SendByte(c);
break;
case COM2:
UART1_SendByte(c);
break;
}
return 1;
}
INT16S SerPort_RecvBuf(INT8U byComPort, INT8U *pcBuf, INT16U nSize, INT16U nTickCnt)
{
INT16U wRecLen=0;
ULONG dwStartTime = OSTime;
switch(byComPort)
{
case COM1:
//Led_Ctl(LED_232, LED_ON);
while((dwStartTime + nTickCnt) > OSTime)
{
for(; wRecLen<nSize; wRecLen++)
{
if(QueueRead(pcBuf+wRecLen, (void*)rcv_buf0, TRUE) != QUEUE_OK)
break;
}
if(wRecLen >= nSize)
{
break;
}
OSTimeDly(1);//延时
}
return wRecLen;
case COM2:
Led_Ctl(LED_485, LED_ON);
while((dwStartTime + nTickCnt) > OSTime)
{
for(; wRecLen<nSize; wRecLen++)
{
if(QueueRead(pcBuf+wRecLen, (void*)rcv_buf1, TRUE) != QUEUE_OK)
break;
}
if(wRecLen >= nSize)
{
break;
}
OSTimeDly(1);//延时
}
return wRecLen;
}
return wRecLen;
}
INT16S SerPort_RecvByte(INT8U byComPort, INT8U *pc)
{
switch(byComPort)
{
case COM1:
if(QueueRead(pc, (void*)rcv_buf0, TRUE) == QUEUE_OK)
return 1;
else
return 0;
case COM2:
if(QueueRead(pc, (void*)rcv_buf1, TRUE) == QUEUE_OK)
return 1;
else
return 0;
}
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -