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

📄 uart.c

📁 lpc2136芯片的硬件全部功能示例程序
💻 C
字号:
/*************************************************************
		WPD800 串口驱动
		修改历史    2007-9-25  zaken create version 1.0


*************************************************************/
/*
使用串口0 ,接收采用中断方式

*/
#include "main.h"
#include "string.h"
#include "intctrl.h"
#include "uart.h"

extern volatile DWORD	dTCounter;
//波特率表定义
const uint32  brgtlb[]={300,600,1200,2400,4800,9600,19200,38400,115200};

typedef struct tagT_PACKET
{
	WORD	data_ptr;
	WORD	data_len;
	BYTE	data[UART_PACKET_SIZE];
}	T_PACKET;

typedef struct tagT_PACKET_LIST
{
	WORD	 l_head;
	WORD	 l_tail;
	T_PACKET packet[UART_MAX_PACKET];
}	T_PACKET_LIST;

typedef struct tagT_UART_STATUS
{
	DWORD RxFrameCnt;//接收桢计数
	DWORD RxFrameErrCnt;//接收错误帧计数
	DWORD SendFrameCnt;//发送桢计数
}T_UART_STATUS;

typedef struct	tagT_UART
{
	WORD			u_flags;
	Uart_Config		u_config;
	WORD			idle_time;	/* 接收空闲间隔时间		*/
	DWORD			recv_time;	/* 前一个字符的接收时间 */
	bool			recv_flag;	/* UART是否正在接收数据 */
	T_PACKET_LIST	recv_list;	//接收缓冲
	T_UART_STATUS   status;
}T_UART;

static T_UART  tuart;
/* 接收中断回调函数,用以判断数据帧的结束。*/
uint16 huarui94_check_packet(const uint8 *p_data, uint16 data_len)
{
	BYTE len;
	if(data_len==1)
	{
		if(p_data[0]!=1)
			return UART_PKT_ERR;
	}
	if(data_len < 5)
	return UART_PKT_CON;
	len = p_data[2] + 4;			//读报文长度
	if(data_len >= len)
	{
		return UART_PKT_FIN;
	}	
	return UART_PKT_CON;
}
//取得串口的配置
int uart_config()
{
	
	return OK;
}
void uart_open(Uart_Config *pcfg)
{	
	uint32 baudrate,bak;
	/* 参数过滤 */
	if(pcfg->brg>=UART_BRG_MAX_INDEX)
		pcfg->brg=UART_DEFAULT_BRG;
	
	if ((pcfg->databit <5) || (pcfg->databit > 8))
		pcfg->databit=8;
			
	if ((pcfg->stopbit == 0) || (pcfg->stopbit > 2))
		pcfg->stopbit=0; 	
	if (pcfg->parity > 4)	
		pcfg->parity=0;
	baudrate=brgtlb[pcfg->brg];
	/* 设置串口波特率 */
	U0LCR = 0x80;						// DLAB = 1	
	bak   = (Fpclk >> 4) / baudrate;
	U0DLM = bak >> 8;
	U0DLL = bak & 0xFF;
	
	/* 设置串口模式 */
	bak   = pcfg->databit - 5;				// 设置字长
	if (pcfg->stopbit == 2)	bak |= 0x04;	// 判断是否为2位停止位
	
	if (pcfg->parity != 0)
	{
		pcfg->parity =pcfg->parity - 1;
		bak |= 0x08;
	}
	bak |= pcfg->parity << 4;				// 设置奇偶校验	
	U0LCR = bak;
	
}
static void uart_rx_intr()
{
	T_UART	 *p_uart;
	T_PACKET *p_pkt;
	WORD	 callback;
	p_uart=&tuart;
	p_pkt =&p_uart->recv_list.packet[p_uart->recv_list.l_tail];
	if ( !p_uart->recv_flag )
	{
		p_uart->recv_time =dTCounter;//采样中断计数
		p_uart->recv_flag =TRUE;
		p_pkt->data_len   =0;
	}
	else
	{
		if ((DWORD)(dTCounter/*采样中断计数*/-p_uart->recv_time) >= 1000)//超时时间
		{		
			p_pkt->data_len =0;
		}
		p_uart->recv_time =dTCounter;//采样中断计数
	}
   	p_pkt->data[p_pkt->data_len++] =U0RBR;
	/* 如果接收缓冲区满,默认为一帧报文结束 */
	if (p_pkt->data_len >= UART_PACKET_SIZE)
	{
		WORD next =(p_uart->recv_list.l_tail + 1) % UART_MAX_PACKET;
		
		if (next != p_uart->recv_list.l_head)
		{
			p_uart->recv_list.l_tail =next;
		}
		p_uart->recv_flag =FALSE;
		return;
	}
	/* call callback function to validate the packet. */
	if ( !p_uart->u_config.pcb )
	{
		return;
	}
	callback =(*p_uart->u_config.pcb)(p_pkt->data, p_pkt->data_len);
	if (callback == UART_PKT_FIN)
	{
		
		WORD next =(p_uart->recv_list.l_tail + 1) % UART_MAX_PACKET;
		p_uart->status.RxFrameCnt++;
		if (next != p_uart->recv_list.l_head)
		{
			p_uart->recv_list.l_tail =next;
		}
		else //缓冲满,记录错误状态
			RECORD_ERR_FLAG(4);//接收缓冲溢出
			
		p_uart->recv_flag =FALSE;
	}
	else if (callback == UART_PKT_ERR)
	{
		p_uart->status.RxFrameErrCnt++;
		p_uart->recv_flag =FALSE;
	}
}
void __irq uart_interrupt (void)
{
	uint8 status;
	while(((status=U0IIR)& 0x01)==0)//中断处理
	{
		switch(status & 0x0e)
		{
			case 0x02://接收中断,未使能,如果产生报错
				//置错误位
				RECORD_ERR_FLAG(0);
				break;
			case 0x04:
				uart_rx_intr();
				break;
			case 0x06://线状态
				//置错误位
				RECORD_ERR_FLAG(1);
				RECORD_ERR_STATUS(U0LSR);//读LSR复位中断				
				break;
			case 0x0c://字符超时
				RECORD_ERR_FLAG(2);
				RECORD_ERR_STATUS(U0RBR);//读RBR复位中断	
				break;
			default:
				RECORD_ERR_FLAG(3);
				break;
		}
		VICVectAddr = 0x00;			// 中断处理结束
	}
}
//串口初始化
int32 uart_init(void)
{

	tuart.u_config.brg=UART_DEFAULT_BRG;
	tuart.u_config.databit=8;
	tuart.u_config.stopbit=0;
	tuart.u_config.parity=0;
	tuart.u_config.pcb=huarui94_check_packet;
	//清接收发送缓冲未写
	PINSEL0 = (PINSEL0 & 0xfffffff0)|0x00000005;				// 设置I/O连接到UART0
	
	uart_open(&tuart.u_config);			// 串口初始化
	U0FCR = 0x01;						// 使能FIFO,并设置触发点为1字节
	U0IER = 0x05;						// 允许RBR中断,即接收中断和rx线状态中断	
	return Int_Setup(6,(uint32)uart_interrupt,0,0);
	/*
	IRQEnable();						// 使能IRQ中断
	VICIntSelect = 0x00000000;			// 设置所有的通道为IRQ中断
	VICVectCntl0 = 0x20 | 0x06;			// UART0分配到IRQ slot0,即最高优先级
	VICVectAddr0 = (uint32)uart_interrupt;	// 设置UART0向量地址
	VICIntEnable = 1 << 0x06;			// 使能UART0中断
	*/
	//return OK;
}
WORD UART_Read(BYTE *p_data)
{
	WORD	  next, bytes_read;
	T_UART	 *p_uart;
	T_PACKET *p_pkt;
	p_uart =&tuart;
	next =p_uart->recv_list.l_head;
	if (next == p_uart->recv_list.l_tail)
	{
		return 0;
	}
	p_pkt =&p_uart->recv_list.packet[next];
	
	bytes_read =p_pkt->data_len;
	memcpy(p_data, p_pkt->data, bytes_read);
	p_uart->recv_list.l_head =(next + 1) % UART_MAX_PACKET;
	return bytes_read;
}
WORD UART_Write(const BYTE *p_data, WORD data_len)
{
	WORD i;
	if ((data_len == 0) || (data_len > UART_PACKET_SIZE))
	{
		return 0;
	}
	for(i=0;i<data_len;i++)
	{
		U0THR = p_data[i];	// 要发送的数据
		while ((U0LSR & 0x40) == 0);
	}
	tuart.status.SendFrameCnt++;
	return data_len;
}
void Uart_Close()//关闭串口,切换规约时
{
	
}

⌨️ 快捷键说明

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