Support » Tic Stepper Motor Controller User’s Guide »
10. I²C command encoding
As described in Section 8, the Tic’s I²C commands each use one of four formats: quick, 7-bit write, 32-bit write, and block read. This section explains how these four command formats are encoded as sequences of bytes within I²C transfers.
For a reference implementation of this protocol, see the TicI2C class in our Tic Stepper Motor Controller library for Arduino.
Note that most of these formats are compatible with the SMBus protocols of the same names; an exception is the block read command, although an SMBus-compatible workaround can be found in its description below.
The default slave address for the Tic is 0001110b (0x0E in hex; 14 in decimal), but this is a setting (“device number”) you can change. (This setting also determines the Tic’s device number when using the Pololu protocol over TTL serial.)
As specified by the I²C standard, a transfer’s address byte consists of the 7-bit slave address followed by another bit to indicate the transfer direction: 0 for writing to the slave, 1 for reading from the slave. This is denoted by “addr + Wr” and “addr + Rd” below. With the Tic’s default slave address, the address byte is 00011100b (0x1C) for a write transfer and 00011101b (0x1D) for a read transfer.
These symbols are also used in the format descriptions below:
- S: start condition
- P: stop condition
- A: acknowledge (ACK)
- N: not acknowledge (NACK)
Any stop condition followed by a start condition can optionally be replaced with a repeated start condition.
Quick
master: | S | addr + Wr | command | P | ||
Tic: | A | A |
A Quick command sends no data and simply consists of the command byte.
Example: Halt and hold
addr + Wr | command | |||||
master: | S | 0x1C | 0x89 | P | ||
Tic: | A | A |
7-bit write
master: | S | addr + Wr | command | data | P | |||
Tic: | A | A | A |
A 7-bit write command has a single byte of data containing a 7-bit value (the most-significant bit of the data byte is always 0).
Example: Set step mode to 1/8 step
addr + Wr | command | data | ||||||
master: | S | 0x1C | 0x94 | 0x03 | P | |||
Tic: | A | A | A |
32-bit write
master: | S | addr + Wr | command | data1 | data 2 | data 3 | data 4 | P | ||||||
Tic: | A | A | A | A | A | A |
A 32-bit write command has four data bytes following the command byte. These contain the 32-bit value in little-endian order (starting with the least-significant byte).
Example: Set target position to 1,234,567,890
addr + Wr | command | data 1 | data 2 | data 3 | data 4 | |||||||||
master: | S | 0x1C | 0xE0 | 0xD2 | 0x02 | 0x96 | 0x49 | P | ||||||
Tic: | A | A | A | A | A | A |
Write value: 1,234,567,890 = 0x4996 02D2
Block read
master: | S | addr + Wr | command | offset | P | |||
Tic: | A | A | A |
master: | S | addr + Rd | A | … | N | P | |||
Tic: | A | data 1 | data n |
A block read command reads a block of data from the Tic. The offset byte specifies the offset within the data that the response should start at. The master can then read up to 15 bytes of response data from the Tic. Any multi-byte values contained in the response are in little-endian order (starting with the least-significant byte).
Example: Get variable “target position” (32 bits)
addr + Wr | command | offset | ||||||
master: | S | 0x1C | 0xA1 | 0x0A | P | |||
Tic: | A | A | A |
addr + Rd | data 1 | data 2 | data 3 | data 4 | ||||||||
master: | S | 0x1D | A | A | A | N | P | |||||
Tic: | A | 0xD2 | 0x02 | 0x96 | 0x49 |
Read value: 0x4996 02D2 = 1,234,567,890
Unlike the other Tic command formats, the block read command is not compatible with the SMBus protocol of the same name. If your master device is limited to using SMBus protocols, you can do a Tic block read by first using an SMBus “Write Byte” transfer to send the Tic command and offset, then using an SMBus read transfer (e.g. Read Byte, Read Word, or Read 32) to send the same Tic command and get the response data:
Example: Get variable “target position” (32 bits) – SMBus compatible (Write Byte + Read 32)
addr + Wr | command | offset | ||||||
master: | S | 0x1C | 0xA1 | 0x0A | P | |||
Tic: | A | A | A |
addr + Wr | command | |||||
master: | S | 0x1C | 0xA1 | P | ||
Tic: | A | A |
addr + Rd | data 1 | data 2 | data 3 | data 4 | ||||||||
master: | S | 0x1D | A | A | A | N | P | |||||
Tic: | A | 0xD2 | 0x02 | 0x96 | 0x49 |
Read value: 0x4996 02D2 = 1,234,567,890
If you are using a clock speed faster than the standard 100 kHz, you should ensure that no activity happens on the bus for 100 μs after the end of a block read command. Failure to do this could lead to I²C communication issues.
Clock stretching
The Tic uses a feature of I²C called clock stretching, meaning that it sometimes holds the SCL line low to delay I²C communication while it is busy with other tasks and has not gotten around to processing data from the master. This means that the Tic is only compatible with I²C masters that also support clock stretching. It also means that the time to send an I²C command to the Tic is variable, even if you are only writing data and not reading anything.
The Tic only uses clock stretching at most once per byte. It stretches its clock after it receives a matching address byte, after it receives a command/data byte, and after it sends a byte that is not the last byte in a read transfer.
Each time the Tic stretches the clock, it could stretch the clock for as long as 1.5 ms if it is busy running its step planning algorithm, which it does approximately (but never more frequently than) every 5 ms. At other times, the Tic will usually stretch the clock for 150 μs or less, depending on the timing of the I²C bytes and how busy the Tic is performing other tasks.
The “serial response delay” setting can be used to guarantee a minimum amount of clock stretching each time the Tic stretches the clock.