|
|
View previous topic :: View next topic |
Author |
Message |
Jerry I
Joined: 14 Sep 2003 Posts: 96 Location: Toronto, Ontario, Canada
|
I2C Bus Scanner |
Posted: Tue May 05, 2020 7:50 pm |
|
|
Using Pic 18F27K40, CCS PCH C Compiler, Version 5.078.
Can the I2C Bus scanner code from the code library clobber the time/date in a DS1307 RTC Module that are available from many web sites.
It appears to keep time and date all of the time when program running. The code reads the time and date every 10 seconds.
I use the I2C Bus scanner to detect if the RTC is present, if not the hardware will be configured with a GPS Module.
At boot or power on I test for the RTC Module with the I2C Scanner code and sometimes the time & date get corrupted.
Thanks in advance for any ideas.
-Jerry |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Tue May 05, 2020 8:01 pm |
|
|
hmm, you do have a battery on the RTC Vbat pin ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19543
|
|
Posted: Wed May 06, 2020 2:18 am |
|
|
What is your power supply?.
The DS1307, has an issue if the battery is higher than 3v, or the supply
is lower than 5v. To work correctly, there must be at least 1.25* the
battery voltage on the main supply. If you use a lithium that is new,
the voltage can be as much as 3.3v. If the supply is a little low, this can
then give issues. Attempting to talk to the chip when it is close to the
switchover point can result in data corruption. So you need to make
absolutely sure your main supply is genuinely fully 'up' to it's running
voltage before trying to talk to the chip, and that this really is well over
4.2v.... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Wed May 06, 2020 4:13 am |
|
|
Adding to Mr. T. typing....
Be sure the PUT fuse is enabled.
Also have a one time delay_ms(1000) before main(). This do-nothing time allows for external peripherals and PS caps to stabilize.
If you're using an LCD module, this delay( I think 500ms..) is in the LCD_init() function, though I've always added 1 second.
I used to use the ds1307 and never had any problem, though now I use the ds3231. More accurate, 32KHz clk and comes with EEPROM chip on same PCB. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 06, 2020 6:12 am |
|
|
I tested this, and it worked OK. I turned off the power to the PIC board
every few seconds, waited a short time, and then turned it on again.
At power-up I do a scan of the i2c bus and then start displaying the
date/time. The ds1307 keeps time accurately. Scanning the i2c bus
did not disrupt it.
I am using hardware i2c at Slow speed, with 4.7K pullups.
Quote: |
Scanning i2c bus:
Found chip at: D0
05/06/20 15:21:42
05/06/20 15:21:44
05/06/20 15:21:45
05/06/20 15:21:46
05/06/20 15:21:47
05/06/20 15:21:48
05/06/20 15:21:49
Scanning i2c bus:
Found chip at: D0
05/06/20 15:21:56
05/06/20 15:21:58
05/06/20 15:21:59
05/06/20 15:22:00
05/06/20 15:22:01
05/06/20 15:22:02
Scanning i2c bus:
Found chip at: D0
05/06/20 15:22:06
05/06/20 15:22:08
05/06/20 15:22:09
05/06/20 15:22:10
05/06/20 15:22:11
05/06/20 15:22:12
05/06/20 15:22:13
05/06/20 15:22:14
05/06/20 15:22:15
Scanning i2c bus:
Found chip at: D0
05/06/20 15:22:18
05/06/20 15:22:20
05/06/20 15:22:21
05/06/20 15:22:22
05/06/20 15:22:23 |
Test program:
Code: | #include <18F46K22.h>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOPBADEN
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
#include <ds1307.c>
void scan_i2c_bus(void);
//======================================
void main()
{
BYTE sec;
BYTE min;
BYTE hrs;
BYTE day;
BYTE month;
BYTE yr;
BYTE dow;
scan_i2c_bus();
ds1307_init();
// Initialize the date/time only the first
// time this program is run. Set a flag in
// eeprom to tell us if we already set date/time.
if(read_eeprom(0) != 0x55)
{
write_eeprom(0, 0x55); // Set flag to show date/time was set
// Set date for -> May 6, 2020, Wednesday
// Set time for -> 15:20:55
ds1307_set_date_time(5,6,20,3,15,20,55);
}
while(TRUE)
{
delay_ms(1000);
ds1307_get_date(day,month,yr,dow);
ds1307_get_time(hrs,min,sec);
printf("\%02d/\%02d/\%02d ",day,month,yr);
printf("\%02d:\%02d:\%02d \r\n", hrs,min,sec);
}
while(TRUE);
}
//===========================================
// This function writes the slave address to the i2c bus.
// If a slave chip is at that address, it should respond to
// this with an "ACK". This function returns TRUE if an
// ACK was found. Otherwise it returns FALSE.
int8 get_ack_status(int8 address)
{
int8 status;
i2c_start();
status = i2c_write(address); // Status = 0 if got an ACK
i2c_stop();
if(status == 0)
return(TRUE);
else
return(FALSE);
}
//----------------------------------
void scan_i2c_bus(void)
{
unsigned int8 i;
unsigned int8 status;
unsigned int8 count = 0;
printf("\n\rScanning i2c bus:\n\r");
// Try all slave addresses from 0x10 to 0xEF.
// See if we get a response from any slaves
// that may be on the i2c bus.
for(i=0x10; i < 0xF0; i+=2)
{
status = get_ack_status(i);
if(status == TRUE)
{
printf("Found chip at: %X\n\r", i);
count++;
delay_ms(1); // Was 2000
}
}
if(count == 0)
printf("\n\rNothing Found");
//else
// printf("\n\rNumber of i2c chips found: %u", count);
} |
The ds1307.c file comes from this post in the Code library:
http://www.ccsinfo.com/forum/viewtopic.php?t=23255 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19543
|
|
Posted: Wed May 06, 2020 7:23 am |
|
|
Well done PCM.
The only time I have seen data loss with the DS1307, it turned out the
supply was only going up to about 4.6v, and with a new battery it then
corrupted the data if you talked to it. I had a 'batch', where the internal
to external switch over, seemed to happen at about 1.3* Vbat, and these
were the ones that gave problems with a new battery.
The same sort of problem could also appear if the supply was slow rising
(the PIC might then wake well before the RTC decides to switch), or
rose then dropped.
A delay at boot is very necessary for anything like this...
Also (of course), the PIC could be trying to do it's normal clock read
from the chip during the moment when the system is turned off. Might
again give the same problem. |
|
|
Jerry I
Joined: 14 Sep 2003 Posts: 96 Location: Toronto, Ontario, Canada
|
|
Posted: Wed May 06, 2020 12:17 pm |
|
|
Thanks for all the great answers.
I just wrote a nice long response and did not submit because I had lunch. After lunch I finished the response and not knowing the forum logged had me out and I lost everything. Arrg.
Here we go again.
The Battery voltage is 3.32v
The customer board is powered with 12-14v regulated down measuring 5.032v via 7805.
This board does not have a RTC on it. It used a GPS module for time and location data. All the GPS Modules are all failing in the field up to 50 units. Since there was an open header with unused pins I wired the I2C pins to the header and plugged in the RTC module. Link Below.
[url]
https://www.canadarobotix.com/products/1791
[/url]
This module includes a DS1307 and a AT24C32 where the SDA & SCK pins are pulled high with 3.3k resistors.
Can this be the problem 3.3k instead of 4.7K ??. The customer board has no pull-up on these free pins SDA PIN_B5 and SCL PIN_B0.
I have used the great test program PCM Programmer has provided and got no errors. I have cycled the power and reset the chip many times in the 2-3 hours and still running.
The new replacement program I have written accesses the RTC every 5-10 seconds but I also get a random lockup when running as part of the main application. I am sure I found that it locks up when reading the RTC. The I2C bus hangs and does not recover. The customer program stops running. I do have a LED flashing via an interrupt and still flashes but the rest of the main loop does not get executed. I also had a LED to flash as part of the main loop when I did a read on the RTC, this LED has stopped flashing. Lock-up on I2C ??.
Since I replaced the original PIC 18F2610 on the board with a PIC18F27K40. This chip has SSP and I required more code space. I tried HW I2C and SW I2C as coded below and I do get random lockup using either methods accessing the RTC then corrupt data. I2C Bus hangs?.
I did notice after it hangs I can reset the PIC but the scanner finds no devices. If I cycle the power everything is normal again.
Code: |
// Using SSP Option to reallocate the I2C pins
#PIN_SELECT SCL1OUT = PIN_B5
#PIN_SELECT SCL1IN = PIN_B5
#PIN_SELECT SDA1OUT = PIN_B0
#PIN_SELECT SDA1IN = PIN_B0
#use i2c(Master,Slow,I2C1,force_hw, stream=I2CBUS)
// Also Tried the SW I2C
#use i2c(Master, Slow, sda=PIN_B0, scl=PIN_B5, stream=I2CBUS)
|
Any more ideas.
Thanks Again
I better take a copy of this before I submit.
-Jerry |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Wed May 06, 2020 12:34 pm |
|
|
To recover from a hung I2C slave you will need to toggle the clock line manually. Probably 8 times. This will allow the slave to release the I2C lines for a new message. |
|
|
Jerry I
Joined: 14 Sep 2003 Posts: 96 Location: Toronto, Ontario, Canada
|
|
Posted: Wed May 06, 2020 2:38 pm |
|
|
Hi gaugeguy,
How do you do that in code when I call read RTC it goes to built in I2C functions that does not return if hung.
Code: |
void ds1307_get_date(BYTE &day, BYTE &mth, BYTE &year, BYTE &dow)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x03); // Start at REG 3 - Day of week
i2c_start();
i2c_write(0xD1);
dow = bcd2bin(i2c_read() & 0x7f); // REG 3
day = bcd2bin(i2c_read() & 0x3f); // REG 4
mth = bcd2bin(i2c_read() & 0x1f); // REG 5
year = bcd2bin(i2c_read(0)); // REG 6
i2c_stop();
}
|
Where do I manually toggle the clock line?.
Thanks for the idea |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 06, 2020 3:23 pm |
|
|
Actually you were testing it with hardware i2c twice.
The statement below doesn't create software i2c code:
Quote: |
..... // Also Tried the SW I2C
..... #use i2c(Master, Slow, sda=PIN_B0, scl=PIN_B5, stream=I2CBUS) |
Look at the .LST file below. The ASM code created by the line above
is talking to hardware registers:
Quote: |
00004: BCF SSP1CON1.WCOL
00006: MOVLB E
00008: BCF xCD.0
0000A: MOVFF data,SSP1BUF
0000E: MOVLW 02
00010: BTFSC SSP1CON1.WCOL
00012: GOTO 0022
00016: BTFSS xCD.0
00018: GOTO 0016
0001C: MOVLW 00
0001E: BTFSC SSP1CON2.ACKSTAT
00020: MOVLW 01
00022: MOVWF @01
00024: MOVLB 0
00026: GOTO 009C (RETURN)
...... |
If you want software i2c, then add the parameter shown in bold below:
Quote: | #use i2c(Master, Slow, sda=PIN_B0, scl=PIN_B5, FORCE_SW, stream=I2CBUS)
|
Then you get software i2c. Look at the MOVLW 8. That's the bit count.
The TRIS code is the bit-banging.
Code: | 00004: MOVLW 08
00006: MOVWF @01
00008: NOP
0000A: BCF LATB.5
0000C: BCF TRISB.5
0000E: NOP
00010: RLCF data,F
00012: BCF LATB.0
00014: BTFSC STATUS.C
00016: BSF TRISB.0
00018: BTFSS STATUS.C
0001A: BCF TRISB.0
0001C: BSF TRISB.5
0001E: BTFSS PORTB.5
00020: GOTO 001E
00024: DECFSZ @01,F
00026: GOTO 0008
0002A: NOP
0002C: BCF LATB.5
0002E: BCF TRISB.5
00030: NOP
00032: BSF TRISB.0
00034: NOP
00036: NOP
00038: BSF TRISB.5
0003A: BTFSS PORTB.5
0003C: GOTO 003A
00040: CLRF @01
00042: NOP
00044: BTFSC PORTB.0
00046: BSF 01.0
00048: BCF LATB.5
0004A: BCF TRISB.5
0004C: BCF LATB.0
0004E: BCF TRISB.0
00050: GOTO 00B0 (RETURN)
.................... |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 06, 2020 5:18 pm |
|
|
Jerry I wrote: |
Where do I manually toggle the [i2c] clock line ?
|
Newguy has a suggestion here about setting a timer when the i2c
routine begins. If the timer expires then it means the routine is stuck.
In that case, do the i2c reset procedure (in the timer isr).
http://www.ccsinfo.com/forum/viewtopic.php?t=58653&start=1
This post shows one way to generate the nine i2c clocks:
http://www.ccsinfo.com/forum/viewtopic.php?t=56821&start=17
This code isn't that great because it sits in a loop forever if the
clearing procedure fails. He should use a for() loop with a count of 9.
Also, he should use getenv() to get the bit address.
But what if the reset procedure doesn't work ? You need to have a way
for the PIC to power-cycle the i2c device to reset it.
(Or if you're lucky, the i2c device will have a reset line that you can use). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19543
|
|
Posted: Thu May 07, 2020 12:43 am |
|
|
and on the resistors, no.
4.7K, is a very high resistor value only suitable where there is just a
single device, and short wires. The minimum resistor is about 1K5R.
With your fairly long total bus, the lower resistor is better.
Try just turning the I2C speed down a little SLOW=50000 for example.
With the device attached on an external board, and possibly reasonably
long wires, bus capacitance may be becoming significant.... |
|
|
Jerry I
Joined: 14 Sep 2003 Posts: 96 Location: Toronto, Ontario, Canada
|
|
Posted: Sat May 09, 2020 6:06 pm |
|
|
Thanks for your suggestions I will try to implement them.
Thanks again. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|