Hello, I built a circuit which includes a
bq2013h battery gas gauge. The IC uses a proprietary communication protocol called HDQ which is very similar to 1-Wire except that it's faster, devices don't send a presence pulse and it transmits words at a time rather than bits at a time. Sadly I had to pick the component with possibly the worst datasheet and app notes TI has ever publish (no, really I mean it!). So I'm having quiet a few issues. A whole word must be sent in a minmum of 190uS, bus is MSB first. As per the datasheet, the slave should pull the line low (there's a 4.7K pull up) once it's received a command register address. But using the code below I never get this ACK from the slave. The only code available anywhere is some weird 8085 asm compiled for a 16CXX PIC and it uses a uart rather than a digital IO.
Two app notes describing the protocol
http://focus.ti.com/lit/an/slua408/slua408.pdfhttp://focus.ti.com/lit/ug/spru688/spru688.pdfThe first one specifies that "If the host implements the HDQ communication using a discrete processor I/O port, the timing of the transmitted HDQ data and the sampling of the received HDQ data depends on the host processor timing of the transitions on the HDQ line."
Which I interpret as "the slave will copy the host's timing as long as the host respects the min/max timings of the slave". Doesn't seem to be the case. The same app note also says "The procedure is to set the UART baud rate to 57,600 with no parity and 2 stop bits. This yields a data word with 11 bits total (start bit, 8 data bits, and 2 stop bits). At a baud rate of 57,600 (17.3 µs per bit), this is a total communication time of 190.9 µs and meets the required HDQ bit
timing of 190 µs minimum." As such, I've assumed that these minimum timing + a little extra should do just fine and that's what is replicated below.
Sadly this got me nowhere. Got anymore ideas? Anyone? Anyone? Buller?
P.S. I thought HDQ was another brand name for 1-Wire (TWI vs I2C) when I choose the IC, but now it's on the
PCB already
uint8_t HDQ::read(uint8_t reg)
{
uint8_t result = 0;
uint8_t maxTries = 255;
uint8_t ii;
// Compute read mask
reg |= HDQ_ADDR_MASK_READ;
HDQ::doBreak();
sbi(*modeReg, pin); // Set pin as output
cbi(*outputReg, pin); // Bring pin low
// Wait the minimum break time
delayMicroseconds(1);
// Bring the pin back high
cbi(*outputReg, pin);
delayMicroseconds(20);
for (ii = 0; ii < 8; ii++)
{
sbi(*outputReg, pin);
delayMicroseconds(5);
// Toggle the pin for this bit, MSB first
if (reg<<ii & B10000000) {
sbi(*outputReg, pin);
}
else {
cbi(*outputReg, pin);
}
delayMicroseconds(15);
}
sbi(*outputReg, pin);
delayMicroseconds(40);
cbi(*modeReg, pin); // Set pin as input
// Wait for the slave to toggle a low
while (_HDQ_readPin() != 0);
Serial.println("Got ACK");
for (ii = 0; ii < 8; ii++)
{
delayMicroseconds(10);
result |= _HDQ_readPin()<<(7 - ii);
delayMicroseconds(10);
}
delayMicroseconds(40);
return result;
}