| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| BrianC 
 
 
 Joined: 23 Apr 2022
 Posts: 11
 Location: UK
 
 
			    
 
 | 
			
				| 18F26K42 I2C [Solved] |  
				|  Posted: Sat Apr 23, 2022 8:30 am |   |  
				| 
 |  
				| Hi, I am trying to get the hardware I2C master working on the K42,
 
  	  | Code: |  	  | #pin_select SDA1OUT=PIN_C4
 #pin_select SDA1IN=PIN_C4
 
 #pin_select SCL1OUT=PIN_C3
 #pin_select SCL1IN=PIN_C3
 
 #use delay(internal=32000000)
 
 #use i2c(Master,Slow,I2C1,force_hw)
 
 | 
 However when I run the code it then sits in a tight loop at the #use i2c statement at lines 180 / 182, having set a flag then waiting for it to clear.
 
 Any suggestions would be well received !
 
 Regards
 BrianC
 
 
  	  | Code: |  	  | .................... #use i2c(Master,Slow,I2C1,force_hw)
 *
 0014A:  MOVLB  3D
 0014C:  BCF    x76.4
 0014E:  BCF    x78.7
 00150:  BSF    x78.2
 00152:  MOVFFL 206,3FEA
 00158:  MOVFFL 205,3FE9
 0015E:  MOVLB  2
 00160:  BTFSS  x04.0
 00162:  BRA    016A
 00164:  MOVLB  3D
 00166:  BSF    x73.6
 00168:  MOVLB  2
 0016A:  BTFSC  x04.0
 0016C:  BRA    0172
 0016E:  MOVLB  3D
 00170:  BCF    x73.6
 00172:  MOVLB  3D
 00174:  MOVF   x6C,W
 00176:  BZ    017E
 00178:  MOVFFL 3FEE,3D6B
 0017E:  BSF    x73.5
 00180:  BTFSC  x73.5
 00182:  BRA    0180
 00184:  BTFSC  x76.4
 00186:  BRA    0198
 
 | 
 |  |  
		|  |  
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9589
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Apr 23, 2022 8:51 am |   |  
				| 
 |  
				| re: 
  	  | Quote: |  	  | 00180: BTFSC x73.5 00182: BRA 0180
 
 | 
 OK, so whatever bit 5 of SFR 73 is, it is always high, Until is 'Clears' ( goes low), it'll be there forever, which is what you're seeing.
 
 Would have to get the datasheet to see what it is,as I don't use that PIC.
 great ..downloaded the sheet...
 looked at the SFRs.. can't find x73.......sigh....I suppose it's really 0xNN73, but no idea what NN really is.
 
 Also, looks like that PIC has a 'real' I2C peripheral...so there may be something 'funny' going on ?
 
 Do you have pullups on the I2C clk and data pins ??
 
 more looking....
 I 'think' that SFR might be 0x3D73, the I2C control register for device #0. If so, then it makes sense.
 You USE wants I2C device #1, but the code wants device #0.
 
 trying to help....
 
 Jay
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Apr 23, 2022 9:56 am |   |  
				| 
 |  
				| You _have_ got suitable pullups on the wires?. 
 It'll hang there if the lines aren't going high. 0x3D72, is I2c1CON0, and
 this is the start bit. Setting it sends a start, and it drops when the start
 has been sent.The hardware waits for BFRE to be set, before it'll
 assert this bit. This requires both lines to be high.
 Also, what commands are you using to drive this?. This chip has the
 'new' I2C module instead of the MSSP. You should be using the
 I2C_transfer command, not I2C_start / I2C_write etc..
 |  |  
		|  |  
		| BrianC 
 
 
 Joined: 23 Apr 2022
 Posts: 11
 Location: UK
 
 
			    
 
 | 
			
				| 18F26K42 I2C |  
				|  Posted: Sat Apr 23, 2022 10:28 am |   |  
				| 
 |  
				| Yes, pull-ups are on the board. and the commands are 'transfer' rather than 'start' ..... 'stop'. The old MSSP struff has worked well for years on this product, but had to redesign for the customer as lead times on the current PIC are November and beyond ! |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Apr 23, 2022 1:18 pm |   |  
				| 
 |  
				| Can you physically test the lines are high?. What compiler version?.
 |  |  
		|  |  
		| BrianC 
 
 
 Joined: 23 Apr 2022
 Posts: 11
 Location: UK
 
 
			    
 
 | 
			
				| 18F26K42 I2C |  
				|  Posted: Sat Apr 23, 2022 4:24 pm |   |  
				| 
 |  
				| Yes, they are both high. The compiler version is 5.107, updated it a couple of days a go to make sure I had the latest version. 
 The bit that bothers me is that this seems to be at the point where it is initialising the i2c, and has not actually got as far as trying to send a byte. I know it has done some processing before this as at start up it checks some data in e2 and if it fails it reloads default data, and restarts. That is all working fine.
 
 It has not got as far as trying to send the initialisation codes to the LCD display sat on the end of the i2c. I have an i2c protocol analyser sat on the i2c and it does not see anything. So looks like it has a problem executing the #use i2c statement.
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Apr 24, 2022 3:11 am |   |  
				| 
 |  
				| Odd. 
 I have just tried a basic test with a 46K42 (same chip except in a larger
 package), and a 24LC01 EEPROM.
 It runs:
 
  	  | Code: |  	  | #include "18F46K42.h"
 #device ADC=12
 
 #FUSES NOWDT                    //No Watch Dog Timer
 #FUSES NOMCLR
 
 #use delay(internal=32000000)
 #pin_select SDA1=PIN_C4
 #pin_select SCL1=PIN_C3
 
 #use i2c(Master,Slow=100000,I2C1,stream=I2C)
 
 #pin_select U1TX=PIN_B0
 #pin_select U1RX=PIN_B1
 
 #use rs232(baud=9600,parity=N,bits=8,stream=PORT1)
 
 //Basic code to access 2401 EEPROM
 
 #define EEPROM_ADDRESS BYTE
 #define EEPROM_SIZE    128
 #define EEPROM_R 0xa0
 #define NULL (void *)0
 
 //test if EEPROM gives an acknowledge
 BOOLEAN ext_eeprom_ready() {
 int1 ack;
 ack=i2c_transfer(I2C,EEPROM_R, NULL ,0);
 return !ack;
 }
 
 //write a byte to the eeprom
 void write_ext_eeprom(BYTE address, BYTE data) {
 int to_send[2];
 
 while(!ext_eeprom_ready())
 ;
 to_send[0]=address;
 to_send[1]=data; //setup data to send
 i2c_transfer(I2C, EEPROM_R, to_send, 2);
 }
 
 //read a byte from EEPROM
 BYTE read_ext_eeprom(BYTE address) {
 BYTE data;
 
 while(!ext_eeprom_ready())
 ;
 i2c_transfer(I2C, EEPROM_R, &address, 1, &data,1);
 return(data);
 }
 
 void main()
 {
 int1 write=TRUE;
 int16 rval;
 while(TRUE)
 {
 if (write)
 {
 write_ext_eeprom(0,0xAA);
 write_ext_eeprom(1,0x55);
 write=FALSE;
 }
 //Now read back
 rval=make16(read_ext_eeprom(0), read_ext_eeprom(1));
 fprintf (PORT1, "Value read is %lx\n",rval);
 delay_ms(1000);
 }
 }
 
 | 
 It is not working right, not reading the right value, but that may be
 something like needing to turn the slew rate limitation off on the pins.
 Will investigate later when I have time. However it does not hang where
 you are describing.
 
 What are you calling to 'initialise the I2c'?. The only initialisation is done
 at the start of main, where it programs the pin select options, sets up the
 TRIs etc. It does not call this routine. This is only called for an actual
 transfer.
 If it is arriving at this part of the code without a call to I2C_Transfer
 actually occurring, then it says there is a flow problem in the code.
 Something like an interrupt enabled without a handler, which could
 result in a call to an invalid address.
 |  |  
		|  |  
		| BrianC 
 
 
 Joined: 23 Apr 2022
 Posts: 11
 Location: UK
 
 
			    
 
 | 
			
				| 18F26K42 I2C |  
				|  Posted: Sun Apr 24, 2022 3:52 am |   |  
				| 
 |  
				| Many thanks, I will have a look at this and see where it gets me.
 |  |  
		|  |  
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9589
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Apr 24, 2022 5:22 am |   |  
				| 
 |  
				| hmm, not something like USE I2C before the pin selects? One of those 'we need to see your code' problems......
 It'd be nice to see Mr. T's  #USE I2C(...)  assembler to compare.
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Apr 24, 2022 7:07 am |   |  
				| 
 |  
				| The thing that worries me, is he talks as if this is happening before any actual I2C calls. It only calls this section when I do the transfer.
 I'll post the assembler later.
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Apr 24, 2022 8:09 am |   |  
				| 
 |  
				| Assembler: 
  	  | Code: |  	  | .................... #use i2c(Master,Slow=100000,I2C1,stream=I2C)
 *
 00018:  MOVLB  3D
 0001A:  BCF    x76.4
 0001C:  BCF    x78.7
 0001E:  BSF    x78.2
 00020:  MOVFFL @I2C_TRANSFER_OUT_HW_2471.P1+1,FSR0H
 00026:  MOVFFL @I2C_TRANSFER_OUT_HW_2471.P1,FSR0L
 0002C:  BTFSC  ??65535.0
 0002E:  BSF    x73.6
 00030:  BTFSS  ??65535.0
 00032:  BCF    x73.6
 00034:  MOVF   x6C,W
 00036:  BZ    003E
 00038:  MOVFFL POSTINC0,I2C1TXB
 0003E:  BSF    x73.5
 00040:  BTFSC  x73.5
 00042:  BRA    0040
 00044:  BTFSC  x76.4
 00046:  BRA    0058
 00048:  BTFSS  x78.5
 0004A:  BRA    0044
 0004C:  MOVF   x6C,W
 0004E:  BZ    0058
 00050:  MOVFFL POSTINC0,I2C1TXB
 00056:  BRA    0044
 00058:  BTFSC  ??65535.0
 0005A:  BRA    0062
 0005C:  BTFSC  x77.5
 0005E:  BRA    0058
 00060:  BRA    0066
 00062:  BTFSS  x73.3
 00064:  BRA    0062
 00066:  CLRF   @01
 00068:  BTFSC  x74.5
 0006A:  INCF   @01,F
 0006C:  MOVLB  0
 0006E:  RETURN 0
 
 | 
 |  |  
		|  |  
		| BrianC 
 
 
 Joined: 23 Apr 2022
 Posts: 11
 Location: UK
 
 
			    
 
 | 
			
				| 18F26K42 I2C |  
				|  Posted: Sun Apr 24, 2022 10:50 am |   |  
				| 
 |  
				| I have just compiled it with exactly the same #use line and get the following assembler. The first part replicates yours, but then there is a second part, if that gives you any clue ???? 
 Compiler 5.107
 
 .................... #use i2c(Master,Slow=100000,I2C1,stream=I2C)
 *
 00028:  MOVLB  3D
 0002A:  BCF    x76.4
 0002C:  BCF    x78.7
 0002E:  BSF    x78.2
 00030:  MOVFFL 0F,3FEA
 00036:  MOVFFL 0E,3FE9
 0003C:  BTFSC  0D.0
 0003E:  BSF    x73.6
 00040:  BTFSS  0D.0
 00042:  BCF    x73.6
 00044:  MOVF   x6C,W
 00046:  BZ    004E
 00048:  MOVFFL 3FEE,3D6B
 0004E:  BSF    x73.5
 00050:  BTFSC  x73.5
 00052:  BRA    0050
 00054:  BTFSC  x76.4
 00056:  BRA    0068
 00058:  BTFSS  x78.5
 0005A:  BRA    0054
 0005C:  MOVF   x6C,W
 0005E:  BZ    0068
 00060:  MOVFFL 3FEE,3D6B
 00066:  BRA    0054
 00068:  BTFSC  0D.0
 0006A:  BRA    0072
 0006C:  BTFSC  x77.5
 0006E:  BRA    0068
 00070:  BRA    0076
 00072:  BTFSS  x73.3
 00074:  BRA    0072
 00076:  CLRF   01
 00078:  BTFSC  x74.5
 0007A:  INCF   01,F
 0007C:  MOVLB  0
 0007E:  GOTO   00EE (RETURN)
 00082:  MOVLB  3D
 00084:  BCF    x76.4
 00086:  BCF    x78.3
 00088:  BSF    x78.2
 0008A:  BCF    x74.6
 0008C:  BSF    x74.7
 0008E:  MOVFFL 0F,3FEA
 00094:  MOVFFL 0E,3FE9
 0009A:  BSF    x73.5
 0009C:  BTFSC  x73.5
 0009E:  BRA    009C
 000A0:  BCF    x73.6
 000A2:  BTFSC  x76.4
 000A4:  BRA    00B6
 000A6:  BTFSS  x78.0
 000A8:  BRA    00A2
 000AA:  MOVFFL 3D6A,3FEE
 000B0:  MOVF   x6C,W
 000B2:  BZ    00B6
 000B4:  BRA    00A2
 000B6:  BTFSC  x78.0
 000B8:  MOVFFL 3D6A,3FEE
 000BE:  BTFSC  x77.5
 000C0:  BRA    00B6
 000C2:  CLRF   01
 000C4:  BTFSC  x77.3
 000C6:  BRA    00CC
 000C8:  BTFSC  x76.4
 000CA:  INCF   01,F
 000CC:  MOVLB  0
 000CE:  GOTO   0112 (RETURN)
 |  |  
		|  |  
		| BrianC 
 
 
 Joined: 23 Apr 2022
 Posts: 11
 Location: UK
 
 
			    
 
 | 
			
				| 18F26K42 I2C |  
				|  Posted: Sun Apr 24, 2022 11:08 am |   |  
				| 
 |  
				| In case it is silly error my part I have attached the source for the piece of test code that I have been using to get the i2c running. This part of the project was written 10 years ago using Microchip C18, so having to rewrite it all, so its been a while since visited this project. 
  	  | Code: |  	  | #include <18F26K42.h>
 #device ADC=12
 
 #FUSES NOWDT                    //No Watch Dog Timer
 #FUSES NOBROWNOUT               //No brownout reset
 
 //#device ICD=TRUE
 
 #use delay(internal=2000000)
 #pin_select SDA1=PIN_C4
 #pin_select SCL1=PIN_C3
 
 
 #use i2c(Master,Slow=100000,I2C1,stream=I2C)
 
 static int i2c_lcd_address = 0x7C;     //device I2C LCD address
 static char i2c_control = 0x00;
 static char i2c_data =0x00;
 
 //==========================================================================
 
 void WRITE_CODE(int8 i2c_control,int8 i2c_data)
 {
 
 i2c_transfer(I2C,i2c_lcd_address,i2c_control,i2c_data,3);
 }
 
 //====================================================================
 
 static void Initial_st7032()
 {
 
 WRITE_CODE(0x00,0x38);
 delay_us(300);
 WRITE_CODE(0x00,0x38);
 delay_us(300);
 WRITE_CODE(0x00,0x38);
 delay_us(300);
 WRITE_CODE(0x00,0x0c);
 delay_us(300);
 WRITE_CODE(0x00,0x01);
 delay_us(300);
 WRITE_CODE(0x00,0x39);
 delay_us(300);
 WRITE_CODE(0x00,0x14);
 delay_us(300);
 WRITE_CODE(0x00,0x76);
 delay_us(300);
 WRITE_CODE(0x00,0x5f);
 delay_us(300);
 WRITE_CODE(0x00,0x68);
 delay_us(300);
 WRITE_CODE(0x00,0x06);      //Incement, no shift
 delay_us(300);
 WRITE_CODE(0x00,0x0C);      //Display On, Cursor Off, Blink Off
 delay_us(300);
 //====================================
 WRITE_CODE(0x00,0x06);      //Incement, no shift
 delay_us(300);
 WRITE_CODE(0x00,0x0C);      //Display On, Cursor Off, Blink Off
 delay_us(300);
 }
 
 
 //-------------------------------------------------------------------------------------
 static void Write_Line1(unsigned char Position)
 {
 WRITE_CODE(0x00,(0x80+Position));   //0x80
 delay_us(30);
 
 }
 
 //-------------------------------------------------------------------------------------
 static void Write_Line2(unsigned char Position)
 {
 WRITE_CODE(0x00,(0xC0+Position));   //0x80
 delay_us(30);
 
 }
 
 //========================================================================
 
 void putr4XLCD(char *buffer)
 {
 while(*buffer)                  // Write data to LCD up to null
 {
 WRITE_CODE(0x40,*buffer); // Write character to LCD
 buffer++;               // Increment buffer
 }
 return;
 }
 
 
 //============================================================================
 
 void Display_Select_Option(void)
 {
 printf(WRITE_CODE," Select Option  ");
 delay_ms(20);
 Write_Line2(0x00);
 delay_ms(20);
 printf(WRITE_CODE,"Restart   NewRun");
 delay_ms(20);
 }
 
 //===========================================================================
 
 
 
 void main()
 {
 
 Initial_st7032();      //LCD Initialisation
 
 while(TRUE)
 {
 
 
 //TODO: User Code
 DisplayAgain:
 delay_ms(50);
 Write_Line1(0x00);
 Display_Select_Option();
 
 delay_ms(1000);
 
 Goto DisplayAgain;
 
 
 }
 
 }
 
 | 
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Apr 24, 2022 11:52 am |   |  
				| 
 |  
				| When I2C_transfer was first launched, you had to give it the total count, including the address byte. This was quickly revised, and the count
 now is just the length of the data, not the address as well.
 
 The function then expects to receive an address of an array of bytes
 containing what is to be sent, not separate integers.
 Then your count is larger than what you are asking it to send.
 
 Look at how I transfer the bytes into an array, and then pass the
 array to the function. Not two separate bytes.
 
 You are giving it more values than it expects, so with the overload,
 probably triggering a read as well.
 |  |  
		|  |  
		| BrianC 
 
 
 Joined: 23 Apr 2022
 Posts: 11
 Location: UK
 
 
			    
 
 | 
			
				| 18F26K42 I2C |  
				|  Posted: Sun Apr 24, 2022 12:15 pm |   |  
				| 
 |  
				| Point taken, but the reality is there is showing up on the i2c protocol analyser, not even a 'start' transition, so I doubt it is getting that far. When you run the code under debug it stops in a tight loop within the code for the #use statement. |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |