The EE Compendium - The Home of Electronic Engineering and Embedded Systems Programming

The Home of Electronic Engineering and Embedded Systems Programming

Intel 8051
Microchip PIC
Motorola 6805
Motorola 68HC11
Motorola 68HC12
Rabbit 2000
More Micros...
LCD Project
MP3 Projects
PC Parallel Port
MAX7219
More Projects...
Project Kits
Software
Code Cache
Compilers
Hardware
CAD / CAE
Components
Distributors
Simulation
Test Equipment
Hotsheet  NEW! 
Articles
Books
Career
Consultants
Forums
Free Stuff
Fun Stuff
Magazines
Portals
Project Management 
Product Reviews
Robotics
Misc. Links
Here's a collection of various bite-sized bits of C code that I've written and accumulated over time. This code was written for embedded systems that employed various processors and microcontrollers, using various compilers, but most of it should be fairly portable. If you find anything useful, grab it.

This code is used to communicate via the SPI (Serial Peripheral Interface) on the 68HC11 (but should also work with the 6805). It was written for the IAR compiler, but should work with others. It assumes that the HC11 registers have been defined with their standard names.

There's not much to this. Call SPI_Init() during system initialization. Call SPI_Transfer() to simultaneously send and receive a byte of data. If you want to send only, and ignore the received byte, precede the name of the function with a (void) when you call it, to tell the compiler that you're purposely ignoring the return value.

    /*
    *********************************************************************************************************
    *
    * SPI_Init()
    *
    * Description: SPI initialization function.  SPI_Init() must be called
    *              before calling any other SPI functions.
    * Arguments  : none
    * Returns    : none
    *********************************************************************************************************
    */
    void SPI_Init (void)
    {
      SPCR = 0x5d;    // initialize SPI Control Register
                      //  (7) SPIE = 0 -- disable SPI interrupts
                      //  (6) SPE  = 1 -- enable SPI system
                      //  (5) DWOM = 0 -- normal CMOS outputs (not wired-or)
                      //  (4) MSTR = 1 -- this is the SPI master
                      //  (3) CPOL = 1 -- SCLK is high in idle state
                      //  (2) CPHA = 1 -- data is clocked on rising edge of SCLK
                      //  (1) 0 \ SPI clock rate = E / 4
                      //  (0) 1 /   (500KHz @ 2MHz E clock)
    }
    
    
    /*
    *********************************************************************************************************
    *
    * SPI_Transfer()
    *
    * Description : Transfer data to/from the SPI port
    * Arguments   : data to send
    * Returns     : received data
    *********************************************************************************************************
    */
    unsigned char SPI_Transfer (unsigned char data_out)
    {
      SPDR = data_out;              // send data out spi port
      while (!(SPSR & 0x80));       // wait for transfer to complete
      return = SPDR;                // return data from spi register
    }
    
    

This code is used to convert an unsigned long (32 bits) to an ASCII string suitable for displaying. It is intended as a replacement for the standard library ltoa() function, for cases where your compiler doesn't supply it, or it's slow and/or fat. This code was written for the 68HC11 and the IAR compiler, but should be fairly generic.

Call long_to_string() to convert a long to a string, with leading zeros suppressed. If you want leading zeros, use long_to_string_lz(). These two functions could be combined into a single function, but it would require an extra parameter. Be sure to allocate enough space for the resulting string before calling these functions. Failure to do so will cause bad things to happen.

    /*
    *********************************************************************************************************
    * long_to_string()
    *
    * Description : Convert a "long" to a null-terminated string
    *               (base = decimal)
    * Arguments   : input = number to be converted
    *               str = pointer to string (i.e. display buffer)
    *               numdigits = number of digits to display
    * Returns     : none
    *********************************************************************************************************
    */
    void long_to_string (unsigned long input, char *str, char numdigits)
    {
      char digit;
      char blank = TRUE;
    
      long_to_string_lz(input, str, numdigits);
    
      for (digit=0; digit < numdigits-1; digit++) {
        if (str[digit] == '0') {
          if (blank == TRUE) str[digit] = ' ';
        }
        else {
          blank = FALSE;
        }
      }
    }
    
    
    /*
    *********************************************************************************************************
    * long_to_string_lz()
    *
    * Description : Convert a "long" to a null-terminated string, with leading zeros
    *               (base = decimal)
    * Arguments   : input = number to be converted
    *               str = pointer to string (i.e. display buffer)
    *               numdigits = number of digits to display
    * Returns     : none
    *********************************************************************************************************
    */
    void long_to_string_lz (unsigned long input, char *str, char numdigits)
    {
      char digit;
    
      for (digit=numdigits; digit > 0; digit--) {
        str[digit-1] = (input % 10) + '0';
        input = input / 10;
      }
      str[numdigits] = 0;    // null-terminate the string
    }
    
    

This code is used to convert an unsigned integer (16 bits) to an ASCII hexidecimal string suitable for displaying. Note that this only creates the digits -- if you want a leading "0x" or "$", it's up to the calling function to add it. This code was written for the 68HC11 and the IAR compiler, but should be fairly generic.

Be sure to allocate enough space for the resulting string before calling uword_to_hexstring(). Failure to do so will cause bad things to happen.

hexstring_to_uword() is simply the inverse of uword_to_hexstring(). Given a string of hex digits (0-9, A-F, a-f), it converts them intil an unsigned integer. Note that it requires the standard library function isxdigit().

    /*
    *********************************************************************************************************
    * uword_to_hexstring()
    *
    * Description : Convert an unsigned int to a null-terminated string
    *               (base = hexidecimal)
    * Arguments   : input = number to be converted
    *               str = pointer to string (i.e. display buffer)
    *               numdigits = number of digits to display
    * Returns     : none
    *********************************************************************************************************
    */
    void uword_to_hexstring (unsigned int input, char *str, char numdigits)
    {
      char digit;
    
      for (digit=numdigits; digit > 0; digit--) {
        char temp = input % 0x10;
        if (temp <= 0x09)
          str[digit-1] = temp + '0';
        else
          str[digit-1] = temp - 0x0a + 'A';
        input = input / 0x10;
      }
      str[numdigits] = 0;    // null-terminate the string
    }
    
    
    /*
    *********************************************************************************************************
    * hexstring_to_uword()
    *
    * Description : Convert a null-terminated string (base = hexidecimal)
    *               to an unsigned int (16 bits);
    * Arguments   : str = pointer to string
    * Returns     : result
    * Note        : Adapted from a function in the "Snippets" collection, by Bob Stout.
    *********************************************************************************************************
    */
    unsigned int hexstring_to_uword (char *str)
    {
      unsigned int i, j = 0;
    
      while (str && *str && isxdigit(*str)) {
        i = *str++ - '0';
        if (9 < i)
          i -= 7;
        j <<= 4;
        j |= (i & 0x0f);
      }
      return(j);
    }
    
    

Refer to the LCD Project page for a nifty little project to control a character-mode LCD from the PC printer port. It includes a schematic and code. The code was written for Borland C, but should be easily adaptable for most compilers. I'm using essentially the same code in an HC11 project, to control a 4x20 LCD.

The Maxim MAX7219 is an LED display driver that can control up to 64 individual LEDs, or eight 7-segment LED digits, or any combination of individual LEDs and digits, connected in a matrix of eight rows and eight columns. It frees the host from the chore of constantly multiplexing the 8 rows and 8 columns.

Visit the MAX7219 Project page for details and the source code.

Xicor offers a number of interesting and useful memory devices, including a line of serial EEPROMs and SerialFlash memories, which communicate using SPI-compatible signals. These routines implement a driver for the X25xxxx series of devices.

Visit the Xicor25 Driver page for details and the source code.

While not strictly an embedded application, the standard PC printer port is handy for testing and controlling devices. It provides an easy way to implement a small amount of digital I/O.

Visit the Parallel Port page for details and the source code.

Disclaimer
There is no warranty, either expressed or implied, with respect to the code contained on this page, it's quality, performance, or fitness for any particular purpose. All code is offered "as is". I am not responsible for what you do with the code (or what the code does to you). In other words, you're on your own ...

Also, I make no claims that this is great code. There are nearly always better and/or different ways to do things. These routines work for me, but your mileage may vary ...

 
Home About This Site Add URL Contact Us Privacy Link To Us Search What's New?

—   T H E   E E   C O M P E N D I U M   —
Copyright © 2008 by EE Compendium, Last Update: Wednesday, 09/06/06