CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

pic i2c slave is "not found"
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
webgiorgio



Joined: 02 Oct 2009
Posts: 123
Location: Denmark

View user's profile Send private message

pic i2c slave is "not found"
PostPosted: Sat Nov 06, 2021 1:02 pm     Reply with quote

Hi,
I have a PIC16F1789 (slave) connected with i2c to a ESP32.
Both running at 3.3V.
2.2k pull-ups on i2c.
Compiler 5.034.

On the ESP32 I have a i2c scanner code, which works (if I add a i2c device to the bus like a PCF8574 it is detected).

The PIC does not want to work, even though the code is very similar to the CCS example.

Code:


#include <16F1789.h>
#fuses INTRC_IO, NOLVP, PUT, NOPROTECT //INTRC_IO to be able to use A7 and A6 as GPIO
#use delay(clock=8M) //8M or 8000000
#bit INTF_BIT = 0x0B.1 //corrects something that makes int I/O to work

//pin definitions
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)
//#use i2c(Slave,Fast,sda=PIN_C4,scl=PIN_C3,address=0xA0)
//#use i2c(Slave,sda=PIN_C4,scl=PIN_C3,address=0xA0)
#use i2c(SLAVE, I2C1, address=0xA0)


unsigned int8 address, buffer[16];


#INT_SSP
void ssp_interrupt(){
   unsigned int8 incoming, state;
   state = i2c_isr_state();
   if(state <= 0x80)                      //Master is sending data
   {
      if(state == 0x80)
         incoming = i2c_read(2);          //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
      else
         incoming = i2c_read();

      if(state == 1)                      //First received byte is address
         address = incoming;
      else if(state >= 2 && state != 0x80)   //Received byte is data
         buffer[address++] = incoming;
   }

   if(state >= 0x80)                      //Master is requesting data
   {
      i2c_write(buffer[address++]);
   }
}

void main(){
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_SSP);
   
   while(TRUE){
   }

}

webgiorgio



Joined: 02 Oct 2009
Posts: 123
Location: Denmark

View user's profile Send private message

PostPosted: Sat Nov 06, 2021 1:36 pm     Reply with quote

I tried also with SMBUS as advised here:
http://www.ccsinfo.com/forum/viewtopic.php?p=191024#191024
I lowered the address to 0x33 (i2c scanner goes to 127 max).
I checked the solder joints on the PIC and they are good.
No luck so far.
webgiorgio



Joined: 02 Oct 2009
Posts: 123
Location: Denmark

View user's profile Send private message

PostPosted: Sat Nov 06, 2021 3:40 pm     Reply with quote

I tested the PIC as a master with a slave i2c display. It works. So my hardware is ok, even though I tested it at 5V, while my slave application need to work at 3.3V.
I read that working at 3.3V could be a problem for i2c, but the option #use i2c(....SMBUS) should fix that.

I run the same setup at 3.3V (simply moving the jumper inside the ICD U64), and it works (I had to adjust the contrast on the display, where I can barely see the text).

Still as a slave, I can't figure what's wrong. A compiler bug? I've an old version 5.034
jeremiah



Joined: 20 Jul 2010
Posts: 1315

View user's profile Send private message

PostPosted: Sat Nov 06, 2021 4:58 pm     Reply with quote

I don't recall off the top of my head if the #use spi() uses an 8bit or 7bit address. You might try adjusting the address for the other format. So for example, if the 8bit address representation is 0xA0 then try 0x50 on the PIC side as the 7bit representation. Also I seem to remember some I2C addresses are reserved by the I2C standard (I *think*), but I don't recall which. You might check into that as the internal PIC slave hardware may not allow some addresses (and that wouldn't show up if tested as a master as it's just sent as data and not part of the hardware like the slave is).
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Nov 07, 2021 12:07 am     Reply with quote

webgiorgio wrote:

I lowered the address to 0x33 (i2c scanner goes to 127 max).

What does this mean ? Did you put 0x33 in the PIC's #use i2c()
statement as the slave address ? That's not allowed. The PIC's
slave address must be even.

I suspect your ESP32 device uses 7-bit i2c addresses.
CCS uses 8-bit addresses. So if the ESP32 is setup to talk to a slave
at address 0x50, the PIC should be configured for address=0xA0.

Also, what is the speed of the ESP32 in MIPS ? I suspect it's high.
Your PIC is only running at 2 MIPS. It's better if the PIC slave runs
faster than the master. Try running your PIC at 32 MHz. This will
give 8 MIPS. It still might not be fast enough, depending on the
speed of the ESP32.

Edit: Fixed a typo. I meant "if the ESP32 is setup to talk".
I have fixed that typo above.


Last edited by PCM programmer on Sun Nov 07, 2021 8:03 am; edited 1 time in total
webgiorgio



