📄 16950pci.c
字号:
//
// Switch to receive
//
#ifdef AUTOMATIC_RX
// Disable automatic DTR control
u950pci_acr_write( DevExt, U950PCI_RX_ACR( DevExt) );
#else
u950pci_outb( DevExt->port, UART_MCR, U950PCI_RX_MCR( DevExt ) & 3 );
#endif
u950pci_inb( DevExt->port, UART_IIR ); /* flush irq */
u950pci_inb( DevExt->port, UART_LSR ); /* flush irq */
return TRUE;
};
//*****************************************************************************
//** 16950pci initialize ports (2nd part)
//**
//*****************************************************************************
int u950pci_pinit( PPROFIM_DEVICE_EXTENSION DevExt )
{
unsigned u;
int baud = DevExt->baud_val;
int SC;
int DIV;
int CPR;
/* Switch to enhanced mode */
u950pci_outb( DevExt->port, UART_LCR, U950PCI_LCR_EFR );
u950pci_outb( DevExt->port, UART_EFR, UART_EFR_ECB );
u950pci_outb( DevExt->port, UART_LCR, U950PCI_LCR_UL );
/* Disable transmitter output */
u950pci_outb( DevExt->port, UART_MCR, U950PCI_RX_MCR( DevExt ) & 3 );
/* Set up ACR and state */
u950pci_acr_write( DevExt, U950PCI_RX_ACR( DevExt ) );
DevExt->U950PCI_STATE = U950PCI_STATE_FLUSH;
DevExt->chip_buff[0] = 0;
//
// setup baud rate
//
if ( !baud )
baud = 19200;
u950pci_GetBaudRateParameters( DevExt, DevExt->baud_base, baud,
&SC, &DIV, &CPR );
u950pci_SetBaudRate( DevExt, SC, DIV, CPR );
DbgPrint ( "ProfiM u950pci : Baud rate setup SC=%d DIV=%d CPR=%d\n",
SC,
DIV,
CPR );
DbgPrint ( "ProfiM u950pci : Skutecny Baudrate = %ldbaud\n",
8 * DevExt->baud_base / ( SC * DIV * CPR ) );
/* setup initial FIFO levels */
u950pci_outb( DevExt->port, UART_IER, 0 ); /* disable interrupt sources */
u950pci_outb( DevExt->port,
UART_FCR,
UART_FCR_ENABLE_FIFO |
UART_FCR_CLEAR_RCVR |
UART_FCR_CLEAR_XMIT ); /* enable and clear FIFOs */
u950pci_icr_write( DevExt, UART_TTL, 0 ); /* transmittion FIFO treshold */
#ifdef AUTOMATIC_RX
u950pci_RxTreshold( DevExt, 127 ); /* set maximum FIFO treshold */
#else
u950pci_RxTreshold( DevExt, 1 ); /* receive FIFO treshold */
#endif
/* reset errors */
u950pci_inb( DevExt->port, UART_LSR );
/* and other irq */
u950pci_inb( DevExt->port, UART_RX );
/* Enable interrupts */
u950pci_outb( DevExt->port, UART_MCR, U950PCI_RX_MCR( DevExt ) );
/* enable interrupt sources */
u950pci_outb( DevExt->port, UART_IER,
UART_IER_RDI | UART_IER_THRI | UART_IER_RLSI ); // UART_IER_RLSI zatim navic - pro time-out ???
//DbgPrint ( "ProfiM u950pci : Last MCR value=%2x\n",
// UART_MCR, U950PCI_RX_MCR( DevExt ) );
//DbgPrint ( "Profim u950pci : ACR = %x",
// u950pci_icr_read( DevExt, UART_ACR ) );
return TRUE;
};
//*****************************************************************************
//** Set transmittion FIFO treshold
//**
//*****************************************************************************
void u950pci_TxTreshold( PPROFIM_DEVICE_EXTENSION DevExt, int Treshold )
{
u950pci_icr_write( DevExt, UART_TTL, Treshold );
}
//*****************************************************************************
//** Set receive FIFO treshold
//**
//*****************************************************************************
void u950pci_RxTreshold( PPROFIM_DEVICE_EXTENSION DevExt, int Treshold )
{
DevExt->RTL = Treshold;
u950pci_icr_write( DevExt, UART_RTL, Treshold );
}
//*****************************************************************************
//** Checks for waitting data if receiver FIFO
//**
//*****************************************************************************
BOOLEAN u950pci_RxDataReady( PPROFIM_DEVICE_EXTENSION DevExt )
{
return ( u950pci_xfl_read( DevExt, UART_RFL ) > 0 );
}
//*****************************************************************************
//** Set baud rate
//**
//** Vysledny baud rate je dan jako:
//** BR = 8 * XTALFrequency / ( SC * DIV * CPR )
//**
//*****************************************************************************
void u950pci_SetBaudRate( PPROFIM_DEVICE_EXTENSION DevExt,
int SC,
int DIV,
int CPR )
{
//
// prescaler 1 to 31.875 step 0.125
// prescaler=CPR/8
//
u950pci_icr_write( DevExt, UART_CPR, CPR );
//
// 4 to 16 times per clock
//
if (SC>=4 && SC<=15)
u950pci_icr_write( DevExt, UART_TCR, SC );
else
u950pci_icr_write( DevExt, UART_TCR, 0x00 );
//
// divisor 1 to 2^16
//
u950pci_outb( DevExt->port, UART_LCR, UART_LCR_DLAB );
u950pci_outb( DevExt->port, UART_DLL, DIV & 0x00FF );
u950pci_outb( DevExt->port, UART_DLM, ( DIV >> 8 ) );
u950pci_outb( DevExt->port, UART_LCR, U950PCI_LCR_UL );
}
//*****************************************************************************
//** Get baud rate parameters
//** Pro zname hodnoty frekvenci krystalu vraci parametry pro nastaveni rych-
//** losti UARTu. Vracene parametry jsou nejlepsi mozne pro dany krystal a
//** pozadovany baud rate - skutecny baud rate ma minimalni odchylku.
//** Pro potreby Profibusu je normou stanovena maximalni tolerance +/- 0.3 %.
//** Takze pro krystal 1.8432Mhz je nejvyssi rychlost v norme 45.45kbps
//** (prakticky funguje az po 187.5kbps.
//** Pro krystal 14.7456Mhz je nejvyssi rychlost v norme 500kbps.
//**
//** Vysledny baud rate je dan jako:
//** BR = 8 * XTALFrequency / ( SC * DIV * CPR )
//**
//** Vztah mezi hodnotami Prescaler a CPR:
//** Prescaler = CPR / 8
//**
//*****************************************************************************
void u950pci_GetBaudRateParameters( PPROFIM_DEVICE_EXTENSION DevExt,
LONG XTALFrequency,
LONG BaudRate,
int *SC,
int *DIV,
int *CPR )
{
switch (XTALFrequency)
{
case 1843200:
switch (BaudRate)
{
case 9600: *SC=16; *DIV=12; *CPR=8;
break;
case 19200: *SC=16; *DIV=6; *CPR=8;
break;
case 45450: *SC=12; *DIV=3; *CPR=9;
break;
case 93750: *SC=13; *DIV=1; *CPR=12; // chyba presahuje 0.3%
break;
case 187500: *SC=6; *DIV=1; *CPR=13; // chyba presahuje 0.3%
break;
case 375000: *SC=5; *DIV=1; *CPR=8; // chyba presahuje 0.3%
break;
default: *SC=16; *DIV=12; *CPR=8; // chyba presahuje 0.3%
break;
}
break;
case 14745600:
switch (BaudRate)
{
case 9600: *SC=16; *DIV=96; *CPR=8;
break;
case 19200: *SC=16; *DIV=48; *CPR=8;
break;
case 45450: *SC=15; *DIV=1; *CPR=173;
break;
case 93750: *SC=14; *DIV=10; *CPR=9;
break;
case 187500: *SC=14; *DIV=5; *CPR=9;
break;
case 375000: *SC=7; *DIV=5; *CPR=9;
break;
case 500000: *SC=4; *DIV=1; *CPR=59;
break;
case 750000: *SC=13; *DIV=1; *CPR=12; // chyba presahuje 0.3%
break;
case 1500000: *SC=6; *DIV=1; *CPR=13; // chyba presahuje 0.3%
break;
default: *SC=16; *DIV=96; *CPR=8;
break;
}
break;
case 24073420:
switch (BaudRate)
{
case 9600: *SC=10; *DIV=118; *CPR=17;
break;
case 19200: *SC=10; *DIV=59; *CPR=17;
break;
case 45450: *SC=13; *DIV=2; *CPR=163;
break;
case 93750: *SC=13; *DIV=2; *CPR=79;
break;
case 187500: *SC=13; *DIV=1; *CPR=79;
break;
case 375000: *SC=9; *DIV=3; *CPR=19;
break;
case 500000: *SC=7; *DIV=5; *CPR=11;
break;
case 750000: *SC=16; *DIV=2; *CPR=8; // chyba 0.3%
break;
case 1500000: *SC=16; *DIV=1; *CPR=8; // chyba 0.3%
break;
case 3000000: *SC=8; *DIV=1; *CPR=8; // chyba 0.3%
break;
case 6000000: *SC=4; *DIV=1; *CPR=8; // chyba 0.3%
break;
default: *SC=10; *DIV=118; *CPR=17;
break;
}
break;
default:
//
// Pokud frekvence krystalu nepatri k predpocitanym jsou parametry
// vypocitany, avsak pouze pro pevne hodnoty Prescaler=1 a SC=4
// tzn. muze existovat jina kombinace Prescaler, SC a Divider, ktera
// dosahne pro pozadovany baud rate vetsi presnosti.
//
*CPR=8; // odpovida Prescaler=1
*SC=4;
*DIV=XTALFrequency / ( 4 * BaudRate );
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -