LUFA, Atmega32u4, TWI, SCL and SDA stay flatlined

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have wired D0 (SCL) and D1 (SDA) to 5V through 4.7 kOhm pull-up resistors.

I turn on TWI:

void setup_twi() {
    TWI_Disable();
    PORTD |= 0x3; 
    DDRD |= 0x3;
    TWI_Init(TWI_BIT_PRESCALE_1, TWI_BITLENGTH_FROM_FREQ(1, 400000));
}

Unfortunately, the SDA and SCL lines just stay low. Any attempt to transmit on the bus with TWI_StartTransmission() fails to make them budge.

Here's some code from the state machine I run to transmit data, although I'd be happy if just the setup code made the SDA and SCL stay high...

void service_twi(void) {
    switch (twi_state) {
    case tsIdle:
        if (TWI_StartTransmission((TWI_ID_MOTOR << 1) | TWI_BIT_WRITE, 2) != TWI_ERROR_NoError) {
            twi_error();
            twi_state = tsEndedMotor;
            break;
        }
        twi_state = tsStartedMotor;
        memcpy(twibuf, motorpower, sizeof(motorpower));
        sndcnt = 0;
        sndend = (unsigned char)sizeof(motorpower);
        break;
    case tsStartedMotor:
        if (sndcnt == sndend) {
            TWI_StopTransmission();
            twi_state = tsEndedMotor;
            break;
        }
        else {
            if (!TWI_SendByte(twibuf[sndcnt])) {
                twi_error();
                twi_state = tsEndedMotor;
                break;
            }
            ++sndcnt;
        }
        break;
...

I've read chapter 20 of the data sheet, and compared to the code in LUFA/Drivers/Peripheral/AVR/TWI_AVR8.c and it seems to match up.

So, what am I doing wrong?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Turns out, I was doing two things wrong:

1) The jumper that was supposed to power the pull-up on this end was not installed. (Durr!)

2) After fixing this, the receiving end (an Atmega328p) and sending end were having start-up sequencing issues, where the TWI state machine would just jam. Adding a timeout and resetting the TWI if heard nothing for a little while fixed that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jwatte wrote:

PORTD |= 0x3;
DDRD |= 0x3; 

As it turns out, there's more.

You really are not allowed to set the TWI pins as high outputs at no time at all. Ever.

I do not recommend setting them as low outputs either.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The regular IO pin driver for the port is actually completely disconnected when the TWI is enabled.
So the settings of PORTD/DDRD won't have any effect on the SCL and SDA pins.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

atomicdog wrote:
The regular IO pin driver for the port is actually completely disconnected when the TWI is enabled.
So the settings of PORTD/DDRD won't have any effect on the SCL and SDA pins.

True.

But it is still wrong to configure the GPIO ports incorrectly before the TWI module is enabled to take control of those pins.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, don't configure them as outputs. Explicitly configure them as inputs instead so that the pullups can do their job.

I've had problems when pinging i2c devices when the r/w bit was wrong, i.e. When pinging a device in read mode when it would only accept a write ping, even if the datasheet stated something different. It happens that the device just acks and stretches the clock until power is cycled.

I tend to post off-topic replies when I've noticed some interesting detail.
Feel free to stop me.