Joined: 02 Oct 2009
Posts: 123
Location: Denmark

View user's profile Send private message

PostPosted: Sun Nov 07, 2021 4:25 am     Reply with quote

To my understanding the R/W bit is the LSB.
So if A0 is the read address, A1 is the write address.
The i2c scanner program on the ESP32 is using a "for" loop where the address is incremented from 1 to 127 decimal. So that is the "7 bit address", and is able to go trough all possible read addresses (LSB=0).

Anyway, I have set the PIC address to 0xA0.
Code:
#use i2c(SLAVE, sda=PIN_C4, scl=PIN_C3, address=0xA0, SMBUS, FAST=100000)

I've set the PIC to run at 32 MHz.
ESP32 is going at 240 MHz. I've tested also 20 MHz and 10 MHz. I still get no response from the PIC.
ESP32 has something like 400 MIPS. I've set in both slave and master to use a bus speed of 100 kbit/s. Can the CPU speed be an issue? at the end the bus is going at 100 kbit/s speed.
temtronic



Joined: 01 Jul 2010
Posts: 9097
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Nov 07, 2021 6:04 am     Reply with quote

random thoughts..
1) Since the ESP32(Master) sees the PCF8574(Slave), reprogram the PIC with the same address as the PCF8574. The ESP32 scanner program should now see the PIC. If it doesn't, post the ESP32 scanner program, maybe there's something 'weird' going on,that isn't obvious.

2) The PIC clock should be very fast compared to the I2C bus speed. This allows it to 'do stuff as needed' between I2C bus activity. It's not that the ESP32 clock speed vs PIC that matters, well shouldn't be. There is 'overhead' in any ISR,not just the handler code, and the PIC needs time for that. The faster the clock, the quicker it gets done...

My 'gut' says it's something silly, like the adrs being left shifted one extra position...
Going to be nice to see 'solved' and WHAT the problem was, hopefully before you've gone bald....
webgiorgio



Joined: 02 Oct 2009
Posts: 123
Location: Denmark

View user's profile Send private message

PostPosted: Sun Nov 07, 2021 2:03 pm     Reply with quote

I did more testing. I removed the ESP32 to take a variable out of the question.
I wired up two PIC16F1789, 5V, one as a slave, and one as i2c scanner.
The scanner works, as I can detect a i2c display if hooked to the bus at 7E.
The slave PIC however is not found.
I even tried to give the slave the address 7E, but is not found anyway.
So the problem is in the slave program.
It does not enter the interrupt. Shall I try with i2c_poll() ?


Code:
/*
 i2c slave
*/

#include <16F1789.h>
#fuses INTRC_IO, NOLVP, PUT, NOPROTECT //INTRC_IO to be able to use A7 and A6 as GPIO
#use delay(clock=32M) //8M or 8000000
//#bit INTF_BIT = 0x0B.1 //corregge qualcosa del compilatore per far funzionare int I/O

//pin definitions
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
//#use i2c(Slave,Fast,sda=PIN_C4,scl=PIN_C3,address=0xA0)
#use i2c(Slave,sda=PIN_C4,scl=PIN_C3,address=0x10)
//#use i2c(SLAVE, sda=PIN_C4,scl=PIN_C3, address=0xA0, SMBUS, FAST=100000)


unsigned int8 address, buffer[16];


#INT_SSP
void ssp_interrupt(){
   output_toggle(PIN_C2);
   unsigned int8 incoming, state;
   state = i2c_isr_state();
   if(state <= 0x80)                      //Master is sending data
   {
      if(state == 0x80)
         incoming = i2c_read(2);          //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
      else
         incoming = i2c_read();

      if(state == 1)                      //First received byte is address
         address = incoming;
      else if(state >= 2 && state != 0x80)   //Received byte is data
         buffer[address++] = incoming;
   }

   if(state >= 0x80)                      //Master is requesting data
   {
      i2c_write(buffer[address++]);
   }
}

void main(){
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   printf(" Boot i2c slave \n");
   
   while(TRUE){
   
   delay_ms(1);
   
   }

}




Code:
/*
 i2c scanner
*/
#include <16F1789.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=32M)
#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;

printf("\n\rStart i2c scanner:\n\r");

while(1){
   // 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);
          delay_ms(2000);
         }
      }
   
   if(count == 0)
      printf("\n\rNothing Found");
     
   output_toggle(PIN_C2);
   delay_ms(2000);
   
   }
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Nov 07, 2021 11:37 pm     Reply with quote

There are some differences in the .LST file code between vs. 5.034
and vs. 5.104.

vs. 5.034: Code in #int_ssp
Code:

