View previous topic :: View next topic |
Author |
Message |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
i2c bus scanner program |
Posted: Wed Jan 09, 2013 2:41 pm |
|
|
Here is a diagnostic program (see below) which will look for any i2c slave
devices that are on the i2c bus, and report the slave address for each
one. This program is useful if you want to be sure that your PIC actually
sees the i2c slave device on the i2c bus. It's important to check for this
if you wonder if the PIC is really talking to the i2c slave chip. This
program also lets you verify that the i2c slave chip is really at the same
slave address that you think it is.
This i2c bus scanner program works if the PIC is using either hardware
or software i2c. Note: CCS defaults to software i2c, unless you use the
hardware i2c pins and add the FORCE_HW parameter to the #use i2c()
statement.
For example, if I run this program on my PicDem2-Plus board, it
shows the following result in a terminal window (TeraTerm) on my PC:
Quote: |
Start:
ACK addr: 9A
ACK addr: A0
Number of i2c chips found: 2
|
This means that it found the TC74 temperature chip (slave address 0x9A)
and the 24LC256 eeprom (slave address 0xA0). Run the program on
your board and see what it finds. Note: change the #include, #fuses,
#use delay() and the i2c and RS232 pins (if necessary) so they fit your
development board.
Code: |
#include <16F887.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=4M)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
// 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 main()
{
unsigned int8 i;
unsigned int8 status;
unsigned int8 count = 0;
printf("\n\rStart:\n\r");
delay_ms(1000);
// 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("ACK addr: %X\n\r", i);
count++;
delay_ms(2000);
}
}
if(count == 0)
printf("\n\rNothing Found");
else
printf("\n\rNumber of i2c chips found: %u", count);
while(1);
}
|
The PIC must be connected to the i2c slave device's SDA and SCL pins.
The SDA and SCL pins must have pull-up resistors on them. There must
also be a ground connection between the Vss pin on the PIC and the
ground or Vss pin on the i2c slave chip. And of course, both the PIC
and the i2c slave chip must have power (Vdd) applied. If you bought
a development board, then these connections normally already exist.
Example:
Code: |
+5v
|
<
> 4.7K
<
To PIC | To i2c slave
pin C4 ------------------ SDA pin
(SDA)
+5v
|
<
> 4.7K
<
To PIC | To i2c slave
pin C3 ------------------ SCL pin
(SCL)
To PIC To i2c slave
Vss pin ----------------- Vss or ground pin
|
-----
--- Ground
-
|
Please don't use this thread to get help for writing an i2c driver program.
Start a new thread in the CCS General Discussion forum and ask for help there:
http://www.ccsinfo.com/forum/viewforum.php?f=1
----------------------
Edit: Made each variable be 'unsigned' for compatiblity with the PCD
compiler, per Jeremiah's suggestion.
Last edited by PCM programmer on Fri Jan 20, 2017 12:41 pm; edited 1 time in total |
|
|
MikeW
Joined: 15 Sep 2003 Posts: 184 Location: Warrington UK
|
|
Posted: Wed Jan 16, 2013 12:27 pm |
|
|
@ PCM programmer.
You are a diamond !!
I found and used your I2C diagnostic program (found in an old thread) last week to help me get started on an SSD1306 design.
Once I had got the hardware sorted, it found the device straight away.
It's a great tool for helping to debug the hardware.
Many many thanks. |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Sun Jul 07, 2013 11:31 am |
|
|
Hi PCM Programmer,
Thanks for the code... I think i found a bug?... maybe..
This is my first time using I2C, so i thought a good place to start was your test code.
Quote: | Start:
ACK addr: 4E
Number of i2c chips found: 1 |
as you can see, it worked.
I'm using a Breakout board from Sparkfun for the HIH-6130, on a tried and tested dev board I've made a while back...
I later went ahead to use this driver:
http://www.ccsinfo.com/forum/viewtopic.php?t=48077
But it did NOT work using "0x4E" as the address, like your code reported.
I tried "0x24" as the original poster, and that didn't work...
So further checking the datasheet i found the appropriate address to be "0x27" which happens to be =0x4E/2.
Although i have no idea what i am doing, i figured you could share some light on why the code is reporting an address value x2.
thanks..
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Sun Jul 07, 2013 12:14 pm |
|
|
In the driver you linked, it shifts the address to the left one bit (or *2 to the address). That is why you have to specify it as /2 in that driver. PCM's uses 8-bit address format while the other driver uses 7-bit address format.
PCM's test is correct. |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Mon Jul 08, 2013 7:10 am |
|
|
I see it.
Thanks for the explanation.
Quote: | PCM's test is correct. |
I was sure the "error" was mine, so thats why i asked this question.
anyways, thanks for clearing that up.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
th3gr8
Joined: 16 Jul 2013 Posts: 12 Location: Pakistan
|
Gr8 .. |
Posted: Wed Jul 02, 2014 3:04 pm |
|
|
Wow.. Really a nice program .. Thanks PCM Programmer .. _________________ A learner |
|
|
UgurSezgin
Joined: 06 Aug 2015 Posts: 1 Location: Turkey
|
|
Posted: Thu Aug 06, 2015 1:25 am |
|
|
Very Useful Program Thank You So Much @PCM Programmer..
I tried on 18F452 and Working Very Well..
I Edited SomeCodes (actualy cut cut cut and paste..) and Oversimplify.
i2cScanner.c
Code: | void i2cScanner() {
int8 count = 0;
printf("\n\rStart I2C Scanner..\n\r");
for(int8 i=0x10; i < 0xF0; i+=2) {
i2c_start();
if(i2c_write(i) == 0) { printf("ACK addr: 0x%X\n\r", i); count++; }
i2c_stop();
}
if(count == 0) {printf("Nothing Found\n\r"); }
else { printf("Number of i2c chips found: %u\n\r", count); }
}
|
main.c
Code: | #include <18F452.h>
#fuses PROTECT,NOWDT,PUT,NOLVP,NOBROWNOUT
#use delay(crystal=16MHz)
#use i2c(Master,Fast=400000,sda=PIN_C4,scl=PIN_C3,force_hw) // maybe force_sw
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,ERRORS)
#include <i2cScanner.c>
void main() {
i2cScanner();
while(1);
}
|
I Wanted to Share |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Fri Jan 20, 2017 11:44 am |
|
|
We recently had trouble running this in an older version PCD for a chip due to the int8 variables being considered signed by default and thus the for loop not acting completely correct. One suggestion is to manually indicate the unsigned keyword to avoid those situations. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jan 20, 2017 12:42 pm |
|
|
Done. Thanks. |
|
|
ressas
Joined: 15 Nov 2019 Posts: 135
|
|
Posted: Wed Nov 20, 2019 4:45 am |
|
|
Thanks for help |
|
|
|