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

📄 example.c

📁 C89c51 usb驱动程序,实现了usb转串口的功能,提供了一个虚拟的串口
💻 C
字号:
/*
*   example.c
*
*   Main module with example functions for USB comm's with "virtual UART".
*/

#include "a89c5131.h"        /* MCU-specific definitions */
#include "intrpt.h"          /* Compiler-specific interrupt support defs (Hi-Tech C 8051) */
#include "eval_defs.h"       /* Eval. board application common definitions */
#include "usb_vuart_lib.h"   /* Atmel USB library defs */
#include "usb_drv.h"
#include "usb_cdc_enum.h"


/*
*   Function prototypes -- better to be put in a header file
*/
void  transmit_data_to_host( void );
void  usb_putstr( char * psz );
void  usb_putHexdigit( uint8 d );
void  usb_putHexbyte( uint8 b );
void  usb_putHexword( uint16 uwArg1 );
void  usb_putDecimal( uint16 uwArg1, uint8 ubPlaces );


/*
*   globals
*/
idata  bit    yUSB_connected;
idata  uint8  bUSB_SOFcounter;
idata  uint8  bLastTxCounter;

extern uint8  usb_configuration_nb;
extern uint8  tx_counter;


/*****
*   Function to initialise application program variables, etc.
*/
void
initialise_app( void )
{
	uint16  wStartTime = get_ticks();

	configure_usb_clock();
	Usb_enable();
	Usb_detach();
	while ( get_ticks() - wStartTime < 100 )   // wait 500mS
	{
		;;;
	}
	Usb_attach();
	usb_configure_endpoint( EP_CONTROL, CONTROL );
	usb_reset_endpoint( EP_CONTROL );
	usb_var_init();
	usb_vuart_init();
	bLastTxCounter = 0;
	yUSB_connected = TRUE;
}


/*********************************  MAINLINE  ********************************************
*
*/
void
main( void )
{
	initialise_rtos();
	initialise_cli();
	initialise_app();

	while ( 1 )     // main loop
	{
		maintain_usb_connection();
		background_process();
		check_uart_HCI_input();   // Using UART (RS232) for CLI "debug port"
/***
		check_usb_HCI_input();    // Disabled!!! Not using USB for CLI!!!
***/
	}
}


/*****
*   Function:   maintain_usb_connection
*   Purpose:    maintain USB connection
*
*   Must be called *frequently* from main loop!
*/
void
maintain_usb_connection(void)
{
	if ( ! yUSB_connected )
	{
		if ( Usb_resume() )
		{
			Usb_clear_suspend_clock();
			yUSB_connected = TRUE;
			Usb_clear_suspend();
			Usb_clear_resume();
			Usb_clear_sof();
		}
	}
	else
	{
		if ( Usb_suspend() )
		{
			yUSB_connected = FALSE;
			Usb_clear_suspend();
			Usb_set_suspend_clock();
		}
		if ( Usb_reset() )
		{
			usb_var_init();
			Usb_clear_reset();
			usb_vuart_init();
			bLastTxCounter = 0;
		}
		if ( Usb_sof() )
		{
			if ( bLastTxCounter == tx_counter ) usb_vuart_flush();  // check
			bLastTxCounter = tx_counter;
			bUSB_SOFcounter++ ;
			Usb_clear_sof();
		}
		if ( Usb_endpoint_interrupt() )     // polling, not a real interrupt
		{
			Usb_select_ep( EP_CONTROL );
			if ( Usb_setup_received() )  usb_enumeration_process();
			Usb_select_ep( 3 );
			if ( Usb_tx_complete() )  Usb_clear_tx_complete();
		}
	}
}



/******************************************************************************************
*
*   Function:       background_process
*   Purpose:        Background task dispatcher for scheduled tasks.
*   Called from:    main background loop
*
*   The background process consists of a number of tasks which may be executed periodically
*   or "ad-hoc" (i.e. invoked by another process). Periodic tasks are scheduled by the RTI
*   timer "tick handler" (foreground routine). B/G tasks are not prioritised in this
*   minimal RTOS design... pending tasks are executed in a round-robin loop.
*
*   The background process should normally be completed within 5 mSec (tick interval),
*   although the occasional *brief* overrun can be tolerated, as long as the overrun time
*   does not exceed the watchdog time-out interval.
*
*   The background process and all functions which it calls are prohibited from
*   calling functions which input data via "getch()" or which output data via "putch()".
*   This is because getch() and putch() call the background process, so that command functions
*   which use getch() or putch() do not cause delays to background tasks during serial I/O.
*/
void
background_process( void )
{
	if ( Test_Bit( gubTaskFlags, TICKS_TASK ) )         /* Flag set every tick (5 mSec) */
	{
		#if WATCHDOG_ENABLED
			service_watchdog();
		#endif

		/*** Put here calls to function(s) to be executed every tick (5 mSec) ***/

		Clear_Bit( gubTaskFlags, TICKS_TASK );
	}
	if ( Test_Bit( gubTaskFlags, FIFTY_MSEC_TASK ) )    /* Flag set every 10th tick (50 mSec) */
	{
		/*** Put here calls to function(s) to be executed every 50mSec ***/

		Clear_Bit( gubTaskFlags, FIFTY_MSEC_TASK );
	}
	if ( Test_Bit( gubTaskFlags, SECONDS_TASK ) )       /* Flag set every second */
	{
		/*** Put here calls to function(s) to be executed every second ***/

		transmit_data_to_host();    // Application-specific task

		Clear_Bit( gubTaskFlags, SECONDS_TASK );
	}
	if ( Test_Bit( gubTaskFlags, NEWDAY_TASK ) )        /* Flag set every day at mid-night */
	{
		/*** Put here calls to function(s) to be executed every day at midnight ***/

		Clear_Bit( gubTaskFlags, NEWDAY_TASK );
	}

	if ( Test_Bit( gubTaskFlags, EEPROM_UPD_TASK ) )    /* Flag set to store data in EEPROM */
		eeprom_update_task();

	/*** Put here conditional calls to any other task functions ***/
}


/*
*   Function to transmit data to host PC via USB virtual uart.
*   This is a scheduled task, called by the background_process() "task dispatcher",
*   once every second.
*
*   In this example, a 16-bit binary number is converted to a decimal ASCII string
*   and output via the USB "vuart" by the function usb_putDecimal(), defined below.
*   The number is incremented each time, so it will count up in seconds.
*/
void  transmit_data_to_host( void )
{
	static  uint16  counter;      // The number to be output

	usb_putDecimal( counter, 5 ); // Output number as decimal ASCII (write to USB buffer)
	usb_vuart_putchar('\r');      // Output CR, stay on same line
	usb_vuart_flush();            // Transmit the USB buffer contents now
	counter++ ;
}


/*________________________________________________________________________________________*\
*
*  The functions below comprise an extension to the "USB VUART I/O library".
*  These functions implement ASCII formatted output of data to the host PC.
\*________________________________________________________________________________________*/

/*
*  Output NUL-terminated string, i.e. "near" or "idata" char array, in page zero RAM.
*  The string must be stored in the MCU internal RAM page zero (address range 00..FF).
*  Using the compiler Small Memory Model (recommended), variables which are not
*  explicitly declared "far" or "const" will be allocated to page zero RAM.
*
*  Newline (0x0A) is expanded to CR + LF (0x0D + 0x0A) and the USB TX buffer is flushed.
*
*  Called by:  background tasks
*  Entry args: psz = address of NUL-terminated string in page zero RAM.
*  Returns:    --
*  Affects:    --
*/

void  usb_putstr( char * psz )
{
	char   c;

	while ( (c = *psz++) != NUL )
	{
		if ( c == 0x0A )
		{
			usb_vuart_putchar( CR );
			usb_vuart_putchar( LF );
			usb_vuart_flush();
		}
		else   usb_vuart_putchar( c );
	}
}


/*
*  Output 4 LS bits of a byte as Hex (or BCD) ASCII char.
*
*  Called by:  background tasks
*  Entry args: d = value of Hex digit (0 to 0xf)
*  Returns:    void
*  Affects:    --
*/

void  usb_putHexdigit( uint8 d )
{
	d &= 0x0F;
	if ( d < 10 )  usb_vuart_putchar( '0' + d );
	else  usb_vuart_putchar( 'A' + d - 10 );
}


/*
*  Output byte as 2 Hex ASCII chars, MSD first.
*
*  Called by:  background tasks
*  Entry args: b = byte to output
*  Returns:    void
*  Affects:    --
*/

void  usb_putHexbyte( uint8 b )
{
	usb_putHexdigit( b >> 4 );
	usb_putHexdigit( b );
}


/*
*  Output 16-bit word as 4 Hex ASCII chars, MSD first.
*
*  Called by:  background tasks
*  Entry args: uwArg1 = word to output
*  Returns:    void
*  Affects:    --
*/

void  usb_putHexword( uint16 uwArg1 )
{
	usb_putHexdigit( (uint8) (uwArg1 >> 12) );
	usb_putHexdigit( (uint8) (uwArg1 >> 8) );
	usb_putHexdigit( (uint8) (uwArg1 >> 4) );
	usb_putHexdigit( (uint8) (uwArg1 & 0xF) );
}


/*
*  Output a 16-bit unsigned word as an ASCII decimal number.
*  The number of digit places to be output (1 to 5) is specified as a parameter.
*  If the decimal word value is larger than can fit into the number of places
*  specified, then the output will be truncated to the least significant digit(s).
*  If the decimal word value is smaller than can occupy the number of places
*  specified, then the output will be padded with leading 0's.
*
*
*  Called by:  background tasks
*  Entry args: (uint16) uwArg1 = word to output
*              (uint8) ubPlaces = number of digit places to output (1..5)
*  Returns:    void
*  Affects:    --
*/

void  usb_putDecimal( uint16 uwArg1, uint8 ubPlaces )
{
	int8   bPos;
	uint8  aubDigit[5];    /* BCD result, 1 byte for each digit */

	if ( ubPlaces > 5 )  ubPlaces = 5;
	for ( bPos = 4;  bPos >= 0;  --bPos )
	{
		aubDigit[bPos] = uwArg1 % 10;
		uwArg1 /= 10;
	}
	for ( bPos = 5 - ubPlaces;  bPos < 5;  ++bPos )
		usb_putHexdigit( aubDigit[bPos] );
}


/*** end ***/

⌨️ 快捷键说明

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