....... incoming = i2c_read(); 
0062:  MOVLB  04
0063:  BCF    SSP1CON1.SSPOV
0064:  MOVLB  00
0065:  BTFSS  PIR1.SSP1IF
0066:  GOTO   065
0067:  MOVLB  04
0068:  MOVF   SSP1BUF,W
0069:  BSF    SSP1CON1.CKP
006A:  MOVLB  00
006B:  MOVWF  incoming

vs. 5.104: Code in #int_ssp
Code:

....... incoming = i2c_read();
0062:  MOVLB  04
0063:  BCF    SSP1CON1.SSPOV
0064:  BTFSS  SSP1STAT.BF   // Tests BF instead of SSP1IF
0065:  GOTO   064
0066:  MOVF   SSP1BUF,W
0067:  BSF    SSP1CON1.CKP
0068:  MOVLB  00
0069:  MOVWF  incoming


vs. 5.034: Init code in main()
Code:

0131:  MOVLW  36
0132:  MOVWF  SSP1CON1
0133:  BSF    SSP1CON2.SEN


vs. 5.104: Init code in main()
Code:

012F:  MOVLW  36
0130:  MOVWF  SSP1CON1
0131:  BSF    SSP1CON2.SEN
0132:  BSF    SSP1CON2.GCEN   // Sets GCEN bit


vs. 5.034:
Code:

...... i2c_write(buffer[address++]); 
0087:  MOVF   address,W
0088:  INCF   address,F
0089:  ADDLW  buffer+-32
008A:  MOVWF  FSR0L
008B:  MOVLW  buffer+-9
008C:  MOVWF  FSR0H
008D:  BTFSC  STATUS.C
008E:  INCF   FSR0H,F
008F:  MOVF   INDF0,W
0090:  MOVWF  @@42
0091:  MOVF   @@42,W
0092:  MOVWF  i2c_wrt_data
0093:  MOVLB  04
0094:  MOVF   SSP1BUF,W
0095:  MOVLB  00
0096:  MOVF   i2c_wrt_data,W
0097:  MOVLB  04
0098:  MOVWF  SSP1BUF
0099:  BSF    SSP1CON1.CKP
009A:  MOVLB  00
009B:  BCF    PIR1.SSP1IF
009C:  MOVLB  04
009D:  BTFSC  SSP1STAT.BF
009E:  GOTO   09D
009F:  CLRF   @78
00A0:  BTFSC  SSP1CON1.CKP
00A1:  INCF   @78,F
00A2:  MOVLB  00

vs. 5.104:
Code:

...... i2c_write(buffer[address++]);
0085:  MOVF   address,W
0086:  INCF   address,F
0087:  ADDLW  buffer+-32
0088:  MOVWF  FSR0L
0089:  MOVLW  20   // Instead of buffer-9 it uses 0x20
008A:  MOVWF  FSR0H
008B:  BTFSC  STATUS.C
008C:  INCF   FSR0H,F
008D:  MOVF   INDF0,W
008E:  MOVWF  @@42
008F:  MOVF   @@42,W
0090:  MOVWF  i2c_wrt_data
0091:  MOVLB  04
0092:  MOVF   SSP1BUF,W
0093:  MOVLB  00
0094:  MOVF   i2c_wrt_data,W
0095:  MOVLB  04
0096:  MOVWF  SSP1BUF
0097:  BSF    SSP1CON1.CKP
0098:  MOVLB  00
0099:  BCF    PIR1.SSP1IF
009A:  MOVLB  04
009B:  BTFSC  SSP1STAT.BF
009C:  GOTO   09B
009D:  CLRF   @78
009E:  BTFSS  SSP1CON2.ACKSTAT  // It tests ACKSTAT vs. CKP
009F:  INCF   @78,F
00A0:  MOVLB  00
webgiorgio



Joined: 02 Oct 2009
Posts: 123
Location: Denmark

View user's profile Send private message

PostPosted: Mon Nov 08, 2021 3:43 am     Reply with quote

Hi,
thanks for investigating.
Are those differences something that I can fix in my source code? How?
Could you send the .hex file of the slave, to test?


Last edited by webgiorgio on Tue Nov 09, 2021 3:45 am; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 08, 2021 10:25 am     Reply with quote

Here is the i2c slave hex file for CCS vs. 5.104:
Code:

