📄 8051单片机uart驱动程序.txt
字号:
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 + -