📄 eval_rtos.c
字号:
{
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 + -