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

📄 serial-lpc.c

📁 ucos ii串口通讯程序
💻 C
字号:
/***************************************************************************\
	Copyright (c) 2004-2007 threewater@up-tech.com, All rights reserved.
	by threewter	2004.4.26
\***************************************************************************/
	

/***************************************************************************\
    #说明: lpc2xxx串口驱动程序for uCOS-II
	----------------------------------  Bug  --------------------------------------

	----------------------------------  TODO list  --------------------------------------

	----------------------------------修正--------------------------------------
	2005-5-30	创建

\***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

#include	"../inc/sys/uart.h"
#include "../inc/drivers.h"
#include "../inc/drv/serial.h"
#include "../inc/sys/io.h"
#include <uhal/isr.h>

#define GENERATOR_CLK		Fpclk

#define FIFO_LENGTH		16

//Register OFFSET in 16550
#define Uart_RBR		(0x0)
#define Uart_THR		(0x0)
#define Uart_DLL		(0x0)
#define Uart_IER		(0x4)
#define Uart_DLM		(0x4)
#define Uart_IIR		(0x8)
#define Uart_FCR		(0x8)
#define Uart_LCR		(0xc)
#define Uart_MCR		(0x10)
#define Uart_LSR		(0x14)
#define Uart_MSR		(0x18)
#define Uart_SCR		(0x1c)
#define Uart_UartEN	(0x30)

#define Uart_LSR_TEMT		(1<<6)
#define Uart_LSR_THRE		(1<<5)
#define Uart_LSR_DR			(1)

#define Uart_FCR_FIFOEN		(1)
#define Uart_FCR_RCVR		(1<<1)
#define Uart_FCR_XMIT		(1<<2)

#define Serial_Isr(n)		(UART0_OFFSET+n)	//串口中断号

const static int Uart_Base[]={U0BASE, U1BASE};
static U8 serial_sending[NumberOfArray(Uart_Base)];

#define serial_inb(ndev, offset)	_inb(Uart_Base[ndev] + offset)
#define serial_outb(ndev, offset, ch)	_outb(Uart_Base[ndev] + offset, ch)

static void serial_isr(int vector, int ndev);

__inline static int serial_init(int ndev, int baudrate)
{
	int div=(GENERATOR_CLK*10/16/baudrate+5)/10;

	serial_outb(ndev, Uart_UartEN, 1);	//enable uart
	
	//set serial baudrate
	serial_outb(ndev, Uart_LCR, 0x80);	//DLAB=1
	serial_outb(ndev, Uart_DLL, div);
	serial_outb(ndev, Uart_DLM, div>>8);

	serial_outb(ndev, Uart_LCR, 0x03);	//DLAB=0, 8bit,1 stop, N mode
	serial_outb(ndev, Uart_FCR, Uart_FCR_FIFOEN);	//FIFO on
	serial_outb(ndev, Uart_IER,0x0);	//disable all interrupt
	serial_outb(ndev, Uart_MCR,0x03);	//set RTS and DTR 

	serial_sending[ndev]=0;

	return 0;
}

__inline static int serial_open(int ndev)
{
	serial_outb(ndev, Uart_IER,0x1);	//enable recieve interrupt
	SetISR_Interrupt(Serial_Isr(ndev), (Interrupt_func_t)serial_isr, (void*)ndev);
	
	return 0;
}

__inline static int serial_read(int ndev)
{
	return serial_inb(ndev, Uart_RBR);
}

__inline static int serial_write(int ndev)
{
	int data;

	if(serial_sending[ndev])
		return 0;

	while(serial_inb(ndev, Uart_LSR) & Uart_LSR_THRE){
			data=Get_SndBuffer(ndev);
			if(data<0)
				return 0;
			if(data == 13)
				serial_outb(ndev, Uart_THR, 10);
				
			serial_outb(ndev, Uart_THR, data);
	}

	serial_sending[ndev]=1;
	serial_outb(ndev, Uart_IER,0x3);	//enable recieve and send interrupt

	return 0;
}

__inline static int serial_writepoll(int ndev, int ch)
{
	serial_outb(ndev, Uart_THR, ch);
	while(!(serial_inb(ndev, Uart_LSR) & Uart_LSR_THRE));

	return 0;
}

__inline static int serial_poll(int ndev)
{
	return (serial_inb(ndev, Uart_LSR) & Uart_LSR_DR);
}


//采用中断的方式获取串口数据
static void serial_isr(int vector, int ndev)
{
	int lsr;
	while((serial_inb(ndev, Uart_IIR) & 0x01) == 0)/* 有中断未处理完 */
	{
		lsr = serial_inb(ndev, Uart_LSR);
		//(lsr & Uart_LSR_THRE) ==1 判断是否有可读数据
		//isr 包含了多个信息,这里只 处理了接收和发送的中断
		if((lsr & Uart_LSR_THRE) && serial_sending[ndev]==1){	// THRE中断//
			int data, i;

			for(i=0; i<FIFO_LENGTH; i++){
				data=Get_SndBuffer(ndev);
				if(data<0){	//发送缓冲区空
					serial_outb(ndev, Uart_IER, 0x1);	//关闭发送中断
					serial_sending[ndev]=0;
					break;
				}
				serial_outb(ndev, Uart_THR, data);
			}
		}

		if(lsr & Uart_LSR_DR){	//接收中断
			do{
				Put_RevBuffer(ndev, serial_read(ndev));
			}while(serial_inb(ndev, Uart_LSR) & Uart_LSR_DR);
		}
	}
}

__inline static int serial_flush_input(int ndev)
{
	serial_outb(ndev, Uart_FCR, Uart_FCR_RCVR);
	return 0;
}
/**
//真正的刷新缓存函数,将	寄存器的数据全部读出
//这里我默认的触发机制时,有足够的数据就才触发中断,
//即使没有中断产生,但是有接收的数据Uart_LSR_DR 对应的值也是1
__inline static int serial_flush_input(int ndev)
{
			do{
				Put_RevBuffer(ndev, serial_read(ndev));
			}while(serial_inb(ndev, Uart_LSR) & Uart_LSR_DR);
}

*/
__inline static int serial_flush_output(int ndev)
{
	serial_outb(ndev, Uart_FCR, Uart_FCR_XMIT);
	return 0;
}

#define DefSerialN(n)	static int lpc2xxx_serial##n##_init(int baud){return serial_init(n,baud);}\
					static int lpc2xxx_serial##n##_open(void){return serial_open(n);}\
					static int lpc2xxx_serial##n##_read(void){return serial_read(n);}\
					static int lpc2xxx_serial##n##_write(void){return serial_write(n);}\
					static int lpc2xxx_serial##n##_writepoll(int ch){return serial_writepoll(n, ch);}\
					static int lpc2xxx_serial##n##_poll(void){return serial_poll(n);}\
					static int lpc2xxx_serial##n##_flush_input(void){return serial_flush_input(n);}\
					static int lpc2xxx_serial##n##_flush_output(void){return serial_flush_output(n);}

/* export serial driver */
#define ExportSerialN(n)	const serial_driver_t lpc2xxx_serial##n##_driver = {	\
							lpc2xxx_serial##n##_init,	\
							lpc2xxx_serial##n##_open,\
							lpc2xxx_serial##n##_read,\
							lpc2xxx_serial##n##_write,\
							lpc2xxx_serial##n##_writepoll,\
							lpc2xxx_serial##n##_poll,\
							lpc2xxx_serial##n##_flush_input,\
							lpc2xxx_serial##n##_flush_output,\
							}
DefSerialN(0)
DefSerialN(1)


ExportSerialN(0);
ExportSerialN(1);

⌨️ 快捷键说明

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