Submitted by:
Glenn Clark
VersaTech Electronics
The programs and drawings shown below are taken from the examples section of the manual.
The previous example demonstrated how a TICkit can communicate to an Xtender IC via the TICkit's built in I2C interface. There are many manufacturers of I2C compatible products and not all of them use protocols which are compatible with the TICkit's built in read and write formats. This example deals with one such part. This example connects a TICkit to 8 Dallas DS1621 temperature sensing IC via two TICkit general purpose I/O pins controlled by a TICkit I2C simulating library. This simulated I2C is not nearly as fast as the protocols built into the TICkit, but it will accomplish the communications required fairly quickly, certainly as fast as required by most applications. This program actually implements a complete on-demand temperature acquisition system. A partial schematic for this circuit is shown below. An actual application would probably have additional circuitry connected to the DS1621 ICs.
Notice that the two lines used for the I2C bus are pulled high. This is required by the I2C protocol because multiple sources can drive both the clock and data lines. Also notice how the pins A0, A1, and A2 on each DS1621 are strapped for a different address. This is how each IC knows which I2C address to respond to. The 'A' pins allow the designer to specify 3 of the 7 I2C address pins. The other four are hard coded by the manufacturer of the IC. Some ICs internally specify all 7 address lines and must be ordered with different address (like the Xtender) if more than one will be used on an I2C bus.
The following program is relatively complex for an example. It shows how defines can be used in conjunction with a pre-written library to customize the library for the program. This was done with sim_i2c.lib file to specify which pins to use. We also use the DEF directive to define which pin to communicate with the PC or terminal. In this example, we can use the download socket on the TICkit module with the download cable, except that we use a terminal program like WINTERM instead of the download software. This just makes demonstrating easier. We leave it to the reader to examine the sim_i2c.lib file to see how this all works.
; Program to read the 1621 on command and return the value to a PC ; via a serial port. Simulated I2C routines using GP pins are ; used for this routine because the 1621's protocols are too ; complex for the i2c_read and i2c_write functions. DEF tic62_a LIB fbasic.lib DEF si2c_data pin_a1 ; these are the pins to use for I2C DEF si2c_clk pin_a2 LIB sim_i2c.lib ; this library is un-documented in man. ; but is contained on the release disk. ; The 1621 has three pins for strapping an I2C address. ; This means up to 8 1621 devices can exist on the I2C bus ; and be addressed independently. ; The defines below give the addresses for the 8 devices. ; If a read is to be performed, the lsb of the address must be set. DEF DS1621_dev0 0xA0b DEF DS1621_dev1 0xA2b DEF DS1621_dev2 0xA4b DEF DS1621_dev3 0xA6b DEF DS1621_dev4 0xA8b DEF DS1621_dev5 0xAAb DEF DS1621_dev6 0xACb DEF DS1621_dev7 0xAEb ; The 1621 has a fairly elaborate command system. ; Following the typical I2C device address/control byte, ; an 8 bit command byte is used to inform the 1621 of the ; nature of the data transfer. The commands and associated ; data are listed below: DEF DS1621_temp 0xAAb ; This command reads the temperature of the ; last conversion. The 1621 will send 2 ; bytes(16 bits) unless a stop bit is sent ; after the first byte. The second byte only ; has information in bit 7 because the 1621 ; only converts 9 bits of data. DEF DS1621_t_high 0xA1b ; This read/write 16bit register is used ; to control the Tout pin of the 1621. ; This is the high value used in ; comparisons with actual temp reading. ; If the actual temperature exceeds this ; value, Tout is driven high. DEF DS1621_t_low 0xA2b ; This read/write 16bit register is used ; to control the Tout pin of the 1621. ; This is the low value used in comparisons ; with actual temp reading. If the actual ; temperature is less than this value, ; Tout is driven low. This creates a ; hysterisis region to prevent critical ; oscillations around a single temperature ; set point. DEF DS1621_config 0xACb ; This read/write 8 bit register configures ; the 1621 for operation. The bits below ; explain the config options. DEF DS1621C_done 0y10000000b ; 1= conversion finished. DEF DS1612C_thf 0y01000000b ; 1= The device has exceeded the ; t_high value. This bit is only ; reset by writing the config ; register. This bit is unaffected ; by the temp falling below TH or TL DEF DS1621C_thl 0y00100000b ; 1= The device temp has fallen below ; the t_low value. This bit is only ; reset by writing 0 to it in the ; config register. This bit is not ; affected by the temp exceeding TL ; or TH. DEF DS1621C_NVB 0y00010000b ; 1= 1621 is busy writing data to the ; EEprom. Values written to th or tl ; are stored in non volatile memory ; and writes can require up to 10 ms. DEF DS1621C_pol 0y00000010b ; Output polarity for Tout. 1= a high ; is Vdd. DEF DS1621C_single 0y00000001b ; 1= do a single conversion when ; start is commanded. 0= do ; continuous conversion when ; start is commanded. DEF DS1621_count 0xA8b ; This 8bit register holds the count used ; for temp conversion. This read only ; register can be used for increased ; precision (up to 16bit) DEF DS1621_slope 0xA9b ; This 7bit register holds the slope count ; used for temp conversion. This read only ; register can be used with the count ; register to calculate a more precise ; temperature (up to 16 bit) DEF DS1621_start 0xEEb ; A write to this register starts ; conversions. The config register ; determines if a single conversion ; takes place or if continuous conversions ; will follow. A bit of the config register ; indicates when conversion is complete. DEF DS1621_stop 0x22b ; A write to this register halts continuous ; conversion mode. The current conversion ; will finish then the 1621 will remain ; idle until the next start command. DEF pc_serial pin_a7 ; this is the pin to use to communicate to PC GLOBAL byte rs_command ; this is the command received from PC GLOBAL byte err_val ; error on rs receive GLOBAL byte dev_addr ; computed I2C address for 1621 GLOBAL byte config_read ; value of configuration register ; as read from the specified 1621 GLOBAL word temp_result ; 16 bit result as read from 1621 ALIAS byte temp_high temp_result 1b ; upper byte of result ALIAS byte temp_low temp_result 0b ; lower byte of result GLOBAL byte trash ; dummy variable when making pins inputs FUNCTION none rs_word PARAM word rs_data LOCAL word place 10000w LOCAL word num BEGIN =( num, rs_data ) REPEAT rs_send( +( '0', trunc_byte( /( num, place )))) =( num, %( num, place )) =( place, /(place, 10b )) UNTIL ==( place, 1b ) rs_send( +( '0', trunc_byte( num ))) ENDFUN
FUNC none si2c_comm ; function to start message and send command PARAM byte addr PARAM byte comm LOCAL byte trash BEGIN REP si2c_start() IF si2c_wbyte( addr ) STOP ENDIF si2c_stop() LOOP =( trash, si2c_wbyte( comm )) ENDFUN FUNC none main BEGIN rs_param_set( rs_invert | rs_9600 | pc_serial ) pin_high( si2c_data ) pin_high( si2c_clk ) ; configure 1621 for single conversion on command si2c_comm( ds1621_dev0, ds1621_config ) =( trash, si2c_wbyte( ds1621c_single )) si2c_stop() si2c_comm( ds1621_dev1, ds1621_config ) =( trash, si2c_wbyte( ds1621c_single )) si2c_stop() si2c_comm( ds1621_dev2, ds1621_config ) =( trash, si2c_wbyte( ds1621c_single )) si2c_stop() si2c_comm( ds1621_dev3, ds1621_config ) =( trash, si2c_wbyte( ds1621c_single )) si2c_stop() si2c_comm( ds1621_dev4, ds1621_config ) =( trash, si2c_wbyte( ds1621c_single )) si2c_stop() si2c_comm( ds1621_dev5, ds1621_config ) =( trash, si2c_wbyte( ds1621c_single )) si2c_stop() si2c_comm( ds1621_dev6, ds1621_config ) =( trash, si2c_wbyte( ds1621c_single )) si2c_stop() si2c_comm( ds1621_dev7, ds1621_config ) =( trash, si2c_wbyte( ds1621c_single )) si2c_stop() REP ; wait for a command from PC ( ignore bogus values ) =( rs_command, rs_receive( 0b, 0b, err_val )) IF err_val ELSE IF and( >=( rs_command, 'A' ), <=( rs_command, 'H' )) ; valid command calc I2c address and get readings =( dev_addr, +( 0xA0b, *( 2b, -( rs_command, 'A' )))) si2c_comm( dev_addr, ds1621_start ) ; repeatedly read config until conversion is done REP si2c_comm( dev_addr, ds1621_config ) si2c_stop() si2c_start() =( trash, si2c_wbyte( b_or( dev_addr, ~ ~ 0y00000001b ))) =( config_read, si2c_rbyte( 0b )) si2c_stop() UNTIL b_and( config_read, ds1621c_done ) ; now read the conversion results si2c_comm( dev_addr, ds1621_temp ) si2c_stop() si2c_start() =( trash, si2c_wbyte( b_or( dev_addr, 0y00000001b ))) =( temp_high, si2c_rbyte( 0xffb )) =( temp_low, si2c_rbyte( 0b )) si2c_stop() ; now compute result into a normalized 16 bit number ; and send result to PC with a return at the end. =( temp_result, /( temp_result, 128b )) rs_word( temp_result ) rs_send( '\r' ) ENDIF ENDIF LOOP ENDFUN
Protean Logic Inc. Copyright 05/06/04 Top of Page