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

📄 eval_rtos.c

📁 C89c51 usb驱动程序,实现了usb转串口的功能,提供了一个虚拟的串口
💻 C
📖 第 1 页 / 共 3 页
字号:
	{
		bMode = habLEDannuncMode[ubLEDident] & ~0x38;
		habLEDannuncMode[ubLEDident] = bMode | ((ubPeriod << 3) & 0x38);
		bMode = habLEDannuncMode[ubLEDident] & ~7;
		habLEDannuncMode[ubLEDident] = bMode | (ubDuty & 7) | 0xC0;   // bit7 = bit6 = 1
	}
}


/*****
*   Function:  SetLEDoutput()
*   Called by:  LED_Refresh()
*
*   Low-level hardware-dependent device I/O function which sets LED driver
*   output port bit(s) according to the specified LED state (argument values).
*   This driver is not intended to be called directly from application code.
*
*   The driver is customised to suit the hardware platform, in this example, it is
*   customised to suit the AT89C5131 Evaluation Board (Atmel Starter Kit AT89STK-05),
*   except that only 2 LEDs, LED_0 and LED_1, are supported in this firmware version.
*   (MCU pins P3.6 and P3.7 may be utilised for other purposes.)
*   Number of LEDs and their function depends on target hardware platform.
*   (NB: LED colours on the Author's development board may not be the same as AT89STK.)
*
*   Args:  bLEDidx   = LED identifier (enumerated -- see eval_defs.h)
*          yLEDstate = 0 (LED off) or 1 (LED on)
*/
void
SetLEDoutput( uint8 bLEDidx, bool yLEDstate )
{
	if ( bLEDidx == LED_0 )
	{
		if ( yLEDstate == 0 ) Set_Bit( P3, BIT3 );    // LED off
		else  Clear_Bit( P3, BIT3 );                  // LED on
	}
	else if ( bLEDidx == LED_1 )
	{
		if ( yLEDstate == 0 ) Set_Bit( P3, BIT5 );
		else  Clear_Bit( P3, BIT5 );
	}
}



/************************************  SPI SUPPORT  **************************************
*
*   Function:  initialise_SPI
*
*   Sets up the on-chip SPI controller to interface with shift registers on the I/O port 
*   expansion board. (Refer to schematics included in 'C5131 EVAL' distribution package.)
*   The 8-bit input port is implemented with a CD4021B (Parallel In, Serial Out, shift reg.)
*   The 8-bit output port is implemented with a CD4094B (Serial In, Parallel Out, shift reg.)
*   A spare MCU output pin is used as "SPI slave latch/load" signal (P1.4 = SPI_SSL).
*
*   SPI clock rate is Fosc/32 = 500kHz (@ Fosc=16MHz, X2): SPCON bits 7,1,0 = 1,0,0.
*   Transmission Format 'A' (CPHA = 0): SPCON bit 2 = 0.
*   The clock signal is inverted by hardware, so to get a rising (+) edge at the capture
*   point, CPOL = 1, i.e. SPCON bit 3 = 1.   MCU is SPI master:  SPCON bit 4 = 1;
*   Disable the MCU SS# input: SPCON bit 5 = 1;  SPI is enabled: SPCON bit 6 = 1;
*   Thus, SPCON = 1111 1000 = 0xF8.
*/
void
initialise_SPI( void )
{
	SPCON = 0xF8;
	Set_Bit( P1, BIT4 );        // SPI_SSL# = LOW (hardware inversion)
}


/*
*   Function:  SPI_output
*
*   Sends a byte (bData) to the Test Jig output shift register and latches the data.
*   The data bits are inverted by hardware, so must be inverted here also.
*/
void
SPI_output( uint8  bData )
{
	SPDAT = ~bData;                 // Start SPI cycle (write output data)
	while ( Test_Bit( SPSTA, BIT7 ) == 0 )    // wait for data exchange done (SPIF==1)
		;;;  
	Clear_Bit( P1, BIT4 );          // Pulse SPI_SSL# = HIGH (latch output SR data)
	Set_Bit( P1, BIT4 );
}


/*
*   Function:  SPI_input
*
*   Reads a byte from the Test Jig input shift register and returns the data.
*   The data bits are inverted by hardware, so must be inverted here also.
*/
uint8
SPI_input( void )
{
	Clear_Bit( P1, BIT4 );          // Pulse SPI_SSL# = HIGH (capture input SR data)
	Set_Bit( P1, BIT4 );
	SPDAT = 0xFF;                   // Start SPI cycle (write dummy data)
	while ( Test_Bit( SPSTA, BIT7 ) == 0 )    // wait for data exchange done (SPIF==1)
		;;;  
	return  ~SPDAT;
}



/******************************  EEPROM LOW-LEVEL DRIVERS  *******************************
*
*   These functions are designed to suit the AT89c5131 MCU on-chip data EEPROM (1kB).
*   It is assumed that persistent data to be stored in EEPROM has a working copy in ERAM.
*   A background task should be created for the purpose of backing up persistent data
*   (i.e. copy from ERAM to EEPROM); the task being invoked whenever a persistent variable
*   (buffered in ERAM) is modified.
*
*
*   Function:  eeprom_read_byte
*
*   Returns a byte from EEPROM at the given address.
*   The address is not bounds checked.
*
*   Arg's:     (uint16) uwAddr = address of byte relative to EEPROM start (0)
*   Returns:   (uint8)  EEPROM byte at uwAddr
*/
uint8
eeprom_read_byte( uint16 uwAddr )
{
	uint8  bData;

	EECON = 0x02;                      /* Map EEPROM into xdata address space */
	bData = *(far uint8 *)uwAddr;      /* Fetch byte from EEPROM */
	EECON = 0;                         /* Map ERAM into xdata address space */
	return  bData;
}


/*
*   Function:  eeprom_read_data
*
*   Copies a specified number of bytes from MCU EEPROM to Extended RAM.
*   The function must not be called while the EEPROM is busy, i.e. while a programming
*   cycle is in progress. This condition can be tested by a call to eeprom_busy().
*
*   Arg's:  (far uint8 *) phbEEPROMptr = address of first byte in EEPROM (source)
*           (far uint8 *) phbERAMptr   = address of first byte in ERAM (destination)
*           (uint8)  bByteCount  =  number of bytes to be copied (max. 255)
*/
void
eeprom_read_data( far uint8 * phbEEPROMptr, far uint8 * phbERAMptr, uint8 bByteCount )
{
	uint8  bData;

	while ( bByteCount-- != 0 )
	{
		EECON = 0x02;               /* Map EEPROM into xdata address space */
		bData = *phbEEPROMptr++;    /* Fetch byte from EEPROM */
		EECON = 0;                  /* Map ERAM into xdata address space */
		*phbERAMptr++ = bData;      /* Copy data byte to ERAM */
	}
}


/*
*   Function:  eeprom_write_data
*
*   Copies a specified number of bytes from Extended RAM to MCU EEPROM "column latches"
*   in preparation for subsequent programming into the EEPROM array.
*   The data bytes to be written must all reside in the same EEPROM page (128 bytes max.)
*   The function must not be called while the EEPROM is busy, i.e. while a programming
*   cycle is in progress. This condition can be tested by a call to eeprom_busy().
*   The function does NOT initiate an EEPROM programming cycle; this is done by a call to
*   eeprom_start_prog().
*
*   Arg's:  (far uint8 *) phbEEPROMptr = address of first byte in EEPROM (destination)
*           (far uint8 *) phbERAMptr   = address of first byte in ERAM (source)
*           (uint8)  bByteCount  =  number of bytes to be programmed (max. 128)
*/
void
eeprom_write_data( far uint8 * phbEEPROMptr, far uint8 * phbERAMptr, uint8 bByteCount )
{
	uint8  bData;

	while ( bByteCount-- != 0 )
	{
		bData = *phbERAMptr++;      /* Fetch byte from ERAM */
		EECON = 0x02;               /* Map EEPROM into xdata address space */
		*phbEEPROMptr++ = bData;    /* Copy data byte to EEPROM */
		EECON = 0;                  /* Map ERAM into xdata address space */
	}
}


/*
*   Function:  eeprom_busy
*
*   Returns TRUE if an EEPROM programming cycle is in progress, else FALSE.
*/
bool
eeprom_busy( void )
{
	return ( Test_Bit( EECON, BIT0 ) );
}


/*
*   Function:  eeprom_start_prog
*
*   Starts an EEPROM programming cycle.
*/
void
eeprom_start_prog( void )
{
	EECON = 0x50;
	EECON = 0xA0;
}



/********************  MISC. CHARACTER/DIGIT CONVERSION FUNCTIONS  **********************/
/*
*  Convert Hex ASCII char (arg) to 4-bit value (returned as unsigned byte).
*
*  Called by:  various, background only
*  Entry args: c = Hex ASCII character
*  Returns:    0xFF if arg is not hex, else unsigned byte ( 0 to 0x0f )
*  Affects:    --
*/

uint8
hexctobin( char c )
{
	if ( c >= '0'  &&  c <= '9')
		return ( c - '0' );
	else if ( c >= 'A'  &&  c <= 'F' )
		return ( c - 'A' + 10 );
	else if ( c >= 'a'  &&  c <= 'f' )
		return ( c - 'a' + 10 );
	else
		return 0xFF ;
}


/*
*  Convert Hex ASCII string, up to 4 digits, to 16-bit unsigned word.
*  The string must be stored in the "idata" area (MCU register file).
*  There cannot be any leading white space.
*  Conversion is terminated when a non-Hex char is found.
*
*  Entry args: (char *) pac = pointer to first char of "near" char array.
*  Returns:    Unsigned 16bit word ( 0 to 0xffff ).
*              If the target string (1st char) is non-Hex, returns 0.
*  Affects:    --
*/
uint16
hexatoi( char * pac )
{
	uint8   ubDigit, ubCount;
	uint16  uwResult = 0;

	for ( ubCount = 0;  ubCount < 4;  ubCount++ )
	{
		if ( (ubDigit = hexctobin( *pac++ )) == 0xFF )
			break;
		uwResult = 16 * uwResult + ubDigit;
	}
	return  uwResult;
}


/*
*  Convert decimal ASCII char to 4-bit BCD value (returned as unsigned byte).
*
*  Called by:  various, background only
*  Entry args: c = decimal digit ASCII encoded
*  Returns:    0xFF if arg is not a decimal digit, else unsigned byte (0..9)
*  Affects:    --
*/
uint8
dectobin( char c )
{
	if ( c >= '0'  &&  c <= '9')
		return ( c - '0' );
	else
		return 0xFF ;
}


/*
*  Convert decimal ASCII string, up to 5 digits, to 16-bit unsigned word.
*  The string must be stored in the "idata" area (MCU register file).
*  There may be leading zeros, but there cannot be any leading white space.
*  Conversion is terminated when a non-decimal char is found, or when the
*  specified number of characters has been processed.
*
*  Entry args: (char *) pac = pointer to first char of "near" char array
*              (int8)  bNdigs = number of characters to process (max. 5)
*  Returns:    Unsigned 16bit word ( 0 to 0xffff ).
*              If the target string (1st char) is non-numeric, returns 0.
*  Affects:    --
*/
uint16
decatoi( char * pnac, int8 bNdigs )
{
	uint8   ubDigit, ubCount;
	uint16  uwResult = 0;

	for ( ubCount = 0;  ubCount < bNdigs;  ubCount++ )
	{
		if ( (ubDigit = dectobin( *pnac++ )) == 0xFF )
			break;
		uwResult = 10 * uwResult + ubDigit;
	}
	return  uwResult;
}


/*
*  Convert decimal ASCII string, up to 12 digits, to 32-bit unsigned long word.
*  The string must be stored in the "idata" area (MCU register file).
*  There may be leading zeros, but there cannot be any leading white space.
*  Conversion is terminated when a non-decimal char is found, or when the
*  specified number of characters has been processed.
*
*  Entry args: (char *) pac = pointer to first char of "near" char array
*              ubNdigs = number of characters to process (max. 5)
*  Returns:    Unsigned long (32 bit) word ( 0 to 0xffffffff ).
*              If the target string (1st char) is non-numeric, returns 0.
*  Affects:    --
*/
uint32
long_decatoi( char * pac, int8 bNdigs )
{
	uint8   ubDigit, ubCount;
	uint32  ulResult = 0L;

	for ( ubCount = 0;  ubCount < bNdigs;  ubCount++ )
	{
		if ( (ubDigit = dectobin( *pac++ )) == 0xFF )
			break;
		ulResult = 10L * ulResult + (long)ubDigit;
	}
	return  ulResult;
}


/*
*  Test ASCII char (arg) for valid hex digit.
*  Returns:    FALSE if arg is not a hex digit, else TRUE
*  Affects:    --
*/
bool
isHexDigit( char c )
{
	if ( c >= '0'  &&  c <= '9')
		return TRUE;
	if ( c >= 'A'  &&  c <= 'F' )
		return TRUE;
	if ( c >= 'a'  &&  c <= 'f' )
		return TRUE;
	else
		return FALSE ;
}


/*****
*   PSUEDO-RANDOM SEQUENCE GENERATOR
*
*	This is a faster algorithm than the one commonly used in C libraries,
*	but it is not quite as random nor does it have as uniform spread of results.
*   To randomise the sequence, seed with a free-running hardware timer.
*
*	Input args:	uwRandom16 = (unsigned) seed
*/
static  uint16  uwRandom16;

void
srand( uint16 wSeed16 )
{
	uwRandom16 = wSeed16;
}


uint16
rand( void )
{
	uwRandom16 = 0 - (uwRandom16 * 995 + 12345);

	return  uwRandom16;
}


/*
*   Fetch program code byte at specified address.
*
*   Arg(s):   (uint16) uwAddr   = program address (passed in R4(msb),R5(lsb))
*   Returns:  (uint8)  bPeekVal = program byte (returned in R3)
*
*   Note:  It is possible to access program code memory using a "pointer to const", e.g:
*              const  uint8 * pkbCodeFetchPtr;
*              ...
*
*              bPeekVal = *pkbCodeFetchPtr;
*
*          Hence, the function peek_code_byte() could be replaced by a macro, i.e:
*
*          #define  peek_code_byte(addr)  (*(const uint8 *)(addr))
*
*          The pointer method cannot access program code memory below 0x0100. The compiler
*          is designed to access idata memory (IRAM) if the pointer value is below 0x0100.
*
*   The inline assembler function given here is designed to work with Hi-Tech C-8051 Rev 9.x.
*/
uint8  
peek_code_byte( uint16 uwAddr )
{
	uint8  bPeekVal;   // should be register R2
	
	asm(" MOV DPH, R4 "    );
	asm(" MOV DPL, R5 "    );
	asm(" CLR A "          );
	asm(" MOVC A, @A+DPTR ");
	asm(" MOV R2, A "      );
	
	return bPeekVal;
}


/*** eof ***/

⌨️ 快捷键说明

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