PDA

View Full Version : I2C issue



Charles Linquis
- 17th October 2011, 15:35
I'm trying to use the uChip MCP4561 EEPOT. I can read from it just fine, I just can't do a write using I2CWRITE, and Microchip tells me that the device must have a NACK at the end of each data transfer in order to work properly.

For example:

If I want to WRITE two bytes tp address 0x5D, I use the code

I2CAddress = $5D

I2CWRITE SDA,SCL,I2CAddress, Command,[Byte1,Byte2]

PBP sends out the WRITE request to the Address and gives an ACK
It sends out the command and gives an ACK
It sends byte 1 and gives an ACK
It sends byte 2 and gives an ACK <- should give NACK here, since this is the last byte of the transfer.

The MCP4561 holds the data bus low (forever). Is this a fault in PBP or my logic? In any case, does anyone know what I should try next?

mackrackit
- 17th October 2011, 17:04
Darrel can probably tell you how to mod a lib.
In the mean time maybe SHIFTOUT will work?
http://www.picbasic.co.uk/forum/content.php?r=165-Serial-EEPROM-Part-1

Charles Linquis
- 17th October 2011, 19:52
Thanks for the link, I may have to use that technique. I'm currently setting up the hardware to do the WRITE.
I already use it for READ.
I have never been 100% successful in getting the HW WRITE to work, so I usually just fall back to bit
banging. Fortunately, I'm hooked up to the real SDA and SCL on the chips.
It was always real easy to do a master-slave thing by sending in software and receiving in hardware,
you don't have to reconfigure any registers.

And for those of you that want to play with I2C: If you use my interrupt-driven slave (posted on this forum), you can
use I2CREAD and I2CWRITE at the same time the slave is running. One chip at both ends of the conversation!
A great debugging tool.

Charles Linquis
- 17th October 2011, 21:31
6069The SHIFTOUT / SHIFTIN method does, indeed look like it is going to work. I get a lot more control over what is going on.
I don't have eveything configured perfectly yet, but Thanks!

mackrackit
- 17th October 2011, 23:00
Cool!!! :)

Charles Linquis
- 17th October 2011, 23:37
BUT --- I can't use the shiftin/shiftout commands to write I2C. It violates the open-collector spec. That leaves me with a couple of options:
1. Learn to use the hardware
2. Modify the library to give shiftin/shiftout an open-collector mode (like I already have with DEBUG)
3. Do everything at the bit level myself.

cncmachineguy
- 18th October 2011, 00:15
I vote hardware!!

Charles Linquis
- 18th October 2011, 01:10
Working on it now. I'll get an interrupt-driven routine going and share it when it gets done.

mackrackit
- 18th October 2011, 05:10
Is there anything here that would help? I have not used DTs instants for this.
http://darreltaylor.com/DT_INTS-18/home.html

Looking forward to seeing your solution.

Charles Linquis
- 18th October 2011, 05:27
I use DT-INTS for *** EVERYTHING ***

I don't write a LED-blinker without some sort of interrupt!

If you haven't used them, you are missing about 60% of what you can do with PBP. Seriously.

mackrackit
- 18th October 2011, 06:39
I use them, just have not for I2C stuff. They are the only way for USB!

Charles Linquis
- 18th October 2011, 14:29
The I2C slave I posted uses DT-INTs. It is the only way you can have a slave running that can do something else at the same time.

cncmachineguy
- 18th October 2011, 14:57
Charles, Do you mean to say interrupts are the only way, and you use DT_INT? I am really going to have to get more into them, I would like to get another 60% from PBP :)

cncmachineguy
- 18th October 2011, 15:18
BTW, I am assuming you are doing this with PBP3. have you tried 2.6 to see if it is a new issue?

Charles Linquis
- 18th October 2011, 20:44
I haven't tried 2.6, but I have looked at the libraries. They are the same in the I2C area. They have another issue as well that I have mentioned before.
Many devices require you to turn on clock stretching (DEFINE I2C_HOLD 1). This is so they have enough time to process whatever you send to them. The slave holds SCL low until it is ready to accept the next byte. The master waits until the SCL goes high and sends the byte. But PBP has no timeout. If a device holds SCL low forever, your program is hung - forever. A similar situation exists if the I2C device is powered from a different power supply than the PIC master. If the slave has no power, it holds SCL and SDA low. I2CWRITE sends (or tries to send) data to the slave and waits for the SCL to go high, which it won't. Result = dead system. The work-around is to ALWAYS check for SCL and SDA to be high before any I2C read or write.

And if you are serious about not using DT-INTs extensively, you should. Yes, you can still do things the old fashioned way of saving/restoring registers, but Darrel has done all the hard work for you. You can use both ASM and PBP interrupts. My 'template' for all new code has the DT-INTs framework. I generally have an ASM interrupt on TMR0 that runs at a 1mS rate. If I need to make certain
I don't miss a pushbutton or some other input, I just put it in the ISR. I can 'latch' the input there and check for it in my main program loop. If I have to respond to something quick, I put the response in the ISR. All the while, I increment a var called MasterClock. I can measure time in ms between any two events. I also use it to time my main loops. For example: You can only read an I2C temperature sensor every 200-300 milliseconds. You can run your main loop as fast as you want, but when MasterClock > 300 you read the sensor, clear MasterClock and keep going. I generally don't use PAUSE at all, and my little PIC responds instantly to all important inputs.

cncmachineguy
- 18th October 2011, 21:23
I am being shown the light, I have found the switch and am trying to turn it on WRT DT_INT. My mantra is nothing in the ISR should need any PBP system variables (but I could be wrong there, still trying to figure out what uses them and what doesn't). So all my ISR's are ASM, but using PBP commands ie porta=portb.

As for the context saving, all the 16f1xxx and maybe all the 18's already do it for me. So as long as I deal with BSR life is good. But the ease of not looking up all the PIR.somebodys for the INT query does appeal to me. So like I said, I found the switch to turn the light on.

Charles Linquis
- 18th October 2011, 22:53
Yes, the 18Fs save context in an ASM int, but of course PBP is another matter. Sooner or later you will find that writing an ASM ISR is just too complicated, or else the PBP routine is already done for you. Then, figuring out what to save / restore gets to be a bit of a problem (unless you brute-force it and always save everything). The beauty of DT-INTs is that you can have one structure for both ASM and PBP interrupts, and it decodes the INT source for you if you have 5 or 6 of them like I often do.
Because more registers are saved, PBP ints take about twice as long to get into/out of than ASM ints, but if you most always run at 40MHz +, like I usually do, it seldom matters.