TWI - lack of understanding

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

Hello, I’m a bit embarrassed to send my code for TWI.It is attempting to sent the address to a ds1307 RTC and just get it to start transmitting data back. I’m not very knowledgeable with this yet, soo....

#include 
#include 

int main (void)
	{
		TWSR &= ~0x03; //100kb/s
		TWBR  = 28;	   //100kb/s
			TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //Send START condition
				while (!(TWCR & (1<<TWINT))); //indication start condition has been sent
				{
					TWDR = 0x68;
					while (!(TWCR & (1<<TWINT)));//wait for data to be sent before sending next
					TWDR = 0x00;
					
				}	
				
			

}

Its for mega128
I know there is stuff missing from it but im having trouble, can anyone help me. regards

:arrow: Dan :!:

Last Edited: Fri. Jul 21, 2006 - 09:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's been quite extensively covered in the past - a quick search for DS1307 and I2C would have saved you having to wait for a reply. Here's a link to one of many threads. This one has my DS1307 code example in it for download, at the bottom of the page. It's assembler, but you can easily rewrite it in C following the same logical steps.

https://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=31230&highlight=ds1307+i2c

Compiler wizards: is there some reason why I2C support isn't built in to the standard libraries for the AVR? So many people have trouble with it, I'd have thought it would be a hot item.

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

Well thanks for the reply, I had done a search. As for not having it in libraries I’m not sure. :roll:

Dan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
TWDR = 0x68;

I remember seeing that "magical" number somewhere. However I also remember seeing (I think) that all the bits were then shifted left one time which ends up giving you 0xD0 (0b11010000). I remember wondering why the shift left was needed because, according to the datasheet, 0xD0 (the slave address + write "magical" number) and 0xD1 (the slave address + read "magical" number) are what you want to use. (I don't mean to insult your intelligence but you are aware that the DS1307 slave address is setup like this: 0b1101000x, where 'x' is the Read/Write indicator bit, when you want to Read from the DS1307 'x' = 1, when you want to Write to the DS1307 'x' = 0 ).

So try using 0xD0 when you are trying to write the slave address to the DS1307. I am not a C person yet so I can't be sure but it looks like you have the general idea right. What I am doing at the present point in my learning process goes something like this:
(to turn on and setup the DS1307 to count seconds)
1. Send START condition
2. Send SLA+W (SLave Address+Write, 0xD0)
3. Send DS1307 register address (seconds register address = 0x00)
4. Send initial data that will be written into the above register (I am sending 0x00, which starts the counting in the DS1307 and starts it counting from zero. I don't have the DS1307 datasheet handy so from memory, one of the bits of the seconds register is used to turn on/off the clock input to the counters)
5. Send STOP condition
(the above routines check the status of the TWINT bit and the codes in the TWSR)

(to read the DS1307)
1. Send START condition
2. Send SLA+W (SLave Address+Write, 0xD0)
3. Send DS1307 register address (seconds register address = 0x00)
4. Send RESTART condition
5. Send SLA+R (Slave Address+Read, 0xD1)
6. Send DS1307 register address (seconds register address = 0x00)
7. Perform read of DS1307 register addressed above (basically just: (1<<TWINT) | (1<<TWEN) written to the TWCR register)
8. Send ACK condition if additional registers are to be read, Send NACK condition, if finished reading registers (DS1307 has the capability to auto-increment the register addressing, see datasheet) Note: This step has not been tested as outlined here. I have successfully read the seconds and minutes registers but I did it by individually selecting the seconds and minutes register addresses instead of using the auto-increment mode of the DS1307. I experience problems when trying to use the auto-increment mode but I think the problems came from me not sending an ACK after each register read. I hope to try out the above sometime today.
9. Send STOP condition

Sorry to cut this short but work is calling :-) . I will try to come back later to see if there are additional questions or whatever. You would be advised to double check what I have said above, I am learning the TWI just as you are.

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

Another thing that often catches people out - when you read an I2C device, be sure not to send an ACK after receiving the final byte. If you do, the device will think you want another, and talk over the master when it tries to send a stop condition. On AVRs this can make the CPU think it's lost arbitration and go into slave mode, which causes all kinds of grief.

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

Thanks for pointing that out :-), I just found that out the hard way :-) . This TWI stuff is pretty neat once you get it all figured out. I will have to admit though, I don't think I would have stood a chance at getting it to work without the sample assembler code from ERE and all the recent threads on the subject.

[edit] and thanks peret for posting your code. It helped me confirm that ERE's version should work.