From: SourceForge.net <no...@so...> - 2011-07-19 13:31:19
|
Bugs item #3368894, was opened at 2011-07-16 20:31 Message generated for change (Comment added) made by awsit You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=100599&aid=3368894&group_id=599 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: pic16 target Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: Fred Marquis (fredmarquis) Assigned to: Nobody/Anonymous (nobody) Summary: i2c_start and i2c_stop incomplete Initial Comment: I think the routines i2c_start and i2c_stop in the pic16 port of the libio library are incomplete, application note AN989 suggests that i2c_start and i2c_stop should clear PIR1bits.SSPIF before setting SSPCON2bits.SEN or SSPCON2bits.PEN and not exit/return until it (PIR1bits.SSPIF) is set by the hardware. ---------------------------------------------------------------------- Comment By: strobla (awsit) Date: 2011-07-19 15:31 Message: Dear Fred, dear Diego, have a look at one of my i2c functions. I agree with your ideas ... Regards, Strobl Anton uchar get_lm75_value(uchar *cdata, uchar addr) { i2c_idle(); i2c_start(); while(SSP1CON2bits.SEN){}; // wait until start condition is ready i2c_writechar(addr + 1); // want to read data from lm75 i2c_idle(); if (SSP1CON2bits.ACKSTAT == 1) { // 0 if found; 1 if NOT received ACK i2c_stop(); while(SSP1CON2bits.PEN){}; // wait until stop condition is completed return 0; } *cdata++ = i2c_readchar(); i2c_ack(); while(SSP1CON2bits.ACKEN){}; *cdata++ = i2c_readchar(); i2c_nack(); while(SSP1CON2bits.ACKEN){}; i2c_stop(); while(SSP1CON2bits.PEN){}; // wait until stop condition is completed return 1; } ---------------------------------------------------------------------- Comment By: Fred Marquis (fredmarquis) Date: 2011-07-19 14:54 Message: Yes, diegoherranz I agree I have also used the SSPCON2bits.SEN = 1; while (SSPCON2bits.SEN); construction and found it works well, similarly I have used: PIR1bits.SSPIF=0; SSPCON2bits.SEN = 1; while (SSPCON2bits.SEN); which also works. My problem is that the example I have been looking at, trying and modifying are fairly simple and many of the status bits, AFAIK all change at the same time so more than one test can be used -- maybe in more complex cases this will not be the case. I'll have a closer read of AN735 and a play but it will be some time before I can get back to this ---------------------------------------------------------------------- Comment By: Diego Herranz (diegoherranz) Date: 2011-07-19 13:21 Message: Another application note, AN735 (Using the PICmicro® MSSP Module for Master I2C) says: "An important item to note at this point, is when implementing a Master I2C controller with the MSSP module, no events can be queued. One event must be finished and the module IDLE before the next event can be initiated. There are a few of ways to ensure that the module is IDLE before initiating the next event [...]" In short, it shows 3 ways: - Generic idle check subroutine (Example 7): it checks for everything to be idle. It should be called before starting any event. - Specific event idle check (Example 8 and following): it should be checked after starting an event. - Interrupts (Example 11): when an interrupt occurs (SSPIF) last event has ended. I think that the best approach for sdcc would be the second one. Start and stop routines could be something like this: void i2c_start(void) { SSPCON2bits.SEN = 1; while (SSPCON2bits.SEN); } void i2c_stop(void) { SSPCON2bits.PEN = 1; while (SSPCON2bits.PEN); } Perhaps clearing SSPIF before starting these events might be useful too, although ISR should clear it, shouldn't it? ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=100599&aid=3368894&group_id=599 |