Submitted by:
Glenn Clark
VersaTech Electronics
Parallax's Basic STAMP II has proved to be a very capable processor for a wide variety of tasks. Often STAMP based products require additional I/O capabilities, or the ability to perform tasks in background while it continues processing a foreground task. The I2C Xtender 73, made by Protean Logic Inc., can provide these capabilities with a minimum of additional components.
The Xtender can converter analog inputs to 8bit values for measuring voltages, etc. It can also generate PWM signals for motor control or servo control. It can count input pulses for measuring frequencies or RPM. It can control a stepper motor. It has 8 additional general purpose I/O pins. It has 128 bytes of RAM memory. And it can send and receive RS232 serial data.
The sample code below will not actually perform any useful task. It is simply a collection of two routines for writing to and reading from the Xtender IC. The trick here is to make these subroutines small enough to still have a useful amount of BS2 RAM and program space left.
When you use the si2c_write routine, simply assign an 8 bit address to the variable addr_byte, an 8 bit command to the variable comm_byte, and an 8 bit data value to the variable data_byte then execute: GOSUB si2c_write.
When you use the si2c_read routine, simply assign an 8 bit address to the variable addr_byte, an 8 bit command to the variable comm_byte and execute: GOSUB si2c_read. The variable data_byte will contain the 8 bit value read from the Xtender IC.
With these two routines you can use any of the resources on the Xtender device. These subroutines use 5 bytes and 2 bits of the STAMP's RAM, and 218 EEprom bytes. Which leaves approximately 20 bytes and 6 bits of RAM and 1830 EEprom bytes for your application to use.
The following application notes give actual working code samples for utilizing some of the Xtender with a STAMP II.
' Sample routines to do I2C on a STAMPII ' Special Thanks to Victor Epand ' Simulated Inter-Integrated Circuit driver (si2c) ' This driver consists of two internal routes (si2c_wbyte and si2c_rbyte) ' and two user functions (si2c_write and si2c_read) ' the si2c_write function needs three byte parameters: ' addr_byte: the i2c address of the device writing to ' comm_byte: the sub command to tell the device what to do ' data_byte: the byte of data to use for the command ' ' the si2c_read function needs two parameters and returns a byte: ' addr_byte: the i2c address of the device reading from ' comm_byte: the sub command to tell the device what to read ' data_byte: the value returned from the device that was read ' This routine used pin 0 as the I2C clock pin and pin 1 as the I2c data pin ' Both of these pins must be pulled high. Both of these pins should initially ' be configured as inputs at power up. si2c_clk CON 0 ' I/O pin for I2C Clock line ' IN0 is used in some situations si2c_data CON 1 ' I/O pin for I2C data line ' IN1 is used in some situations ' the following are the storage required by the si2c routines. in_byte VAR byte ' used internally by the si2c_wbyte function bit_count VAR byte ' used internally by both the si2c_wbyte and rbyte send_ack VAR bit ' used to tell rbyte if it should ack or not exit_ack VAR bit ' used to indicate if wbyte got an ack or not data_byte VAR byte ' either the data to be written or the data just read addr_byte VAR byte ' address of I2C device (LSB=read indicator) comm_byte VAR byte ' I2C sub command si2c_wbyte: ' returns 1 if successful, 0 = NACK ' in_byte is byte to be written bit_count=%10000000 si2c_wbyte_lp: low si2c_clk input si2c_data IF (bit_count & in_byte) then si2c_wbyte_do1 low si2c_data si2c_wbyte_do1: bit_count=bit_count>>1 input si2c_clk IF bit_count then si2c_wbyte_lp ' now test the acknowledge bit low si2c_clk input si2c_data input si2c_clk exit_ack=0 IF in1 then si2c_wbyte_ex exit_ack=1 si2c_wbyte_ex: return si2c_rbyte: ' send_ack is set for a post ack or not bit_count=%10000000 low si2c_clk data_byte=0 input si2c_data si2c_rbyte_lp: input si2c_clk si2c_rbyte_wt: IF NOT in0 then si2c_rbyte_wt IF NOT in1 then si2c_rbyte_dl data_byte=data_byte|bit_count si2c_rbyte_dl: low si2c_clk bit_count=bit_count>>1 IF bit_count then si2c_rbyte_lp ' send ack bit if required low si2c_data IF send_ack then si2c_rbyte_ak input si2c_data si2c_rbyte_ak: input si2c_clk return si2c_write: ' must set addr, comm, and data before calling low si2c_data ' generate a start bit si2c_write_lp: in_byte=addr_byte gosub si2c_wbyte IF NOT exit_ack then si2c_write_lp in_byte=comm_byte gosub si2c_wbyte in_byte=data_byte gosub si2c_wbyte low si2c_clk ' generate stop bit low si2c_data input si2c_clk input si2c_data return si2c_read: ' must set addr, comm, data_byte will have return low si2c_data ' generate a start bit IF NOT (%00000001 & addr_byte) then si2c_read_sk si2c_read_lp: in_byte=addr_byte gosub si2c_wbyte IF NOT exit_ack then si2c_read_lp in_byte=comm_byte gosub si2c_wbyte low si2c_clk low si2c_data input si2c_clk input si2c_data ' generate the stop low si2c_data ' generate a start addr_byte=addr_byte-1 si2c_read_sk: in_byte=addr_byte gosub si2c_wbyte send_ack=0 gosub si2c_rbyte low si2c_clk low si2c_data input si2c_clk input si2c_data ' generate the stop bit return
Protean Logic Inc. Copyright 05/06/04 Top of Page