SPI Communication and the LM70

   


The LM70 operates in a continuous temperature conversion mode. In this mode, the LM70 operates as a slave device, accepting communication with a host microprocessor. It is an SPI-compatible device that communicates with the host via three signals: chip select (/CS), serial clock (SC), and bidirectional serial data line (SI/O). Synchronous communication with the LM70 is very simple. Because it continually determines the temperature (continuous conversion mode), the LM70 doesn't require that temperature conversion commands be sent from the host, as do other temperature sensors. Also, the SPI communication bus doesn't support multiple devices; therefore, SPI communication with an LM70 requires no packet formation or address information. An SPI communication consists of the host initiating communication with the assertion of the LM70's /CS line, sending 16 clock pulses while reading the LM70's output on the SI/O signal, and then the host de-asserting the chip select. The LM70 outputs 1 sign bit, 10 temperature bits (most significant bit [MSB] first), 3 high bits, and 2 undefined bits on the falling edge of the serial clock signal. This 11-bit temperature representation is a two's-complement word with a least significant bit (LSB) resolution of 0.25°C.

Let's clarify this temperature value encoding by examining the bits of two examples of temperatures. If the temperature were 25°C, communication with the LM70 would return the binary value 0000 1100 1001 1111, which equals 0x0C9F. The five least significant bits don't contain temperature information, and they affect the magnitude of the temperature value. These bits are removed by dividing the temperature value by 32, which is 25. 0x0C9F divided by 32 is 0x64, which is equal to 100. Each least significant bit corresponds to 0.25°C; therefore, 100 times 0.25°C equals 25°C. If the temperature was 25°C, communication with the LM70 would return the binary value 1111 0011 1001 1111, which equals 0xF39F. Dividing by 32 results in a value of 0xFF9C, which corresponds to 100. 100 times 0.25°C equals 25°C.

The LM70 datasheet1 contains serial bus timing diagrams and switching characteristics. These specifications place an upper limit on communication speed, but that is not a concern in this design. In fact, this design will intentionally slow synchronous communication in order to increase design reliability. Typically, the Project Trailblazer target boards will be located in a communication closet or enclosure. The board's temperature sensor will be close by within about 20 feet to measure outside temperatures, for example. Use of slow synchronous communication enables line drivers to overcome the extra capacitance due to long wire lengths.

A device driver communicating with the LM70 temperature sensor performs five steps:

  1. It initializes serial communication with SC high and /CS high. It enters the start condition by taking /CS low.

  2. It starts data bit transfer by taking SC low. The LM70 then actively drives the SI/O signal with the first bit of information.

  3. It takes SC high and then samples the first data bit on the SI/O signal.

  4. It continues toggling the SC signal and sampling SI/O until 16 bits are received.

  5. It enters the stop condition and terminates communication by taking /CS high.

Connecting the LM70 to the x86 Parallel Printer Port

The LM70 SPI signal lines /CS, SC, and SI/O as well as the power line and the ground (GND) connect directly to the parallel port (see Figure 10.1). The parallel port drives /CS and SC but not SI/O. The LM70 drives the SI/O line, which returns the serial data stream. Because of its continuous conversion mode, there's no need to send data to the sensor.

Figure 10.1. The LM70 temperature sensor connection to the x86 parallel printer port.

graphics/10fig01.gif

TIP

Check your x86 parallel printer port signal voltages before connecting your interface circuits. Some printer ports operate with +5V, and newer motherboards use +3.3V. You may not be able to power your +5V devices from a +3.3V signal. Or you might destroy your +3.3V devices by connecting them to a +5V signal.


The x86 LM70 device driver implements SPI signaling communication by using parallel printer port connections. This driver provides users with temperature data through /proc directory entries. Listing 10.1 shows the LM70_x86.c device driver code.

