| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| webgiorgio 
 
 
 Joined: 02 Oct 2009
 Posts: 123
 Location: Denmark
 
 
			    
 
 | 
			
				| pic i2c slave is "not found" |  
				|  Posted: Sat Nov 06, 2021 1:02 pm |   |  
				| 
 |  
				| 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
 
 
			    
 
 |  |  
		|  |  
		| webgiorgio 
 
 
 Joined: 02 Oct 2009
 Posts: 123
 Location: Denmark
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Nov 06, 2021 3:40 pm |   |  
				| 
 |  
				| 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: 1401
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Nov 06, 2021 4:58 pm |   |  
				| 
 |  
				| 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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Nov 07, 2021 12:07 am |   |  
				| 
 |  
				|  	  | 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Nov 07, 2021 4:25 am |   |  
				| 
 |  
				| 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: 9587
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Nov 07, 2021 6:04 am |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Nov 07, 2021 2:03 pm |   |  
				| 
 |  
				| 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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Nov 07, 2021 11:37 pm |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Nov 08, 2021 3:43 am |   |  
				| 
 |  
				| 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
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Nov 08, 2021 10:25 am |   |  
				| 
 |  
				| 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: 19964
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Nov 08, 2021 11:52 am |   |  
				| 
 |  
				| 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Nov 09, 2021 4:07 am |   |  
				| 
 |  
				| It works with the file compiled by PCM programmer!   
 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: 19964
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Nov 09, 2021 4:25 am |   |  
				| 
 |  
				|  	  | 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
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Nov 09, 2021 9:21 am |   |  
				| 
 |  
				| 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);
 }
 }
 
 
 
 | 
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |