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

📄 8051单片机uart驱动程序.txt

📁 8051串口驱动程序
💻 TXT
📖 第 1 页 / 共 2 页
字号:
    if ((unsigned int) baudRate > NUM_BAUD_RATES)
    {
        return 1;
    }

    // See if we *can* set the desired baud rate.
    r_pcon  |= PCON_SMOD;
    th1Value = baudRateTable2x[baudRate];
    if (!th1Value)
    {
        r_pcon  &= ~PCON_SMOD;
        th1Value = baudRateTable1x[baudRate];
        if (!th1Value) return 1;
    }

    // Preserve and clear serial interrupt enable.
    ieEs = _testbit_(r_ieEs);

    // Must ensure that Timer 1 overflow can never cause an interrupt.
    r_ieEt1 = 0;

    // Save this for getUartOption().
    s_currentBaudRate = baudRate;

    // Config. Timer 1 for baud rate generation.
    r_tconTr1 = 0;
    r_tmod   &= T1_MODE_MASK;
    r_tmod   |= T1_8BIT_AUTO_RELOAD;
    r_th1     = (U8) th1Value;
    r_tconTr1 = 1;

    // Restore previous setting.
    r_ieEs    = ieEs;

    return 0;
}
// _____________________________________________________________________________
// _____________________________________________________________________________
//
// Function:  setUartOption
//
// Description:
// ------------
// Allows driver options to be configured by external users.
//
// Design Notes:
// -------------
// Returns zero for no failure, non-zero otherwise. Baud rate changes during
// UART activity may result in corrupt characters sent or received.
// _____________________________________________________________________________
//
bit setUartOption(UartOptions option, int value)
{
    switch (option)
    {
        case UART_TRANSLATE_EOL:
            s_translateEol = (Bool) value;
            return 0;

        case UART_BAUD_RATE:
            return setUartBaudRate((UartBaudRates) value);
    }

    return 1;
}
// _____________________________________________________________________________
// _____________________________________________________________________________
//
// Function:  getUartOption
//
// Description:
// ------------
// Allows driver options to be queried by external users.
//
// Design Notes:
// -------------
// Returns zero for no failure, non-zero otherwise..
// _____________________________________________________________________________
//
bit getUartOption(UartOptions option, int *pValue)
{
    switch (option)
    {
        case UART_TRANSLATE_EOL:
            *pValue = s_translateEol;
            return 0;

        case UART_BAUD_RATE:
            *pValue = s_currentBaudRate;
            return 0;
    }

    return 1;
}
// _____________________________________________________________________________
// _____________________________________________________________________________
//
// Function:  putUartChar
//
// Description:
// ------------
// Driver function to put a character out to the UART via the Tx Ring.
//
// Design Notes:
// -------------
// Will return zero for no failure or non-zero if the ring is full. The Tx
// interrupt will be forced if the Tx Ring is empty to begin a new transmit.
// _____________________________________________________________________________
//
static Bool putUartChar(U8 outChar)
{
    if (s_txRingEmpty || s_txWrIdx != s_txRdIdx)
    {
        Bool data preservedIeEs;

        s_txRing[s_txWrIdx] = outChar;

        // Protect this section from the UART ISR.
        preservedIeEs = _testbit_(r_ieEs);

        ++s_txWrIdx;
#if TX_RING_SIZE != 256
        s_txWrIdx %= TX_RING_SIZE;
#endif

        // Set not empty and prime the transmitter.
        if (s_txRingEmpty)
        {
            s_txRingEmpty = 0;
            r_sconTi      = 1;
        }

        r_ieEs = preservedIeEs;

        return 0;
    }

    return 1;
}
// _____________________________________________________________________________
// _____________________________________________________________________________
//
// Function:  getUartChar
//
// Description:
// ------------
// Driver function to get a character from the UART via the Rx Ring.
//
// Design Notes:
// -------------
// Use _getkey() to see if input is avaiable as this function will return
// failure if caller's <pInChar> is null.
// _____________________________________________________________________________
//
static Bool getUartChar(U8 *pInChar)
{
    if (s_rxRingEmpty) return 1;

    // Do not consume char if caller has no storage for it.
    if (pInChar)
    {
        Bool data preservedIeEs;

        *pInChar = s_rxRing[s_rxRdIdx];

        // Protect this section from the UART ISR.
        preservedIeEs = _testbit_(r_ieEs);

        ++s_rxRdIdx;
#if RX_RING_SIZE != 256
        s_rxRdIdx %= RX_RING_SIZE;
#endif

        // Detect empty.
        if (s_rxRdIdx == s_rxWrIdx) s_rxRingEmpty = 1;

        r_ieEs = preservedIeEs;

        return 0;
    }

    return 1;
}
// _____________________________________________________________________________
// _____________________________________________________________________________
//
// Function:  uartIsr
//
// Description:
// ------------
// UART Interrupt Service Routing (ISR). More like a task that is scheduled by
// hardware events such as RI or TI.
//
// Design Notes:
// -------------
// TI can be set optionally by the timer tick if there is pending data to be
// transmitted and you don't need or want putchar() to initiate transmission.
//
// Only one recv. char and one send char. per interrupt (worse case) for
// determinism reasons.
//
// If a ring size is exactly 256 bytes, this code will skip the modulo operation
// since the 8051 will wrap an unsigned 8-bit var from 0xFF ==> 0x00. Regardless,
// keep the ring sizes a nice even power of two an C51 will use a simple ANL
// instruction for the modulo.
//
// The <s_txRing> is not used as a ring, instead, hitting the wrap point
// indicates empty thus we never need to check for <s_txRdIdx> wrap-to-zero.
// _____________________________________________________________________________
//
static void uartIsr(void) interrupt UART_INTR_NUM using REGISTER_BANK_1
{
    static U8 data inChar;

    if (r_sconRi)
    {
        // Buffer the char in hopes that there is room left in the ring. Drop
        // the char if not. In any case, ack. the receive interrupt.
        r_sconRi = 0;
        inChar   = r_sbufRx;
        if (s_rxRingEmpty || s_rxWrIdx != s_rxRdIdx)
        {
            s_rxRing[s_rxWrIdx] = inChar;
            ++s_rxWrIdx;

#if RX_RING_SIZE != 256
            s_rxWrIdx %= RX_RING_SIZE;
#endif
            s_rxRingEmpty = 0;
        }
    }

    if (r_sconTi)
    {
        // If there are chars. left to send, send one and check for empty,
        // otherwise just ack. the transmit interrupt and leave.
        r_sconTi = 0;
        if (s_txRdIdx != s_txWrIdx)
        {
            r_sbufTx = s_txRing[s_txRdIdx];
            ++s_txRdIdx;

#if TX_RING_SIZE != 256
            s_txRdIdx %= TX_RING_SIZE;
#endif
        }
        else
        {
            // Only declare empty after the last SCON.TI event occurs.
            s_txRingEmpty = 1;
        }
    }
}
// _____________________________________________________________________________
// _____________________________________________________________________________
//
// Function:  main
//
// Description:
// ------------
// Test entry point for this UART driver.
//
// Design Notes:
// -------------
// This main is non-ISO C compliant since it does not return int.
//
// Do not define DBG when using this driver, this main() is only for driver test.
// _____________________________________________________________________________
//
#ifdef DBG
static const char * code s_pUartBaudRateStrings[] =
{
    "1200"  ,
    "2400"  ,
    "9600"  ,
    "19200" ,
    "38400" ,
    "57600" ,
    "115200"
};

sbit r_ieEa = 0xAF; // IE.EA

void main(void)
{
    static int data value;

    initUart(BAUD_RATE_2400);

    r_ieEa = 1;

    // To silence the linker overlay warning and to demonstrate function usage.
    value = 0;
    setUartOption(UART_TRANSLATE_EOL, value);

    // Status message.
    if (getUartOption(UART_BAUD_RATE, &value))
    {
        printf("Failed getting the baud rate.\n");
    }
    else
    {
        printf("The baud rate is %s.\n", s_pUartBaudRateStrings[value]);
        printf("%s started\n", s_moduleInfo);
    }

    // Echo back (loop-back chars).
    for (;;)
    {
        getchar();
    }
}
#endif
// _____________________________________________________________________________
// _____________________________________________________________________________
//
// Revisions:
// ----------
// $Log: uart.c,v $
// Revision 1.15  2002/05/03 21:01:19  mao
// - Now using _testbit_() macro for atomic preservation and clear of UART
//   interrupt enable (credit to Jon Young).
// - Now protect rx and tx ring variables in put and getUartChar(). This fixes
//   false buffer full bug (credit to Jon Young).
//
// Revision 1.14  2002/03/29 16:33:11  mao
// - Switched to proper toolchain constant to distinguish Amrai from Keil builds.
// - Removed unneeded header file.
//
// Revision 1.13  2002/03/28 04:36:02  mao
// - Updated comments.
//
// Revision 1.12  2002/03/28 02:52:57  mao
// - Placed s_moduleInfo into code space, was sucking up precious data space.
//
// Revision 1.11  2002/03/27 16:10:45  mao
// - Added support for AMRAI toolset. Builds but does not work properly yet in
//   simulator.
//
// Revision 1.10  2002/03/27 02:09:51  mao
// - Added license notice.
//
// Revision 1.9  2002/03/27 01:40:44  mao
// - Fixed function header for _getkey().
//
// Revision 1.8  2002/03/17 03:48:08  mao
// - Added some more file header comments about use of driver.
// - Slight style clean up.
// - No longer set EOL translation in initUart() since printf() already does this.
// - Fixed bug. Was not ever clearing s_txRingEmpty bit in putchar().
// - Fixed bug. Was setting s_txRingEmpty in uartIsr() when a char was enqueued
//   instead of transmitted.
// - Fixed bug. Table of baud rates was pointed to improperly.
// - Test main() function now demonstrates all public driver function calls.
//
// Revision 1.7  2002/03/16 04:46:03  mao
// - Freshened file comments.
// - Removed old ifdef C plus plus at end of file.
//
// Revision 1.6  2002/03/16 04:44:01  mao
// - Fixed baud rate typo for 22.118MHz.
// - Added set baud rate function and removed in-lined code in set uart options.
// - Added a non PCON.SMOD = 1 baud rate table and now try to set a baud
//   rate from either table.
// - Fixed table entry bugs for last two XTAL frequencies and moved tables into
//   set uart baud rate function.
// - Fixed recv. ISR bug, now clears Rx Ring empty bit after receiving a char.
// - Added debug table of baud rate strings to print.
//
// Revision 1.5  2002/03/15 04:51:56  mao
// - Fixed bug, debug main() now enables global interrupts.
// - ISR runs fine for both send and receive.
// - Receive seems to work but xmit doesn't show output on debugger screen.
//
// Revision 1.4  2002/03/15 04:29:40  mao
// - Added XTAL frequencies and baud rate table.
// - Added Timer 1 setup.
// - Added save of last set baud rate enum for getUartOptions().
// - Changed some prototypes to return bit instead of int.
// - Fixed putchar() and _getkey() to do as Keil specifies. Removed getchar().
//
// Revision 1.3  2002/03/14 04:21:12  mao
// - Moved ring buffer space and sizing to .c file.
// - Removed rprintf.
// - Implemented more functions.
// - Added set/get options.
// - Test main() now calls all functions, clean build.
// - Added some CPU resources.
// - Baud rate is not yet set.
//
// Revision 1.2  2002/03/13 05:24:20  mao
// - Removed blank line
//
// Revision 1.1.1.1  2002/03/13 05:20:10  mao
// - Initial import
// _____________________________________________________________________________

⌨️ 快捷键说明

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