📄 uart.c
字号:
/*******************************************************************
* 文 件 名: uart.c
*版本/时间: v1.10 2006/06/29
* 描 述: UART0/1的通讯例程,假设Fosc=12M,Fcclk=Fpclk=60M
* 作 者: lenglx
*-------------------------------------------------------------------
* 修改记录:
* 修改时间:
* 描 述:
* 修 改 人:
*******************************************************************/
#include <LPC214X.H>
#include "type.h"
#include "usb.h"
#include "usbcfg.h"
#include "usbhw.h"
#include "uart.h"
// 4个缓冲区,uart0接收/发送,uart1接收/发送
// 接收缓冲区的数据要等待USB读取,如果USB读取不及时,有可能丢失数据,所以缓冲区可设置稍微大点.
#define RCV_BUF_LEN 1024
#define SEND_BUF_LEN 512
BYTE SendBuf0[SEND_BUF_LEN];
BYTE RcvBuf0[RCV_BUF_LEN];
BYTE SendBuf1[SEND_BUF_LEN];
BYTE RcvBuf1[RCV_BUF_LEN];
DWORD r_first0, r_first1, r_next0, r_next1;
DWORD s_first0, s_first1, s_next0, s_next1;
/*
发送/接收 缓冲区是1个循环缓冲,如下图.
图 1)
| |first |next |
| not | | |
+-used--+--------valid data-------+---------not used--------+
| v v |
.-----------------------------------------------------------.
| recive or send buffer |
'-----------------------------------------------------------'
图 2)
| |next |first |
| valid | | |
+-data--+--------not used---------+-------valid data--------+
| v v |
.-----------------------------------------------------------.
| recive or send buffer |
'-----------------------------------------------------------'
位于first和next之间的区域是已经接收的数据或者将要发送的数据.
其它区域是空的区域.
此缓冲区是1个循环缓冲区,当指针达到缓冲区的末尾,将循环到缓冲区头重新开始.
当first==next,表示是整个缓冲区无任何数据.
当next=first-1,表示缓冲区已满.
*/
/*******************************************************************
* 功能描述: 重置缓冲区指针
* 参 数:
* 返 回:
* 备 注:
*******************************************************************/
void ResetBufferPointer(DWORD dwPortNum)
{
if(dwPortNum==0)
{
s_first0 = s_next0 = 0;
r_first0 = r_next0 = 0;
}
else
{
s_first1 = s_next1 = 0;
r_first1 = r_next1 = 0;
}
}
/*******************************************************************
* 功能描述:
* 参 数:
* 返 回:
* 备 注:
*******************************************************************/
void UartDataToHost(DWORD dwPort)
{
BYTE tmpbuf[USB_MAX_PACKET];
DWORD dwEp;
DWORD next;
DWORD first;
BYTE * pBuf;
DWORD i;
DWORD dwCnt;
// 因为此函数调用比较频繁,在没数据的时候尽量快点返回
if( (dwPort==0 && r_next0==r_first0) || (dwPort==1 && r_next1==r_first1))
return;
dwEp = dwPort==0 ? 2 : 5;
next = dwPort==0 ? r_next0 : r_next1;
first = dwPort==0 ? r_first0 : r_first1;
pBuf = dwPort==0 ? RcvBuf0 : RcvBuf1;
dwCnt = USB_MAX_PACKET;
i=0;
// 将接收缓冲区的数据移动到tmpbuf
while(dwCnt--)
{
if(next == first)
break;
tmpbuf[i] = pBuf[first];
if(++first >= RCV_BUF_LEN)
first = 0;
i++;
}
USB_WriteEP(dwEp | 0x80, tmpbuf, i);
if(dwPort == 0)
r_first0 = first;
else
r_first1 = first;
}
/*******************************************************************
* 功能描述: 将从USB来的数据发送到UART端口
* 参 数:
* 返 回:
* 备 注:
*******************************************************************/
void HostDataToUart(DWORD dwPort)
{
BYTE tmpbuf[USB_MAX_PACKET];
DWORD dwEp = dwPort==0 ? 2 : 5;
DWORD next = dwPort==0 ? s_next0 : s_next1;
DWORD first = dwPort==0 ? s_first0 : s_first1;
BYTE * pBuf = dwPort==0 ? SendBuf0 : SendBuf1;
DWORD dwCnt = USB_ReadEP(dwEp, tmpbuf);
DWORD i=0;
// 将数据移到发送缓冲区
while(dwCnt--)
{
if(next == first-1)
break;
pBuf[next] = tmpbuf[i];
if(++next >= SEND_BUF_LEN)
next = 0;
i++;
}
if(dwPort == 0)
{
s_next0 = next;
if(U0LSR & 0x40 && s_first0 != s_next0) // 发送器为空,需要重新启动发送
{
U0THR = pBuf[s_first0];
if(++s_first0 >= SEND_BUF_LEN)
s_first0 = 0;
}
}
else
{
s_next1 = next;
if(U1LSR & 0x40 && s_first1 != s_next1)
{
U1THR = pBuf[s_first1];
if(++s_first1 >= SEND_BUF_LEN)
s_first1 = 0;
}
}
}
/*******************************************************************
* 功能描述: irq中断函数,处理UART0的字节接收/发送
* 参 数:
* 返 回:
* 备 注:
*******************************************************************/
void Uart0_irq(void) __irq
{
uchar iir,ch;
while(1) // 循环处理,直到UART0中无任何挂起的中断
{
if((iir = U0IIR) & 1)
break;
switch(iir & 0x0e)
{
case 0x04: // RDA.
case 0x0c: // CTI.
while(U0LSR & 1) //将fifo中的所有数据读完
{
ch = U0RBR;
if(r_next0 != r_first0-1)
{
RcvBuf0[r_next0] = ch;
if (++r_next0 >= RCV_BUF_LEN)
r_next0 = 0;
}
}
break;
case 0x02: // THR Empty.
{
DWORD nCnt = 16; //fifo counter
while( s_next0 != s_first0 && nCnt--)
{
U0THR = SendBuf0[s_first0];
if(++s_first0 >= SEND_BUF_LEN)
s_first0 = 0;
}
}
break;
default:
;
}
}
VICVectAddr=0;
}
void Uart1_irq(void) __irq
{
uchar iir,ch;
while(1) // 循环处理,直到UART1中无任何挂起的中断
{
if((iir = U1IIR) & 1)
break;
switch(iir & 0x0e)
{
case 0x04: // RDA.
case 0x0c: // CTI.
while(U1LSR & 1) //将fifo中的所有数据读完
{
ch = U1RBR;
if(r_next1 != r_first1-1)
{
RcvBuf1[r_next1] = ch;
if (++r_next1 >= RCV_BUF_LEN)
r_next1 = 0;
}
}
break;
case 0x02: // THR Empty.
{
DWORD nCnt = 16; //fifo counter
while( s_next1 != s_first1 && nCnt--)
{
U1THR = SendBuf1[s_first0];
if(++s_first1 >= SEND_BUF_LEN)
s_first1 = 0;
}
}
break;
default:
;
}
}
VICVectAddr=0;
}
/*******************************************************************
* 功能描述: 初始化UART0
* 参 数:
* 返 回:
* 备 注:
*******************************************************************/
void InitUart (void)
{
// 配置UART管脚
PINSEL0 = (PINSEL0 & (~0x0f000f)) | 0x050005; // set p0[1..0] for uart0
ResetBufferPointer(0);
ResetBufferPointer(1);
U0LCR = 0x83; // 默认"9600,n,8,1"
SET_UART0_BAUD(9600)
U0LCR = 0x03;
U0IER = 0x03; // enable rx/tx interrupt.
U0FCR = 1 | (2<<6); // enable fifo,8 byte
U1LCR = 0x83; // 默认"9600,n,8,1"
SET_UART1_BAUD(9600)
U1LCR = 0x03;
U1IER = 0x03; // enable rx/tx interrupt.
U1FCR = 1 | (2<<6); // enable fifo,8 byte
//设置向量中断
VICVectAddr3 = (unsigned long)Uart0_irq;
VICVectCntl3 = 0x20 | 6;
VICIntEnable = 1 << 6 ;
VICVectAddr4 = (unsigned long)Uart1_irq;
VICVectCntl4 = 0x20 | 7;
VICIntEnable = 1 << 7 ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -