Anyone Tried the Example I2C (TWI) Code in Studio?

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

I'm using a MEGA328PB and used the Atmel START utility to configure a Studio project, including setting up an I2C bus. Trying to talk to another device with I2C, but when emulating via debugWIRE in Studio I keep getting timeouts when attempting to close the I2C connection. 

Here's the attempt to write:

i2c_error_t I2C_0_writeNBytes(i2c_address_t address, void *data, size_t len)
{
	/* timeout is used to get out of twim_release, when there is no device connected to the bus*/
	uint16_t timeout = I2C_TIMEOUT;

	while (I2C_BUSY == I2C_0_open(address) && --timeout)
		; // sit here until we get the bus..
	if (!timeout)
		return I2C_BUSY;    //Times out here subsequent times through
	I2C_0_set_buffer(data, len);
	I2C_0_set_address_nack_callback(i2c_cb_restart_write, NULL); // NACK polling?
	I2C_0_master_write();
	timeout = I2C_TIMEOUT;
	while (I2C_BUSY == I2C_0_close() && --timeout)
		; // sit here until finished.
	if (!timeout)
		return I2C_FAIL;    //Times out here first time through

	return I2C_NOERR;
}

Here's the code for closing:

i2c_error_t I2C_0_close(void)
{
	i2c_error_t ret = I2C_BUSY;

	if (!I2C_0_status.busy) {
		I2C_0_status.inUse = 0;
		// close it down
		I2C_0_status.address = 0xff; // 8-bit address is invalid so this is FREE
		// Clearing INT flag starts operation
		TWCR0 |= (1 << TWINT);
		TWCR0 &= ~(1 << TWIE);
		ret = I2C_0_status.error;
	}
	return ret;
}

Here's where it inits:

void I2C_0_init()
{

	/* Enable TWI0 */
	PRR0 &= ~(1 << PRTWI0);

	TWCR0 = (1 << TWEN)   /* TWI0: enabled */
	        | (1 << TWIE) /* TWI0 Interrupt: enabled */
	        | (1 << TWEA) /* TWI0 Acknowledge: enabled */;

	/* SCL bitrate = F_CPU / (16 + 2 * TWBR0 * TWPS value) */
	/* Configured bit rate is 400.000kHz, based on CPU frequency 12.000MHz */
	TWBR0 = 0x07;          /* SCL bit rate: 400.000kHZ before prescaling */
	TWSR0 = 0x00 << TWPS0; /* SCL precaler: 1, effective bitrate = 400.000kHz */
}

 

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

Go on.   What hardware Slave are you using?

 

What value do you put in the "address" argument ?

i.e. 7-bit or 8-bit address ?

 

David.

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

nobbyv wrote:
Trying to talk to another device with I2C

And that device would be.....?

 

nobbyv wrote:

 effective bitrate = 400.000kHz

As most I2C devices don't really care what speed you clock it, start with a slower clock rate 50k-100k, verify you have the correct address for the device and whether your I2C driver expects a 7bit address or 8bit address (one for read and one for write). Then check to see if your actually getting an ACK back to the address used, because until you do, nothing is going to work.

Once you have verified you have the correct address (ACK) try sending data to the device if you can, and see if it ACK's that as well.

Now once that works, try reading data from the device, note I2C protocol says the master MUST NAK the last data byte from a slave so it knows to release the bus back to the master so it can send stop!

As for the h/w what bus pull up resistors are you using and what voltage level is used on the bus?   How long is the bus?

Do you have an Oscope to view the bits, do they have a nice shark fin shape, if not, slow the bus down until it does.

Always check your function call return status, don't blindly call I2C functions with out checking status.

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

david.prentice wrote:

Go on.   What hardware Slave are you using?

 

What value do you put in the "address" argument ?

i.e. 7-bit or 8-bit address ?

 

David.

 

It's a capacitive touch controller from EETI/eGalax (EXC80H84). I have the I2C programming guide for it; it has a 7-bit address and specs 400kHz as the bitrate. 

Last Edited: Wed. Mar 24, 2021 - 08:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:

And that device would be.....?

 

EETI/eGalax capacitive touch controller. 7-bit address, 400KHz comms speed. 

 

ki0bk wrote:

As for the h/w what bus pull up resistors are you using and what voltage level is used on the bus?   How long is the bus?

Do you have an Oscope to view the bits, do they have a nice shark fin shape, if not, slow the bus down until it does.

Always check your function call return status, don't blindly call I2C functions with out checking status.

 

Jim

 

 

4.7k pullups on the bus lines to 3.3V. The bus is about 2cm long. Ironically, I am at the office in another state where I don't have a scope handy, as I usually work from home where I do have one. 

Last Edited: Wed. Mar 24, 2021 - 08:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh,  I love I2C datasheets.   They never tell you what the Slave address actually is !!

 

And nor do you.   The Start functions expect an 8-bit address.   So they will never ACK the 7-bit address (that only you know).

 

David.

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

david.prentice wrote:

Oh,  I love I2C datasheets.   They never tell you what the Slave address actually is !!

 

And nor do you.   The Start functions expect an 8-bit address.   So they will never ACK the 7-bit address (that only you know).

 

David.

 

David,

This one fortunately does give me the addres (0x2A). So to be clear: are you saying the example code won't work for me because it's all written for 8-bit addresses?

Thanks

-Josh

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

If the 7-bit address is 0x2A you will use (0x2A << 1) for write and ((0x2A << 1) + 1) for read.   i.e. 0x54 for SLAVE_W and 0x55 for SLAVE_R.

 

I have only glanced at the code in #1.

You should read any documentation that comes with Start.

 

David.

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

Start? Is there some reason you aren't using Fleury which is the more established choice for I2C on a chip like 328

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


nobbyv wrote:
are you saying the example code won't work for me because it's all written for 8-bit addresses?

There is no such thing as an "8-bit" I2C address - it's just a question of how the API requires you to present the combination of Address (7 bits) + R/W bit:

 

See: https://www.avrfreaks.net/commen... and follow the link.

 

EDIT - the key point from that post:

I wrote:
It's not just about having the right value - you have to know whether it is

  • purely the 7-bit address, right-aligned in a byte;
  • just the 7-bit address, left-aligned in a byte;
  • the 7-bit address, plus the R/W bit, in a byte;
  • or something else ... ?!

 

and that applies both to the hardware documentation, and the software using it.

 

EDIT 2

 

So, pictorially, if the seven address bits are A6..A0, and 'rw' is the R/W bit:

 

  +----+----+----+----+----+----+----+----+
  | A6 : A5 : A4 : A3 : A2 : A1 : A0 |    |   -- just the 7-bit address, left-aligned in a byte
  +----+----+----+----+----+----+----+----+

  +----+----+----+----+----+----+----+----+
  |    | A6 : A5 : A4 : A3 : A2 : A1 : A0 |   -- purely the 7-bit address, right-aligned in a byte
  +----+----+----+----+----+----+----+----+

  +----+----+----+----+----+----+----+----+
  | A6 : A5 : A4 : A3 : A2 : A1 : A0 | rw |   -- the 7-bit address, plus the R/W bit, in a byte
  +----+----+----+----+----+----+----+----+

 

 

18 June 2021: Due to this bug, the forum has mangled the formatting above - here it is without formatting:

  +----+----+----+----+----+----+----+----+
  | A6 : A5 : A4 : A3 : A2 : A1 : A0 :    |   -- just the 7-bit address,   left-aligned in a byte
  +----+----+----+----+----+----+----+----+

  +----+----+----+----+----+----+----+----+
  |    : A6 : A5 : A4 : A3 : A2 : A1 : A0 |   -- purely the 7-bit address, right-aligned in a byte
  +----+----+----+----+----+----+----+----+

  +----+----+----+----+----+----+----+----+
  | A6 : A5 : A4 : A3 : A2 : A1 : A0 : rw |   -- the 7-bit address, plus the R/W bit, in a byte
  +----+----+----+----+----+----+----+----+

What the highlighting was trying to show:

 

 

See also

 

https://www.avrfreaks.net/commen...

 

https://www.avrfreaks.net/commen...

 

https://www.avrfreaks.net/commen...

 

https://www.avrfreaks.net/commen...

 

The Slave Address is, strictly, just the 7 bits circled in blue;  so the address shown in the diagram is 0x27 - not 0x4E

 

The 8th bit - circled in red - is the Read/Write bit

 

 

#I2Caddress #I2CaddressConfusion

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Jun 18, 2021 - 08:40 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


So just to be sure I am understanding correctly, this is the datasheet for a different slave device:

 

 

To perform a write to this slave, the actual hex value I'd want to send is 0x44, correct (the ADDR pin is tied to ground on my board)? And then a read would be 0x45. And yes, now that I've seen a GOOD example of how manufacturers should document their addresses, I agree it's frustrating that some don't do it well at all. I sent an email to eGalax to clarify how the address is stored for the slave I asked about above. 

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

One suggestion, If you don't have one, pick up an Ardunio Uno, and load it up with an I2C bus scanner sketch and use it for any init test of a new I2C slave, let it run and see what address it finds on the bus!

It will save you a bunch of time....

Good luck

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

But you also need to look at the START documentation to see how it requires you to present the address in the I2C_0_open() call - because that could also be 7-btis left- or right-justified, or 8 bits including the R/W.

 

As David said, you need to study the START documentation.

 

(I'd guess that it wouldn't include the R/W - because "open" suggests that you're preparing for either read or write access ... ?)

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Mar 25, 2021 - 06:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:
pick up an Ardunio Uno, and load it up with an I2C bus scanner sketch and use it for any init test of a new I2C slave, let it run and see what address it finds on the bus!

That doesn't help to answer the question of how START needs the address to be presented.

 

So a better idea would be to use the START functions to make an I2C scanner - then you will know what address you need to feed to START to get the Slave to ACK.

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:

One suggestion, If you don't have one, pick up an Ardunio Uno, and load it up with an I2C bus scanner sketch and use it for any init test of a new I2C slave, let it run and see what address it finds on the bus!

It will save you a bunch of time....

Good luck

Jim

 

 

I actually have a I2C/SPI protocol analyzer back at home. Almost forgot!

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

FYI -  When the slave documentation gives you a read address and a write address, that will be a fully qualified 8-bit address. Now, there are devices that use one or more device pins to set the high bits of the address, but there should be a table that shows you various addesses. Again, even in this case, if they give both a read address and a write address, it should be a full 8-bit address.

 

If the documentation calls out a read/write bit separate from the address, then THAT is invariably a 7 bit address.

 

This leaves the I2C/TWI software API. As awneil pointed out, that API can expect full 8-bit addresses, or 7-bit addresses right or left justified in an 8-bit byte. In my perfect mind, full 8-bit addresses are the only "rational" way to go. But, we don't have that luxury in this modern world, it seems.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

Just to be pedantic but when devices have things like A0, A1, A2 address selection pins they are usually setting the lower bits not the higher bits of the address (but still one bit up from the R/W selection bit).

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

You are probably correct. My bad memory looses again!

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

OK, I've been banging my head against this for two days now. It doesn't get much simpler than this:

 

Init the I2C Port Pins:

/* configure pins and initialize registers */
void I2C_0_initialization(void)
{

	PC5_set_dir(
	    // <y> Pin direction
	    // <id> pad_dir
	    // <PORT_DIR_OFF"> Off
	    // <PORT_DIR_IN"> In
	    // <PORT_DIR_OUT"> Out
	    PORT_DIR_OUT);

	PC5_set_level(
	    // <y> Initial level
	    // <id> pad_initial_level
	    // <false"> Low
	    // <true"> High
	    false);

	PC5_set_pull_mode(
	    // <y> Pull configuration
	    // <id> pad_pull_config
	    // <PORT_PULL_OFF"> Off
	    // <PORT_PULL_UP"> Pull-up
	    PORT_PULL_OFF);

	PC4_set_dir(
	    // <y> Pin direction
	    // <id> pad_dir
	    // <PORT_DIR_OFF"> Off
	    // <PORT_DIR_IN"> In
	    // <PORT_DIR_OUT"> Out
	    PORT_DIR_OUT);

	PC4_set_level(
	    // <y> Initial level
	    // <id> pad_initial_level
	    // <false"> Low
	    // <true"> High
	    false);

	PC4_set_pull_mode(
	    // <y> Pull configuration
	    // <id> pad_pull_config
	    // <PORT_PULL_OFF"> Off
	    // <PORT_PULL_UP"> Pull-up
	    PORT_PULL_OFF);

	I2C_0_init();
}

 

Init the I2C port:

void I2C_0_init()
{

	/* Enable TWI0 */
	//PRR0 &= ~(1 << PRTWI0);

	//TWCR0 = (1 << TWEN)   /* TWI0: enabled */
	  //      | (1 << TWIE) /* TWI0 Interrupt: enabled */
	    //    | (1 << TWEA) /* TWI0 Acknowledge: enabled */;

	/* SCL bitrate = F_CPU / (16 + 2 * TWBR0 * TWPS value) */
	/* Configured bit rate is 400.000kHz, based on CPU frequency 12.000MHz */
	TWBR0 = 0x07;          /* SCL bit rate: 400.000kHZ before prescaling */
	TWSR0 = 0x00 << TWPS0; /* SCL precaler: 1, effective bitrate = 400.000kHz */
}

 

Try to send start condition:

unsigned char i2c_start(unsigned char address)
{
    uint8_t   twst;

	// send START condition
	TWCR0 = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

	// wait until transmission completed
	while(!(TWCR0 & (1<<TWINT)));         //*******************Never Gets Beyond Here***********************//

	// check value of TWI Status Register. Mask prescaler bits.
	twst = TWSR0 & 0xF8;
	if ( (twst != 0x08) && (twst != 0x10)) return 0;

	// send device address
	TWDR0 = address;
	TWCR0 = (1<<TWINT) | (1<<TWEN);

	// wail until transmission completed and ACK/NACK has been received
	while(!(TWCR0 & (1<<TWINT)));

	// check value of TWI Status Register. Mask prescaler bits.
	twst = TWSR0 & 0xF8;
	if ( (twst != 0x18) && (twst != 0x40) ) return 0;

	return 1;

 

I cannot get past just waiting for the start condition to finish. The SDA and SCL lines both have 4.7k resistor pullups to 3.3V, as I mentioned. I confirmed before starting debugging that they are both high (3.3V). I confirmed the 4.7k resistors are actually 4.7k. What else could I be doing wrong?

Last Edited: Wed. Mar 31, 2021 - 07:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Start with a proven library.   e.g. Fleury.   Or whatever Start provides.

 

Use library calls to i2c_start()

Always use the return value from the library function.   (most functions return a good or bad status)

 

If you have a problem,   Zip up your AS7.0 project.   Attach the ZIP file.

Then we can step you through any problems.

 

When it is working 100% with the proven library,   by all means write some home-grown I2C code if you want.

We can help you with that too.   But only if you have the project working with a proven library first.

 

David.

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

The code is posted IS from START and Fleury: the pin init is from START, and the IC2 Init and IC2 Start are from Fleury. And I understand about using return values, but if I don't ever get far enough to hit a return they don't help much. 

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

(never mind)

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Apr 1, 2021 - 07:40 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nobbyv wrote:

The code is posted IS from START and Fleury: the pin init is from START, and the IC2 Init and IC2 Start are from Fleury. And I understand about using return values, but if I don't ever get far enough to hit a return they don't help much. 

 

#1  is a snippet from Start.

#19 does not look like any normal library calls.

 

Zip up your AS7.0 Start project.   Attach the ZIP.

Zip up any home-grown AS7.0 project.  Attach the ZIP.

 

It is always wise to begin with trivial projects that use common hardware.   e.g. 24C32 eeprom, DS1307 RTC, ...

When you get the I2C comms correct on these Slaves,   you go on to the "less common" chips e.g. your EXC80H84

Then we can read, build, and possibly debug your project(s).

 

As a general rule,   you check Slave for ACK.    You read an ID register (if available).   You write to a register.   You attempt to read the register...

 

David.

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

nobbyv wrote:

	// wait until transmission completed
	while(!(TWCR0 & (1<<TWINT)));         //*******************Never Gets Beyond Here***********************//

I cannot get past just waiting for the start condition to finish. The SDA and SCL lines both have 4.7k resistor pullups to 3.3V, as I mentioned. I confirmed before starting debugging that they are both high (3.3V). I confirmed the 4.7k resistors are actually 4.7k. What else could I be doing wrong?

So do you see it actually send a Start Condition?

 

Maybe the lines are "stuck" high - Can you "manually" pull the lines low?

 

david.prentice wrote:
It is always wise to begin with trivial projects that use common hardware.   e.g. 24C32 eeprom, DS1307 RTC, ...

When you get the I2C comms correct on these Slaves,   you go on to the "less common" chips e.g. your EXC80H84

Absolutely!

 

EDIT

 

eg, see: https://www.avrfreaks.net/commen...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Apr 1, 2021 - 08:13 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This may not make the difference but ...

	/* SCL bitrate = F_CPU / (16 + 2 * TWBR0 * TWPS value) */
	/* Configured bit rate is 400.000kHz, based on CPU frequency 12.000MHz */
	TWBR0 = 0x07;          /* SCL bit rate: 400.000kHZ before prescaling */

... it's clear Peter Fleury uses the same formula. Your BRR value is exactly right but his code has this comment beside it:

/* must be > 10 for stable operation */

(Line 32, twimaster.c)

 

I'd expect 400kHz to be fine, and maybe he only offered that warning to ensure his library works with every device. Still, dropping down to 100kHz would bring your BRR value into the region he says is stable.

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

lloydb wrote:

/* Configured bit rate is 400.000kHz, based on CPU frequency 12.000MHz */

Forget about trying to race at Indy, when you can't even get the motor to start! 

Slow your bus speed down to 50kHz and see what happens!

 

awneil wrote:
The SDA and SCL lines both have 4.7k resistor pullups to 3.3V, as I mentioned.

Your pull ups are way too weak for that buss speed and vcc, heed the above advise to at least get started before considering a higher buss speed and h/w changes to support it.

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

ki0bk wrote:
awneil wrote:

The SDA and SCL lines both have 4.7k resistor pullups to 3.3V, as I mentioned.

Well, I quoted it ... cheeky

 

ki0bk wrote:
Your pull ups are way too weak for that buss speed and vcc,

Another case where an oscilloscope would reveal all ...

 

https://www.avrfreaks.net/commen...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:

lloydb wrote:

/* Configured bit rate is 400.000kHz, based on CPU frequency 12.000MHz */

Forget about trying to race at Indy, when you can't even get the motor to start! 

Slow your bus speed down to 50kHz and see what happens!

 

awneil wrote:
The SDA and SCL lines both have 4.7k resistor pullups to 3.3V, as I mentioned.

Your pull ups are way too weak for that buss speed and vcc, heed the above advise to at least get started before considering a higher buss speed and h/w changes to support it.

 

Jim

 

 

Dropped down to 50kHz. Still can't can't past sending the start condition.

 

	/* SCL bitrate = F_CPU / (16 + 2 * TWBR0 * TWPS value) */
	/* Configured bit rate is 50.000kHz, based on CPU frequency 12.000MHz */
	TWBR0 = 0x70;          /* SCL bit rate: 50.000kHZ before prescaling */
	TWSR0 = 0x00 << TWPS0; /* SCL precaler: 1, effective bitrate = 50.000kHz */

 

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

awneil wrote:

Another case where an oscilloscope would reveal all ...

 

I've got one. Just checked: SDA0 and SCL0 both go high and stay high.

Last Edited: Thu. Apr 1, 2021 - 05:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So when, exactly, do they "go" high?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


nobbyv wrote:
I've got one. Just checked: SDA0 and SCL0 both go high and stay high.

Good, So what would prevent the twi from sending start?

 

 

Start is when SDA goes low, followed by SCL going low too.

We are talking about an M328 are we not? The only thing I can think of is the TWI module is not enabled? or it's powered down, have you messed with the PRR reg?

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

ki0bk wrote:
So what would prevent the twi from sending start?

Indeed.

 

The only thing I can think of is the TWI module is not enabled? or it's powered down ...

Or something else is driving the lines high - see #24.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:

We are talking about an M328 are we not? The only thing I can think of is the TWI module is not enabled? 

 

Jim

 

 

I am suitably embarrassed. While testing at 400kHz, I commented out 

	TWCR0 = (1 << TWEN)   /* TWI0: enabled */

in my Init routine for some reason and forgot to remove it. So I'm back up and running up to 100kHz so far, just have to figure out why it's not running at 400kHz (probably pullup related). 

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

nobbyv wrote:
(probably pullup related). 

Try 1.2k's

 

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

In #33, nobbyv wrote:

I am suitably embarrassed. While testing at 400kHz, I commented out 

	TWCR0 = (1 << TWEN)   /* TWI0: enabled */

You mean in your #19?

	//TWCR0 = (1 << TWEN)   /* TWI0: enabled */
	  //      | (1 << TWIE) /* TWI0 Interrupt: enabled */
	    //    | (1 << TWEA) /* TWI0 Acknowledge: enabled */;

I doubt I'm the only one who saw that yesterday. I didn't point it out because you also said you then called this to send Start but it wasn't working:

unsigned char i2c_start(unsigned char address)
{
    uint8_t   twst;

	// send START condition
	TWCR0 = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

Wasn't that just shifting the enable inside the Start function? As you said, it's verbatim from Fleury. It works with his code so yours should have worked too.

 

Is it possible that either:

  • your setup that wasn't working yesterday differed somehow from the code you thought you were testing and posted here
  • or you've fixed something else that's improved things but thought it was due to the line you uncommented (which AFAICT can only have led to the peripheral being enabled twice so seems [EDIT: un]likely to be a fix)?

 

In #31, ki0bk wrote:

We are talking about an M328 are we not?

328PB AFAICT. In #1, nobbyv gave:

TWBR0 = 0x07;

which won't compile for the 328 or 328P. (In their headers, TWBR0 is a bit number not a register address.)

Last Edited: Thu. Apr 1, 2021 - 10:20 PM