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

📄 eval_rtos.c

📁 C89c51 usb驱动程序,实现了usb转串口的功能,提供了一个虚拟的串口
💻 C
📖 第 1 页 / 共 3 页
字号:
*	assuming MCU clock mode is set to "X1" and BDRCON reg bit SPD is 1 (x6 speed)
*	and PCON register bit SMOD1 is 1 (double Baud rate).
*	Fosc is the external MCU clock or crystal osc. freq.
*
*	In this example, the required Baud rate is 38400...
*		Fosc = 16MHz, MCU CLK mode is "X1", SMOD1 = 1, SPD = 1.
*		BDCLKDIV = (16E+6 / 2) / (16 * 38400) = 13
*		BRL = 256 - 13 = 243.
*/
void
initialise_uart( void )
{
	/* Install vector for UART interrupt service */
	ROM_VECTOR( 0x23, uart_service );

	SCON = 0x50;					/* Select UART mode 1 (8 bits data); Enable receiver */
	Set_Bit( PCON, BIT7 );			/* SMOD1 = 1 (doubles the Baud rate) */
	BDRCON = 0x0E;					/* Use internal Baud clk (RBCK=TBCK=1); high speed (SPD=1) */
	if ( CKCON0 & BIT0 ) BRL = 230;		/* MCU clock 'X2' mode => BDCLKDIV = 26 */
	else BRL = 243;						/* MCU clock 'X1' mode => BDCLKDIV = 13 */

	Set_Bit( gubMiscFlags, SCI_TXRDY );	/* Indicate transmitter is ready now */
	Set_Bit( IEN0, BIT4 );				/* Enable UART interrupt (TX and RX) */
	Set_Bit( BDRCON, BIT4 );			/* Start Baud clock gen. (RUN=1) */

	pcRxTail = acRxFIFObuf;     	/* Reset RX buffer pointers, byte count */
	pcRxHead = acRxFIFObuf;
	ubRxCount = 0;
}


/*
*  Interrupt Service Routine for 8051 on-chip UART.
*
*  If there is a character available in the UART RX register, an interrupt is
*  generated and this ISR is called.
*  The received char will be read out into a circular (FIFO) buffer in RAM.
*
*  The 8051 UART sets the 'Transmit Interrupt' flag (TI) to indicate when the last byte
*  has been transmitted, i.e. when the serial "buffer" register (SBUF) can be written to.
*  It is not necessary (and quite inconvenient) to use interrupt mode for transmitting
*  in this application. However, the primitive 8051 UART does not allow independent
*  configuration of TX and RX interrupt modes.
*
*  The interrupt service routine simply sets a flag in RAM which mimics the TI flag,
*  and clears the TI flag, which is the source of the interrupt.
*  The non-interrupt mode UART Transmit function, putch(), uses the RAM flag.
*/
interrupt
uart_service( void )
{
	if ( Test_Bit( SCON, BIT0 ))	/* 'Receive Int' (RI) flag set => RX data register full */
	{
		Clear_Bit( SCON, BIT0 );      /* Clear 'Receive Int.' (RI) flag */
		*pcRxTail++ = SBUF;
		if ( pcRxTail >= (acRxFIFObuf + RXBUFSIZE) )
			pcRxTail = acRxFIFObuf;
		ubRxCount++;
	}
	else if ( Test_Bit( SCON, BIT1 ))	/* 'Transmit Int' (TI) flag set => TX data register empty */
	{
		Clear_Bit( SCON, BIT1 );      			/* Clear 'Transmit Int' (TI) flag */
		Set_Bit( gubMiscFlags, SCI_TXRDY );
	}
	else    /* UART Rx interrupt error */
		Set_Bit( gwSystemError, SCI_INT_ERROR );

	if ( ubRxCount > RXBUFSIZE )		/* Rx buffer overflow */
		Set_Bit( gwSystemError, RX_FIFO_OVFL );
}


/*
*  Check serial port RAM buffer for RX character available.
*
*  Called by:  various
*  Entry args: --
*  Returns:    TRUE if char available, else FALSE
*  Affects:    --
*/

bool
uart_rx_data_avail( void )
{
	if ( ubRxCount )
		return TRUE;
	else  return FALSE;
}


/*
*  Function:	uart_getch()
*
*  Get character from host serial receive RAM buffer. It is assumed the buffer contains
*  unread data, as may be established by a prior call to uart_rx_data_avail().
*  The function does not wait for input; if the RX buffer is empty, the function
*  returns 0xFF (-1), otherwise it returns the character code and adjusts buffer pointers.
*  The character is NOT echoed... (see also uart_getche() ).
*
*  Called by:  CLI functions
*  Entry args: --
*  Returns:    (char) character received, or -1 (0xFF) if none in buffer.
*/
char
uart_getch( void )
{
	char  c;

	if ( uart_rx_data_avail() )
	{
		Clear_Bit( IEN0, BIT4 );		/* Disable UART interrupt during buffer read */
		c = *pcRxHead++;
		if ( pcRxHead >= (acRxFIFObuf + RXBUFSIZE) )
			pcRxHead = acRxFIFObuf;
		--ubRxCount;
		Set_Bit( IEN0, BIT4 );			/* Enable UART interrupt */
	}
	else  c = (char) ERROR;

	return c;
}


/*
*  Function:	uart_getche()
*
*  Get character from host serial receive RAM buffer. It is assumed the buffer contains
*  unread data, as may be established by a prior call to uart_rx_data_avail().
*  The function does not wait for input; if the RX buffer is empty, the function
*  returns 0xFF (-1), otherwise it returns the character code and adjusts buffer pointers.
*  The character is echoed to the UART transmitter.
*
*  Called by:  CLI functions
*  Entry args: --
*  Returns:    (char) character received, or 0xFF if none in buffer.
*/
char
uart_getche( void )
{
	char  c = uart_getch();
	putch( c );
	return c;
}


/*
*  Function:	usb_vuart_getche()
*
*  Get character from USB "virtual UART" RX buffer. It is assumed the buffer contains
*  unread data, as may be established by a prior call to usb_vuart_rx_data_avail().
*  NB: If there is no data ready in the USB RX buffer, the function will wait indefinitely!
*  The character is echoed to the USB transmit buffer and the TX buffer is flushed so that
*  the char is sent to the host immediately. (We don't want to wait for TX buffer full.)
*
*  Called by:  CLI functions
*  Entry args: --
*  Returns:    (char) character received.
*/
char
usb_vuart_getche( void )
{
	char  c = usb_vuart_getchar();
	putch( c );
	usb_vuart_flush();
	return c;
}


/*
*  Function:    hci_data_avail
*
*  Purpose:     Checks for received data available from selected HCI stream (UART or USB).
*  Called by:   CLI command functions (only).
*
*  The input source port (USB or UART) is determined by the variable gbHCI_Stream.
*  If gbHCI_Stream is UART_HOST_LINK, the function checks the UART RX buffer,
*  otherwise it checks the USB RX buffer.
*
*  Entry args:  --
*  Returns:     (bool)  TRUE if data is available from the selected input stream, else FALSE.
*  Affects:     --
*/
bool
hci_data_avail( void )
{
	bool   yResult = FALSE;

	if ( gbHCI_Stream == UART_HOST_LINK && uart_rx_data_avail() )
		yResult = TRUE;
	else if ( gbHCI_Stream == USB_HOST_LINK && usb_vuart_rx_data_avail() )
		yResult = TRUE;
	return ( yResult );
}


/*
*  Function:    getch
*  Purpose:     Wait for and fetch a char from "Service Port" (selected stream, UART or USB)
*
*  The input source port (USB or UART) is determined by the variable gbHCI_Stream.
*  If gbHCI_Stream is UART_HOST_LINK, the function inputs via the UART, else via the USB port.
*  The input character is not echoed to the host.
*
*  While waiting for input, the "background process" (B/G task dispatcher) is called, so as
*  not to delay background tasks.  NB: To avoid the possibility of infinite recursion,
*  neither putch() nor getch() can be called from the "background process" routine.
*
*  Called by:   CLI command functions (only)
*  Entry args:  --
*  Returns:     (char) c = inputted byte
*  Affects:     --
*/
char
getch( void )
{
	char   c;

	if ( gbHCI_Stream == UART_HOST_LINK )
	{
		while ( !uart_rx_data_avail() )
		{
			background_process();       /* wait for char to arrive in UART RX buffer */
		}
		c = uart_getch();
	}
	else  /* Assume gbHCI_Stream == USB_HOST_LINK */
	{
		while ( !usb_vuart_rx_data_avail() )
		{
			background_process();       /* wait for char to arrive in USB RX buffer */
		}
		c = usb_vuart_getchar();
	}
	return ( c );
}


/*
*  Function: 	putch
*  Purpose:		Output 8-bit char via "Service Port" UART or the USB port.
*  Called by:   CLI command functions (only).
*
*  The output destination port (USB or UART) is determined by the variable gbHCI_Stream.
*
*  If gbHCI_Stream is UART_HOST_LINK, the function waits for UART TX interrupt (ISR)
*  to set the flag SCI_TXRDY ... up to a time limit.
*  The time limit ensures that the char will be transmitted, and the function will return,
*  in the event that the 'Transmit Interrupt' flag (TI) remains in the low state.
*  While waiting, the "background process" (B/G task dispatcher) is called, so as not to
*  delay background tasks.  NB: To avoid the possibility of infinite recursion, putch()
*  cannot be called from any "scheduled" background task.
*
*  The character code is added (modulo 256) to a global "response checksum" byte, for
*  applications that require response data integrity checking by the host PC.
*
*  Called by:   CLI command functions
*  Entry args: 	(char) c = byte to be transmitted (8 bits)
*  Returns:    	(char) c
*  Affects:    	gubRespCksm, gubMiscFlags<SCI_TXRDY>
*/
char
putch( char c )
{
	int8  bLoopCount = 100;				/* Arbitrary loop "time-out" */

	if ( gbHCI_Stream == UART_HOST_LINK )
	{
		while ( --bLoopCount > 0 )  		/* Loop until time-out occurs */
		{
			if ( Test_Bit( gubMiscFlags, SCI_TXRDY ) )		/* Transmitter is ready */
				break;
			background_process();
		}
		SBUF = c;		/* Write char in TX register, regardless */
		Clear_Bit( SCON, BIT1 );      			/* Clear TI flag */
		Clear_Bit( gubMiscFlags, SCI_TXRDY );
	}
	else if ( gbHCI_Stream == USB_HOST_LINK )
	{
		usb_vuart_putchar( c );
		if ( c == LF )  usb_vuart_flush();
		background_process();
	}
	gubRespCksm += c;
	return ( c );
}



/***********  DEVICE DRIVERS FOR CONTROL SURFACE SWITCHES AND LED INDICATORS  *************/

/*****
*	Returns TRUE if "INT0" button hit.
*   The INT0 button is wired to the MCU input pin P3.2 (external interrupt is disabled).
*/
bool
Button_INT0_hit( void )
{

	/*** to be developed ***/

	return	FALSE;
}


/*****
*	Returns TRUE if "TEST" button hit
*   The INT0 button is wired to the MCU input pin P1.2 (active Low input).
*/
bool
Button_TEST_hit( void )
{

	/*** to be developed ***/

	return	FALSE;
}


/***************  DEVICE DRIVER FOR CONTROL SURFACE LED ANNUNCIATORS  ********************
*
*   The LED driver provides a selection of modes for each LED independently, i.e.
*   ON, OFF or flashing, with selectable flash rate and duty cycle.
*   The LED annunciation modes are set by an array of bytes, one byte per LED.
*   This method minimises data RAM allocation, to suit low-end MCU applications.
*
*   Annunciator mode byte, bit assignments:
*
*   BIT  |   7   |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
*        | FLASH | ON | P2 | P1 | P0 | D2 | D1 | D0 |
*
*   FLASH (bit7) = 0 : Disable LED flashing;  FLASH = 1 : Enable LED flashing.
*   ON (bit6) = 0 : LED is OFF;  ON = 1 : LED is ON continuously or flashing.
*   Bits 0..5 determine the flash rate (period) and on-time duty...
*       P2..P0 => Flash Period (one of 8 predefined, see aubLEDFlashDuty)
*       D2..D0 => Flash On-time Duty (one of 16 predefined, see kabLEDFlashDuty)
*   The Flash Period must be higher than the Flash Duty.
*
*   Table of constants to define 8 preset LED flash periods and ON-time duty (TICKS).
*   D2..D0 is table index for On-time duty; P2..P0 is table index for flash period.
*   (See enumerated constants, e.g. TIME_100mS, in G2test_defs.h)
*/
static  const  uint8  kabLEDFlashDuty[] = { 10, 20, 40, 50, 80, 100, 160, 200 };  // TICKS

static  far  uint8   habLEDannuncMode[NUMBER_OF_LEDS];    // Annunciation modes
static  far  uint8   habLEDflashTimer[NUMBER_OF_LEDS];    // Flash timers (unit = tick)


/*****
*   LED_Refresh() maintains the required annunciation modes of control surface LEDs.
*   The driver is a periodic foreground task, called by the RTI tick handler.
*/
void
LED_Refresh( void )
{
	uint8  bLEDidx;                      // LED identifier (index)
	bool   yLEDstate;                    // Instantaneous LED state (ON/OFF)... to be determined
	bool   yLEDmode;                     // ON/OFF mode bit (1 => on)
	bool   yLEDflash;                    // Flash mode bit (1 => flashing)
	uint8  bFlashOnTime;                 // ON-time duty for flash mode (ticks)
	uint8  bFlashPeriod;                 // Flash Period (ticks)

	for ( bLEDidx = 0;  bLEDidx < NUMBER_OF_LEDS;  bLEDidx++ )
	{
		yLEDmode = habLEDannuncMode[bLEDidx] & BIT6;
		yLEDflash = habLEDannuncMode[bLEDidx] & BIT7;
		bFlashOnTime = kabLEDFlashDuty[ habLEDannuncMode[bLEDidx] & 7 ];
		bFlashPeriod = kabLEDFlashDuty[ (habLEDannuncMode[bLEDidx] >> 3) & 7 ];
		if ( bFlashOnTime > bFlashPeriod )
			bFlashOnTime = bFlashPeriod / 2;

		if ( yLEDmode == 0 ) yLEDstate = OFF;
		else if ( yLEDflash && habLEDflashTimer[bLEDidx] > bFlashOnTime )
			yLEDstate = OFF;    // Duty is done
		else  yLEDstate = ON;   // Active duty or on continuously

		SetLEDoutput( bLEDidx, yLEDstate );
		if ( ++habLEDflashTimer[bLEDidx] >= bFlashPeriod )    // Adjust flash timer
			habLEDflashTimer[bLEDidx] = 0;
	}
}


/*****
*   The functions below set the operational modes of individual LED annunciators, by writing
*   to the relevant LED Annunciator Mode byte. These functions are intended to be called from
*   higher-level application code. The LED Annunciator Mode array is not directly accessible
*   to functions outside of the kernel module (and doesn't need to be).
*
*
*   Function:  SetLEDmode
*   Purpose:   Sets LED annunciator mode to continuously ON or OFF;
*              cancels flashing mode.
*   Arguments:
*       ubLEDident  : LED identifier, enumerated (see G2test_defs.h).
*       yMode       : LED ON/OFF mode (0 => OFF, 1 => ON continuous)
*/
void
SetLEDmode( uint8 ubLEDident, bool yMode )
{
	if ( ubLEDident < NUMBER_OF_LEDS )
	{
		Clear_Bit( habLEDannuncMode[ubLEDident], BIT7 );      // cancel flash mode
		if ( yMode == 0 )
			Clear_Bit( habLEDannuncMode[ubLEDident], BIT6 );
		else  Set_Bit( habLEDannuncMode[ubLEDident], BIT6 );
	}
}


/*
*   Function:  SetLEDFlashMode
*   Purpose:   Sets LED annunciator mode to flashing, with specified period and duty time.
*              A call to this function starts the LED flashing.
*              To cancel flash mode, use the function SetLEDmode(), above.
*   Arguments:
*       ubLEDident  : LED identifier, enumerated (see G2test_defs.h).
*       ubPeriod    : Flash Period, 0..7 (one of 8 preset times)
*       ubDuty      : Flash On-time Duty, 0..7 (one of 8 preset times)
*
*   Preset flash rates (period & duty times) are enumerated by eLED_FLASH_PRESET_TIME.
*   Flash rate can be set from 1Hz up to 20Hz with variable duty cycle (see G2test_defs.h).
*/
void
SetLEDFlashMode( uint8 ubLEDident, uint8 ubPeriod, uint8 ubDuty )
{
	uint8  bMode;

	if ( ubLEDident < NUMBER_OF_LEDS )

⌨️ 快捷键说明

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