Listing 10.1 The LM70_x86.c Device Driver
 /*  * LM70_x86 v1.0 11/05/01  * www.embeddedlinuxinterfacing.com  *  * The original location of this code is  * http://www.embeddedlinuxinterfacing.com/chapters/10/  *  * Copyright (C) 2001 by Craig Hollabaugh  *  * This program is free software; you can redistribute it and/or modify  * it under the terms of the GNU Library General Public License as  * published by the Free Software Foundation; either version 2 of the  * License, or (at your option) any later version.  *  * This program is distributed in the hope that it will be useful, but  * WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  * Library General Public License for more details.  *  * You should have received a copy of the GNU Library General Public  * License along with this program; if not, write to the  * Free Software Foundation, Inc.,  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  */ /*  * LM70_x86.c is based on procfs_example.c by Erik Mouw.  * For more information, please see The Linux Kernel Procfs Guide, Erik Mouw  * http://kernelnewbies.org/documents/kdoc/procfs-guide/lkprocfsguide.html  * */ /* LM70_x86  * This device driver demonstrates communication with a LM70 temperature  * sensor using SPI signaling. This routine implements SPI communication  * in software (bit-banging). The driver creates a /proc directory entry  * called /proc/trailblazer/temperature. Scripts can read the current  * temperature from this file.  *  * This device driver communicates with a National Semiconductor  * LM70CIMM-3 MUA08A connected in the following manner.  *  *   Parallel              Temperature  *     Port     Direction    Sensor  *      D0    2      ->      V+   5  *      D1    3      ->      /CS  7  *      D2    4      ->      SC   2  *     GND   25      -       GND  4  *    Select 13     <-       SI/O 1  */ /* gcc -O2 -D__KERNEL__ -DMODULE -I/usr/src/linux/include \ -c LM70_x86.c -o LM70_x86.o */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/delay.h> #include <asm/io.h> #define MODULE_VERSION "1.0" #define MODULE_NAME    "LM70_x86" static struct proc_dir_entry  *tb_dir,                               *temperature_file; #define SPPDATAPORT     0x378 #define SPPSTATUSPORT  (SPPDATAPORT + 1) #define SPPCONTROLPORT (SPPDATAPORT + 2) /* status port bit definitions */ #define SIO             0x10 /* data port bit definitions */ #define VCC             0x01 #define nCS             0x02 #define SC              0x04 /* bit delay time, in usecs */ #define DELAY           140 unsigned char data; #define clkLow()        outb(data & ~SC ,SPPDATAPORT) #define clkHigh()       outb(data |  SC ,SPPDATAPORT) #define assertCS()      outb(data & ~nCS,SPPDATAPORT) #define deassertCS()    outb(data |  nCS,SPPDATAPORT) #define readBit()       (SIO == (inb(SPPSTATUSPORT) & SIO)) /*  * function initializeSensor  * This function initializes the 'data' variable with VCC then  * applies power to the LM70 by writing 'data' to the parallel  * port. The /CS and SC lines are then put in an initialization state.  *  */ void initializeSensor(void) {   data = VCC;   outb(data ,SPPDATAPORT); /* write the data to the parallel port */   clkHigh();               /* clock high and /CS are SPI init state */   deassertCS(); } /*  * function powerdownSensor  * This function removes power from the LM70 by zeroing 'data'  * and writing it to the parallel port. This function is called  * when the device driver module is removed  *  */ void powerdownSensor(void) {   data = 0;   outb(data ,SPPDATAPORT); /* write the data to the parallel port */ } /*  * function getTemperature  * This function perform SPI communications with the LM70. The  * LM70 clocks serial out on the falling edge of the SC signal.  * This routine reads the SI/O line for this serial stream after  * the rising edge of SC signal. The LM70 sends MSB first, this  * routine performs the bit shifts. The signals, SC and /CS, are  * intentionally slowed down to allow settling time on long  * communication lines with extra capacitance.  *  * returns  * getTemperature function returns the temperature in degrees C  * in 1 degree increments  *  * This routine doesn't perform communication error checking or  * reporting.  *  */ int getTemperature(void) {   unsigned char i;   int temperature;   assertCS();     /* enter the start condition */   udelay(DELAY);   temperature = 0;   for (i = 0; i < 16; i++) {     clkLow();     udelay(DELAY);     clkHigh();     udelay(DELAY);     temperature = ((temperature << 1) | readBit());     /* shift the temperature bits then OR the input bit into the LSB */   }   deassertCS(); /*  *  Now we to scale the temperature value. Simply shifting the  *  bits right doesn't perform the correct operation if the  *  temperature is below zero. Shifting introduces 0's into the  *  MSB thus losing the negative sign bit. An integer divide by 32  *  preserves the sign bit and eliminates the last unused 5 bits  *  *  At this point, after the divide by 32. temperature contains  *  the count of LSB bits where 1 LSB equals 0.25C. An additional  *  divide by 4 scales temperature in 1 degree increments.  */   temperature /= 128; /* 32 * 4 = 128 */   return temperature; } /*  * function proc_read_temperature  * This function is called when the user performs a read operation  * on /proc/trailblazer/temperature. This function fills the page  * buffer with a temperature in degrees C.  *  */ static int proc_read_temperature(char *page, char **start, off_t off,                                  int count, int *eof, void *data) . FIXED ch. {   int len, temp;   temp = getTemperature();   len = sprintf(page, "%+d", temp); /* temp * 9 / 5 + 32 here for F */   return len; } /*  * function init_LM70_x86  * This initialization function creates the /proc/trailblazer  * directory and a temperature entry in it then initializes the  * LM70 temperature sensor  *  */ static int __init init_LM70_x86(void) {   int rv = 0; /* Create the trailblazer /proc entry */   tb_dir = proc_mkdir("trailblazer", NULL);   if(tb_dir == NULL) {     rv = -ENOMEM;     goto out;   }   tb_dir->owner = THIS_MODULE; /* Create temperature and make it readable by all - 0444 */   temperature_file = create_proc_entry("temperature", 0444, tb_dir);   if(temperature_file == NULL) {     rv = -ENOMEM;     goto no_temperature;   }   temperature_file->data = NULL;   temperature_file->read_proc = &proc_read_temperature;   temperature_file->write_proc = NULL;   temperature_file->owner = THIS_MODULE;   initializeSensor(); /* everything initialized */   printk(KERN_INFO "%s %s initialized\n", MODULE_NAME, MODULE_VERSION);   return 0; no_temperature:   remove_proc_entry("trailblazer", NULL); out:   return rv; } /*  * function cleanup_LM70_x86  * This clean function powers down the sensor and removes  * the /proc/trailblazer directory and the temperature entry.  */ static void __exit cleanup_LM70_x86(void) {   powerdownSensor();   remove_proc_entry("temperature", tb_dir);   remove_proc_entry("trailblazer", NULL);   printk(KERN_INFO "%s %s removed\n", MODULE_NAME, MODULE_VERSION); } module_init(init_LM70_x86); module_exit(cleanup_LM70_x86); MODULE_AUTHOR("Craig Hollabaugh"); MODULE_DESCRIPTION("Trailblazer LM70_x86"); EXPORT_NO_SYMBOLS; 

The LM70_x86.c device driver contains four main functions:

  • init_LM70_x86 This is the device driver initialization function, which creates the /proc directory entries trailblazer and trailblazer/temperature and then initializes the temperature sensor.

  • proc_read_temperature This function is called whenever the user performs a read operation on /proc/trailblazer/temperature. proc_read_temperature calls getTemperature, which performs the actual SPI communication with the LM70.

  • getTemperature This function communicates with the LM70, scales the 11-bit temperature representation, and returns a value in 1-degree-Celcius increments.

  • cleanup_LM70_x86 This is the device driver cleanup function, which powers down the LM70 and removes the /proc directory entries.

Remember that the LM70 clocks MSB first and then clocks out data bits on the SC falling edge. The SI/O line should be sampled on the SC rising edge. The oscilloscope capture shown in Figure 10.2 shows a bit stream of 0000.1101.1111.1111, which corresponds to 27.75°C. The device driver returns 27°C because the getTemperature function performs an integer division on the value.

Figure 10.2. An oscilloscope capture of SC (top trace) and SI/O (bottom trace) signals during an SPI communication with the LM70.

graphics/10fig02.gif

TIP

The LM70 integrated circuit surface mount packaging has little thermal mass. This means it's very responsive to temperature changes. Merely touching the LM70 affects its temperature reading. You can accurately measure the temperature of an object by gluing the LM70 to it with nonconductive glue.


Here are the commands to compile and get a temperature from an LM70 using tbdev1:

 root@tbdev1[516]: gcc -O2 -D__KERNEL__ -DMODULE \ -I/usr/src/linux/include -c LM70_x86.c  graphics/ccc.gif-o LM70_x86.o root@tbdev1[517]: insmod LM70_x86.o root@tbdev1[518]: cat /proc/trailblazer/temperature +27 root@tbdev1[519]: 

Embedded designs often implement bit-banging routines to communicate with synchronous serial devices. In the interfacing example shown in Listing 10.1, a bit-banging function, getTemperature, communicates with the LM70 that is connected to the x86 parallel printer port. Communication delays can be increased to allow for longer communication signal wires between the host CPU and the temperature sensor.

This example clocks in only 16 temperature data bits. Although it is short, the bit-banging operation requires CPU cycles. Bit-banging operations can be CPU intensive for long serial communication streams. This affects the performance of other programs because the Linux scheduler does not interrupt device driver routines.

Other CPUs can contain dedicated peripherals for synchronous communications, thus alleviating the CPU from having to perform the bit-banging chores. Both the ARM SA-1110 and PowerPC MPC860 contain SPI synchronous communication controllers.

Connecting the LM70 to the MediaEngine

The MediaEngine design allows access to the ARM SA-1110's Serial Port 4 through the J13 connector. Serial Port 4 contains two synchronous serial controllers: the multimedia communication port (MCP) and the SSP. CPU register configuration selects which controller attaches to the pins of Serial Port 4. Selecting neither controller allows these pins to become general input/output (I/O) pins. With general I/O pins, the Project Trailblazer engineers could implement a bit-banging algorithm for the ARM processor, but they don't. The SA-1110's SSP controller supports SPI, which makes it ideal for synchronous communication with the LM70. (See section 11.12.7, "SPP Operation," of SA-1110 Developer's Manual2, for more information on SSP.) Figure 10.3 shows the connection between the MediaEngine and the LM70 temperature sensor.

Figure 10.3. The LM70 temperature sensor connection to the MediaEngine.

graphics/10fig03.gif

The MediaEngine LM70 device driver uses programmed I/O operation. That is, it doesn't use CPU interrupts or direct memory access (DMA). Synchronous communication with the LM70 is short and simple; introducing interrupts and DMA channel usage would add unnecessary complications.

Programmed I/O polling is simple. Prior to SPI communication, the SA-1110 SSP receive first in, first out (FIFO) buffer is cleared. The getTemperature function starts SPI communication and then continuously monitors the SSP busy flag Status Register (SSSR) bit. When SPI communication completes, the busy flag bit is cleared and the SSP Data Register (SSDR) contains the 16-bit temperature reading. Programmed I/O using Serial Port 4 with the SSP controller requires configuring the bits in the following two registers:

  • SSP Control Register 1 (SSCR1) configuration bit settings:

    • Receive FIFO Interrupt Enable (RIE): 0 masks interrupt

    • Transmit FIFO Interrupt Enable (TIE): 0 masks interrupt

    • Loopback Mode (LBM): 0 disables loopback mode

    • Serial Clock Polarity (SPO): 0 holds SC low during idle

    • Serial Clock Phase (SPH): 0 adds 1 clock cycle delay

    • External Clock Select (ECS): 0 uses internal clock

  • SSP Control Register 0 (SSCR0) configuration bit settings:

    • Data Size Select (DSS): 1111 selects 16-bit length

    • Frame Format (FRF): 00 selects Motorola SPI

    • Synchronous Serial Port Enable (SSE): 1 for enable

    • Serial Clock Rate (SCR): 11111111 selects slowest clock

The MediaEngine's LM70_mediaengine.c device driver, shown in Listing 10.2, needs to configure the SA-1110's SSCR1 register with 0x0000 and the SSCR0 register with 1111 1111 1000 1111 (0xFF8F).

Listing 10.2 The LM70_mediaengine.c Device Driver
 /*  * LM70_mediaengine v1.0 11/05/01  * www.embeddedlinuxinterfacing.com  *  * The original location of this code is  * http://www.embeddedlinuxinterfacing.com/chapters/10/  *  * Copyright (C) 2001 by Craig Hollabaugh  *  * This program is free software; you can redistribute it and/or modify  * it under the terms of the GNU Library General Public License as  * published by the Free Software Foundation; either version 2 of the  * License, or (at your option) any later version.  *  * This program is distributed in the hope that it will be useful, but  * WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  * Library General Public License for more details.  *  * You should have received a copy of the GNU Library General Public  * License along with this program; if not, write to the  * Free Software Foundation, Inc.,  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  */ /*  * LM70_mediaengine.c is based on procfs_example.c by Erik Mouw.  * For more information, please see The Linux Kernel Procfs Guide, Erik Mouw  * http://kernelnewbies.org/documents/kdoc/procfs-guide/lkprocfsguide.html  *  */ /* LM70_mediaengine  * This device driver demonstrates communication with a LM70 temperature  * sensor using the SA-1110 SPI controller. The driver uses polled I/O  * by checking the SSSR's busy flag instead of using interrupts.  * The driver creates a /proc directory entry called  * /proc/trailblazer/temperature. Scripts can read the current temperature  * from this file.  */ /* arm-linux-gcc -O2 -D__KERNEL__ -DMODULE -I/usr/src/arm-linux/include \ -c LM70_mediaengine.c -o /tftpboot/arm-rootfs/tmp/LM70_mediaengine.o */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/delay.h> #include <asm/io.h> #define MODULE_VERSION "1.0" #define MODULE_NAME    "LM70_mediaengine" static struct proc_dir_entry  *tb_dir,                               *temperature_file; /* see 11.12 Intel StrongARM SA-1110 Microprocessor Developer's Manual */ #define SSP          0x80070000 #define SSCR0_OFFSET 0x60 #define SSCR1_OFFSET 0x64 #define SSDR_OFFSET  0x6C #define SSSR_OFFSET  0x74 #define SSPLEN       0x78 /* SSP bits */ #define SPP_RNE      0x04 #define SPP_BSY      0x08 static void *ssp_base; /*  * function getTemperature  * This function performs SPI communications with the LM70  * using programmed I/O (polled mode). Prior to SPI communication,  * the SA-1110 receive FIFO buffer will be cleared. The getTemperature  * function will start SPI communication then continuously monitor the  * SSP busy flag in the SSP Status Register (SSSR). Upon SPI  * communication completion, the SSP Data Register (SSDR) will contain  * the 16-bit temperature reading.  * returns  * All 16 bits are returned, 11 temperature value bits, 3 1 bits  * and 2 undefined bits.  *  * This routine doesn't perform communication error checking or  * reporting.  */ int getTemperature(void) {   unsigned char i;   int temperature, status; /* need to flush the receive FIFO before we start */   for (i = 0; i < 16; i++)   {     status = readw(ssp_base + SSSR_OFFSET); /* read the status register */     if ((status & SPP_RNE) == 0) /* is the receive FIFO empty? */       break;      temperature = readw(ssp_base + SSDR_OFFSET);      /* read the receive FIFO to clear out old stuff */   } /* start SPI communication, need to feed the transmit FIFO a dummy value */   writel(0x00, ssp_base + SSDR_OFFSET); /* now wait until the BSY flag is not set and read the receive FIFO */   for (i = 0; i < 20; i++)   {     status = readw(ssp_base + SSSR_OFFSET); /* read the status register */     if ((status & SPP_BSY) == 0) /* are we still doing an SPI frame? */       break;     udelay(1000); /* wait a little */   }   temperature = readw(ssp_base + SSDR_OFFSET); /* read the receive FIFO */ /* for debugging uncomment the next line */ /*  printk("temp:  i is %d, temperature is 0x%04X\n",i, temperature); */ /*  *  Now we to scale the temperature value. Simply shifting the  *  bits right doesn't perform the correct operation if the  *  temperature is below zero. Shifting introduces 0's into the  *  MSB thus losing the negative sign bit. An integer divide by 32  *  preserves the sign bit and eliminates the last unused 5 bits  *  *  At this point, after the divide by 32. temperature contains  *  the count of LSB bits where 1 lSB equals 0.25C. An additional  *  divide by 4 scales temperature in 1 degree increments.  */   temperature /= 128; /* 32 * 4 = 128 */   return temperature; } /*  * function proc_read_temperature  * This function is called when the user performs a read operation  * on /proc/trailblazer/temperature. This function fills the page  * buffer with a temperature in degrees C.  */ static int proc_read_temperature(char *page, char **start, off_t off,                                  int count, int *eof, void *data) {   int len, temp;   temp = getTemperature();   len = sprintf(page, "%+d\n", temp); /* temp * 9 / 5 + 32 here for F */   return len; } /*  * function init_LM70_mediaengine  * This initialization function creates the /proc/trailblazer  * directory and a temperature entry in it then initializes the  * LM70 temperature sensor  */ static int __init init_LM70_mediaengine(void) {   unsigned int r;   int rv = 0; /* Create the trailblazer /proc entry */   tb_dir = proc_mkdir("trailblazer", NULL);   if(tb_dir == NULL) {     rv = -ENOMEM;     goto out;   }   tb_dir->owner = THIS_MODULE; /* Create temperature and make it readable by all - 0444 */   temperature_file = create_proc_entry("temperature", 0444, tb_dir);   if(temperature_file == NULL) {     rv = -ENOMEM;     goto no_temperature;   }   temperature_file->data = NULL;   temperature_file->read_proc = &proc_read_temperature;   temperature_file->write_proc = NULL;   temperature_file->owner = THIS_MODULE;   ssp_base = ioremap_nocache(SSP,SSPLEN);   printk("ssp_base       = 0x%08X\n",ssp_base); /*  * SSCR1 binary value 0000 0000 0000 0000 = 0x0000  * External Clock Select (ECS),          0 uses internal clock  * Serial Clock Phase (SPH),             0 adds 1 clock cycle delay  * Serial Clock Polarity (SPO),          0 holds SC low during idle  * Loopback Mode (LBM),                  0 disables loopback mode  * Transmit FIFO Interrupt Enable (TIE), 0 masks interrupt  * Receive FIFO Interrupt Enable (RIE),  0 masks interrupt  */   writel(0x0000, ssp_base + SSCR1_OFFSET); /*  * SSCR0 binary value 1111 1111 1000 1111 = 0xFF8F  * Data Size Select (DSS),               1111 selects 16 bit length  * Frame Format (FRF),                   00 selects Motorola SPI  * Synchronous Serial Port Enable (SSE), 1 for enable  * Serial Clock Rate (SCR),              11111111 selects slowest clock  */   writel(0xFF8F, ssp_base + SSCR0_OFFSET); /* read the registers and printout results */   r = readl(ssp_base + SSCR1_OFFSET);   printk("SSCR1          = 0x%04X\n",r);   r = readl(ssp_base + SSCR0_OFFSET);   printk("SSCR0          = 0x%04X\n",r); /* everything initialized */   printk(KERN_INFO "%s %s initialized\n", MODULE_NAME, MODULE_VERSION);   return 0; no_temperature:  remove_proc_entry("trailblazer", NULL); out:  return rv; } /*  * function cleanup_LM70_mediaengine  * This clean function powers down the sensor and removes  * the /proc/trailblazer directory and the temperature entry.  */ static void __exit cleanup_LM70_mediaengine(void) {   iounmap(ssp_base);   remove_proc_entry("temperature", tb_dir);   remove_proc_entry("trailblazer", NULL);   printk(KERN_INFO "%s %s removed\n", MODULE_NAME, MODULE_VERSION); } module_init(init_LM70_mediaengine); module_exit(cleanup_LM70_mediaengine); MODULE_AUTHOR("Craig Hollabaugh"); MODULE_DESCRIPTION("Trailblazer LM70_mediaengine"); EXPORT_NO_SYMBOLS; 

The LM70_mediaengine.c device driver contains four main functions:

  • init_LM70_mediaEngine This is the device driver initialization function, and it creates the /proc directory entries trailblazer and trailblazer/temperature. It then configures the SA-1110's SSCR1 and SSCR0 registers enabling SSP controller operation on Serial Port 4.

  • proc_read_temperature This function is called whenever the user performs a read operation on /proc/trailblazer/temperature. proc_read_temperature calls getTemperature.

  • getTemperature This function uses the SSP controller that communicates with the LM70. The getTemperature function returns a value in 1-degree-Celcius increments.

  • cleanup_LM70_MediaEngine This is the device driver cleanup function, and it removes the /proc directory entries.

The oscilloscope capture shown in Figure 10.4 shows a bit stream of 0000.1011.0011.1111, which corresponds to 22.25°C.

Figure 10.4. An oscilloscope capture of SC (top trace) and SI/O (bottom trace) signals, using the SA-1110 SSP controller for SPI communication with the LM70.

graphics/10fig04.gif

So far the Project Trailblazer engineers have connected the LM70 temperature sensor to the x86 parallel printer port and the MediaEngine's Serial Port 4 with an SSP controller. Synchronous serial signaling permits easy connection of external devices to microprocessors. Communication is simple and fast because there's no need for packet formation or command addressing. Using this type of synchronous serial communication requires a chip select for each external device. CS signals are subject to availability as external SPI device count increases.


       
    Top


    Embedded LinuxR. Hardware, Software, and Interfacing
    Embedded LinuxR. Hardware, Software, and Interfacing
    ISBN: N/A
    EAN: N/A
    Year: 2001
    Pages: 103

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net