📄 16550.c
字号:
#include "ip51_sfr.h"
#include "target.h"
#include "16550.h"
#include "stdio.h"
static UINT8 xdata utbuf[UTBUF_SIZE];
static UINT8 xdata urbuf[URBUF_SIZE];
static UINT16 idata ur_in=0;
static UINT16 idata ur_out=0;
static UINT16 idata ut_in=0;
static UINT16 idata ut_out=0;
static bit ut_restart=1;
static UINT16 idata ur_ovf_cnt =0;
void uart_initialize (UINT8 confg,UINT32 baut)
{
/******************************************************************************/
/******************************************************************************/
UINT8 temp;
FCR = 0x87;//set receive FIFO threshold = 8 byte,enable FIFO,reset RX/TX FIFO
//******************************************************************************/
/*********Read the following register to clear IIR *****************************/
/*******************************************************************************/
temp = LSR;
temp = MSR;
temp = IIR;
/********************************************************************************/
/*****************set UART work mode ********************************************/
//CLS :confg.1 confg.0 00--data bits = 5
// 01--data bits = 6
// 10--data bits = 7
// 11--data bits = 8
//STOP :confg.2 0---stop bits = 1
// 1---stop bits = 1.5/2;when data bits=5,stop bits = 1.5,
// otherwise,stop bits=2
//PEN :confg.3 0---disable odd/even check
// 1---enable odd/even check
//PES :confg.4 0---odd check
// 1---even check
/********************************************************************************/
LCR = confg & 0x1F;
//set communicate baudrate
uart_baudrate(baut);
/********************************************************************************/
/***********Set UART interrupt enable ******************************************/
/********************************************************************************/
IER |= 0x0F;
/********************************************************************************/
/***********Remove RX FIFO/TX FIFO reset*****************************************/
/********************************************************************************/
FCR &= 0xF9;
//clear UART Interrupt flag
EXIF &= 0xBF;
//open UART's interrupt enable
EIE |= 0x04;
}
void uart_baudrate (UINT32 baudrate)
{
int_2_c div ;
div.i = XTAL/baudrate/16;
LCR |= 0x80;//select DLH,DLL sfr
DLH = div.u8.u8_1;
DLL = div.u8.u8_2;
LCR &= 0x7F;//deselect DLH,DLL
}
static void uart_isr() interrupt 10 using 3
{
UINT8 i;
EIE &= 0xFB;
P6 ^= 0x01;
P5 = IIR;
EXIF &= 0xBF;//clear int flag
switch(IIR & 0x0F)
{
case 0x06://0110 :receive status---overflow;odd/even chech err;frame err;pause int
P4 = LSR;//read LSR to clear interrupt
switch(LSR)
{
default:
break;
}
break;
case 0x04://0100 :receive data valid//
case 0x0C://1100 :receive time out//Read RBR to clear interrupt
while(LSR & 0x01)
{
urbuf[ur_in & (URBUF_SIZE-1)] = RBR;
if((uart_rbuflen() & ~(URBUF_SIZE-1)) == 0)
ur_in ++;
else
ur_ovf_cnt ++;
}
break;
case 0x01://enable at uput_char
/* if((LSR&0x60) != 0x60)
break;*/
// if(LSR == 0x00)
break;
case 0x02://0010 :THR empty //Read IIR or Write THR to clear interrupt
//if((LSR & 0x60))
for(i=0;i<16;i++)
{
if(ut_in != ut_out)
{
THR = utbuf[ut_out & (UTBUF_SIZE-1)];
ut_out ++;
ut_restart = 0;
}
else
{
ut_restart = 1;
break;
}
}
break;
case 0x00://0000 :Modem status change
P5 = MSR;
break;
default:
P6 = 0x55;
break;
}
if(ut_restart)
for(i=0;i<16;i++)
{
if(ut_in != ut_out)
{
THR = utbuf[ut_out & (UTBUF_SIZE-1)];
ut_out ++;
ut_restart = 0;
}
else
{
ut_restart = 1;
break;
}
}
EIE |= 0x04;
}
INT8 uput_char(UINT8 c)
{
//if the output buffer is full,return an error value
if(uart_tbuflen() >= UTBUF_SIZE)
return (-1);
/*******************************************************/
//Add the data to the transmit buffer. If the
//transmit interrupt is disabled, then enable it.
/*******************************************************/
// printf("uput\n");
utbuf [ut_in & (UTBUF_SIZE - 1)] = c;
ut_in++;
/*Add the follwing code to be strong */
// if(LSR & 0x40)//TEMT
// ut_restart = 1;
if (ut_restart)
{
// printf("restart\n");
// ut_restart = 0;
EXIF |= 0x40; // generate transmit interrupt
}
return (0);
}
INT8 usend(UINT8 xdata *str,UINT16 len)
{
UINT8 * character;
UINT16 l;
// printf("usend = %x \n",uart_tbuflen());
l = len;
character = str;
if((uart_tbuflen()+l) > UTBUF_SIZE)//utbuf will overflow
return(-1);
while(l >0)
{
while(1)
if(uput_char(*character)==0)
{
character ++;
l --;
break;
}
}
return (0);
}
INT8 uart_getchar (void)
{
if (uart_rbuflen () == 0)
return (-1);
return (urbuf [(ur_out++) & (URBUF_SIZE - 1)]);
}
UINT16 uart_tbuflen (void)
{
return (ut_in - ut_out);
}
UINT16 uart_rbuflen (void)
{
return (ur_in - ur_out);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -