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

18F26K42 I2C [Solved]
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
BrianC



Joined: 23 Apr 2022
Posts: 11
Location: UK

View user's profile Send private message

18F26K42 I2C [Solved]
PostPosted: Sat Apr 23, 2022 8:30 am     Reply with quote

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: 8528
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Apr 23, 2022 8:51 am     Reply with quote

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: 18123

View user's profile Send private message

PostPosted: Sat Apr 23, 2022 9:56 am     Reply with quote

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

View user's profile Send private message

18F26K42 I2C
PostPosted: Sat Apr 23, 2022 10:28 am     Reply with quote

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: 18123

View user's profile Send private message

PostPosted: Sat Apr 23, 2022 1:18 pm     Reply with quote

Can you physically test the lines are high?.
What compiler version?.
BrianC



Joined: 23 Apr 2022
Posts: 11
Location: UK

View user's profile Send private message

18F26K42 I2C
PostPosted: Sat Apr 23, 2022 4:24 pm     Reply with quote

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: 18123

View user's profile Send private message

PostPosted: Sun Apr 24, 2022 3:11 am     Reply with quote

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

View user's profile Send private message

18F26K42 I2C
PostPosted: Sun Apr 24, 2022 3:52 am     Reply with quote

Many thanks,
I will have a look at this and see where it gets me.
temtronic



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

View user's profile Send private message

PostPosted: Sun Apr 24, 2022 5:22 am     Reply with quote

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: 18123

View user's profile Send private message

PostPosted: Sun Apr 24, 2022 7:07 am     Reply with quote

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: 18123

View user's profile Send private message

PostPosted: Sun Apr 24, 2022 8:09 am     Reply with quote

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

View user's profile Send private message

18F26K42 I2C
PostPosted: Sun Apr 24, 2022 10:50 am     Reply with quote

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

View user's profile Send private message

18F26K42 I2C
PostPosted: Sun Apr 24, 2022 11:08 am     Reply with quote

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: 18123

View user's profile Send private message

PostPosted: Sun Apr 24, 2022 11:52 am     Reply with quote

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

View user's profile Send private message

18F26K42 I2C
PostPosted: Sun Apr 24, 2022 12:15 pm     Reply with quote

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.
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