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 reads the version number of the Xtender, blinks an LED connected to GP0 on the Xtender 128 times, then reads and reports the voltage on the AN0 pin of the Xtender. The A/D value is 8 bit and ratio metric to 5 volts (Xtender Supply) so the granularity of the conversion result is 1=0.195 volts.
Consult the data sheet on the Xtender for more details on the control registers and capabilities of the Xtender.
' Sample routines to do I2C on a STAMPII and an Xtender
' Special Thanks to Victor Epand
xtn_dev CON $80 ' address for xtender device 0
xtn_reset CON $9e ' reads current revision and resets xtender
xtn_pins_out CON $9d ' make GP pins outputs as specified by data_byte
xtn_pins_low CON $9b ' make GP pins output a low
xtn_pins_high CON $9c ' make GP pins output a high
xtn_ad_cont CON $82 ' A/D control register
xtn_ad_res CON $82 ' reads from this register are results of last conv.
b var byte ' temp storage for demo program
main_prog:
input si2c_data
input si2c_clk ' initial state
' Show revision of the Xtender and prove communications
debug "Extender Revision:"
addr_byte=xtn_dev
comm_byte=xtn_reset
gosub si2c_read
debug dec data_byte, CR
pause 3000
' Blink a light for a while
addr_byte=xtn_dev
comm_byte=xtn_pins_out
data_byte=%00000001 ' only make GP0 an output
gosub si2c_write
b=128
xtn_blink_lp:
debug "Blinking LED on GP0", CR
comm_byte=xtn_pins_high
gosub si2c_write
pause 50
comm_byte=xtn_pins_low
gosub si2c_write
pause 50
b = b + 1
IF b then xtn_blink_lp
' read channel one of the A/D
debug "Reading A/D channel 0", CR
xtn_adread_lp:
addr_byte=xtn_dev
comm_byte=xtn_ad_cont
data_byte=%00000101 ' channel 0, internal ref, power up
gosub si2c_write
comm_byte=xtn_ad_res
gosub si2c_read
debug "A/D result: "
debug dec data_byte, CR
goto xtn_adread_lp
end
' Simulated Inter-Integrate 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 in0=0 then si2c_rbyte_wt
IF in1=0 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 exit_ack=0 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 addr_byte.bit0=1 then si2c_read_sk
si2c_read_lp:
in_byte=addr_byte
gosub si2c_wbyte
IF exit_ack=0 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