:060000008031142900000C
:0800080083018031200077081C
:10001000A0007808A1007908A2007A08A3002300B4
:1000200011082000A400230012082000A5002300CE
:1000300013082000A600230014082000A700850153
:1000400091308400801D262891193F282008F70050
:100050002108F8002208F9002308FA0024082300E8
:10006000910020002508230092002000260823008C
:10007000930020002708230094000900200080310D
:10008000412821000E11043022008E062400941A0B
:1000900051282000B9012400141D51282000B9174F
:1000A000240020003908B90AC1004108803C031C23
:1000B00081284108803C031D62282400110820008B
:1000C000C0006A2824001513141C64281108151692
:1000D0002000C000410B6F284008A800812841087B
:1000E000013C031881284108803C03198128280815
:1000F000A80A093E8400203085000318850A4008BC
:10010000800041087F3C0318A1282808A80A093E5E
:100110008400203085000318850A0008C2004208C8
:10012000C300240011082000430824009100151684
:1001300020009111240014189B28F801161FF80ABA
:1001400020009111803126282021EF377410691981
:1001500063107336613B65100A000B088B13230094
:100160009517151400000000891B8B1713087F39A1
:100170000319FB282000BD00230011082000BE0049
:10018000230012082000BF003D08111EC5282300CF
:100190009A0020003E082300910020003F08230021
:1001A00092000B088B139517151400000000891B93
:1001B0008B17130D140D7F390319FB282000BD0088
:1001C000230011082000BE00230012082000BF00F9
:1001D0003D08111EE92823009A0020003E08230054
:1001E000910020003F0823009200910A0319920A0F
:1001F0002000AD282300803120004C2920308500CC
:100200001C3084000008031912290A30F800F70195
:10021000F70B0829F80B07295F30F700F70B0E29B9
:10022000800B052980314F29F030210099002300EF
:100230009F1540309B0003309C00A6309E009030FC
:100240009D0022001D129D1121008E150E16240006
:1002500017109710971110309200FF30930036302E
:1002600095001614961703302000B900BB01BA019F
:1002700023008C018D018E018F01900122009201DB
:10028000910121009115C0308B04A430230091000E
:10029000003092002000AD280130BC00FE284C291F
:0202A0006300F9
:020000040001F9
:04000E00C43FFF1ECE
:00000001FF
;PIC16F1789
;CRC=023D  CREATED="08-Nov-21 08:11"
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Mon Nov 08, 2021 11:52 am     Reply with quote

The i2c_read code changes don't matter (the older compiler is
wasting one instruction by selecting the bank twice).
The initialisation may, so probably worth manually setting the GCEN
bit,
For the write, try coding as:
Code:

   int temp;
   temp=buffer[address++];
   i2c_write(temp); 

It looks as if the .034 compiler is not correctly addressing the array
read inside the function call.
webgiorgio



Joined: 02 Oct 2009
Posts: 123
Location: Denmark

View user's profile Send private message

PostPosted: Tue Nov 09, 2021 4:07 am     Reply with quote

It works with the file compiled by PCM programmer! Very Happy

With my compiler version it does not enter the ssp_interrupt() (no Led toggle), so the code inside does not matter.
I think I will download the demo of the latest copiler version.

How do I set the GCEN bit?
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Tue Nov 09, 2021 4:25 am     Reply with quote

Code:

#bit GCEN=getenv("BIT:GCEN")

   //then
   GCEN=1; //sets the bit

I wouldn't worry about this though, try with the temporary variable for
the array access first. All this bit affects is whether the chip will respond
to a 'general call' (address 0).
webgiorgio



Joined: 02 Oct 2009
Posts: 123
Location: Denmark

View user's profile Send private message

PostPosted: Tue Nov 09, 2021 9:21 am     Reply with quote

Here is the code I modified according to the suggestions,
It doesn't work.

Code:
/*
 i2c slave
*/

#include <16F1789.h>
#fuses INTRC_IO, NOLVP, PUT, NOPROTECT //INTRC_IO to be able to use A7 and A6 as GPIO
#use delay(clock=32M) //8M or 8000000
#bit GCEN=getenv("BIT:GCEN")

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#use I2C(slave,sda=PIN_C4,scl=PIN_C3,address=0x10)

unsigned int8 address, buffer[16];
int temp;
//---------------------------------------
#INT_SSP
void ssp_interrupt(){
   output_toggle(PIN_C2);
   unsigned int8 incoming, state;
   state = i2c_isr_state();
   if(state <= 0x80)                      //Master is sending data
   {
      if(state == 0x80)
         incoming = i2c_read(2);          //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
      else
         incoming = i2c_read();

      if(state == 1)                      //First received byte is address
         address = incoming;
      else if(state >= 2 && state != 0x80)   //Received byte is data
         buffer[address++] = incoming;
   }

   if(state >= 0x80)                      //Master is requesting data
   {
      //i2c_write(buffer[address++]);
      int temp;
      temp=buffer[address++];
      i2c_write(temp);
   }
}
//------------------------------
void main(){
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   printf(" Boot i2c slave \n");
   //i2c_init(TRUE);
   //setup_spi(TRUE);
   GCEN=1; //sets the bit
   
   output_high(PIN_C2);
   delay_ms(1000);
   output_low(PIN_C2);
   
   while(TRUE){
      //delay_ms(1);
   }
}


Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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