• AVR Freaks

AnsweredHot!PIC18F45K50 & I2C - Need Help Getting Up and Running

Page: 12 > Showing page 1 of 2
Author
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
2020/06/03 19:12:42 (permalink)
0

PIC18F45K50 & I2C - Need Help Getting Up and Running

Hi,
I have been playing around with trying to get I2C running with a device without luck.  The first thing I want to check is whether I have the controller configured correctly.  In reading through the manual (page 238 specifically) I noticed something concerning.  Data is supposed to be shifted out of SSPBUF simply after being loaded.  I am not even seeing this.  After a write operation the SSPBUF still retains the contents that were pushed to it.  In any case, hoping someone can give this a browse over and let me know if something is obviously wrong with the functions or initialization.  Additionally looked around for a pre-built I2C library for this chip and could not find one.  If something debugged exists out there that is a welcome alternative.
 
void I2C_As_Master_Init(unsigned long int clock_freq) {
TRISB |= 0b00000011; //SCL and SDA configured as input pins
SSPCON = 0b00101000; //4: <3:0> I2C master mode
SSPCON2 = 0;
SSPADD = (_XTAL_FREQ/(4*clock_freq)) - 1; //set SCL clock frequency
SSPSTAT = 0;
//SSPIF = 0;
}
void I2C_As_Master_Wait(void) {
while (( SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 )); //Check transmission status
}
void I2C_As_Master_Start(void) {
SEN=1; //Initiate start condition
I2C_As_Master_Wait(); //Wait for completion
}
void I2C_As_Master_Write(unsigned char data) {
I2C_As_Master_Wait();
SSPBUF = data;
}
unsigned char I2C_As_Master_Read(unsigned short acknowledge) {
unsigned short temp = 0;
I2C_As_Master_Wait();
RCEN=1; //Enable receive as master
I2C_As_Master_Wait();
temp = SSPBUF;
I2C_As_Master_Wait();
ACKDT = (acknowledge)?0:1;
//while(!BF); //Wait till buffer is full
ACKEN = 1;
return temp;
}
void I2C_As_Master_Stop(void) {
I2C_As_Master_Wait();
PEN=1; //Initiate Stop condition
//mssp_wait(); //Wait till completion of event
//SSPEN=0; //Disable I2C operation
}
void I2C_As_Master_RepeatedStart(void) {
I2C_As_Master_Wait();
RSEN=1; //Initiate restart condition
 
//Then usage goes something like this in main().
 
I2C_As_Master_Init(100000);  //one shot initialization
 
//loop activity
I2C_As_Master_Start();
I2C_As_Master_Write(0b00111010); //call to accelerometer as write
I2C_As_Master_Write(0x06); //specify accelerometer register to read
I2C_As_Master_RepeatedStart(); //repeated start for single byte read
I2C_As_Master_Write(0b00111011); //LSB true indicating read
I2C_read = I2C_As_Master_Read(1); //read data, specify yes for ACK
I2C_As_Master_Stop();
#1
ric
Super Member
  • Total Posts : 27629
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/03 19:40:45 (permalink)
+1 (1)
IBrokeIt
...
I noticed something concerning.  Data is supposed to be shifted out of SSPBUF simply after being loaded.  I am not even seeing this.  After a write operation the SSPBUF still retains the contents that were pushed to it. 

Where in the datasheet does it say it won't?
What did you expect to see afterwards? Zero?
Ignore this test, it's not telling you anything useful.
 
Most of the code looks ok, but there's a couple of things you should be doing.
[1] You don't show any code switching the RB0 and RB1 pins from analog to digital mode. This is needed.
[2] Your I2C_As_Master_Start() function is not testing for a "bus collision", which it would have detected if the pins were in analog mode.
[3] Your I2C_As_Master_Write() function is not checking the ACK/NAK response from the Slave.
 
Here's some fairly generic example code I wrote to access an RTC chip via I2C.
http://picforum.ric323.co...pic.php?f=76&t=755
This is on a PIC16F877A, but the peripherals are very similar.
Note, I prefer to wait for each specific operation to complete, rather than putting a generic wait operation BEFORE each action.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#2
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/04 18:59:35 (permalink)
0
Thanks for pointers.  I did notice I made a big mistake due to incorrect #define _XTAL_FEEQ = 1000000 (which wasn't visible).  Would have been way too fast.  I used a fixed value of 39 for SSPADD now which with FOSC = 16 MHz should give me my desired 100kHz.  I used your version of start() to be safe.  I also put a latch in the program with both counter and bus_collision initialized to 0.  At any point in time I can pause and watch variables.  Counter = 1 and bus_collision = 95 without exception.  You appear to have been correct about collision.
 
if (bus_collision != 95) {
   counter++;
   if (I2C_As_Master_Start()) {
      bus_collision = 95;
   }
}
 
Also not done in the original (although the register was initialized for discrete inherently by chance) I am now forcing ANSELB = 0.  Beyond that I am reading through the manual and see a note that if at the beginning of the start condition the SDA and SCL pins are already sampled low...[other low conditions]...a bus collision interrupt is thrown.  So now (haven't had chance to break out scope yet due to probe disappearing) I am curious as to if there may be any other configuration settings for the PIC that I may be missing that could be causing this before I start looking at circuit and if something is broken there.  I'm pretty sure I have this wired up correctly, and according to the device I am trying to interface with, it can only ever function in slave mode.  No other masters on the bus to conflict with so can rule that out as well.
 
Not making it through start from the get go.
 
#3
ric
Super Member
  • Total Posts : 27629
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/04 19:05:26 (permalink)
+1 (1)
Sure you have pullups on both SDA and SCL?
You're working blind until you hook up the scope. That is an essential to fault find an I2C connection.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#4
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/04 19:44:06 (permalink)
0
Pretty sure.  Using an Adafruit MMA845 breakout and according to print it has a 3.3-5V level shifting circuitry.  PIC is powered via USB at 5V reference.  Powering down, disconnecting SDA and SCL from PIC, then powering up I am reading an initialization of the Adafruit device to a 5V logic level on both pins with a voltmeter.  So it appears 10k pull ups to reference and everything is at least wired OK.  Comment program segment that calls for I2C out outside of initialization routine.  Connecting breakout back to PIC I get a high logic level of 4.65V sitting idle on both pins.  Looks OK.  Insert code and run through debug mode again.  SCL sits at 5V.  SDA is held at 0V.  Same bus collision flag.  All I can test are initial conditions right now but from what I can see, breakout slave board is functioning OK isolated, and system initializes to what I would expect with only I2C initialization routine.  I2C start call then added back in and boom.
 
Yup, I'm dead in the water without a scope I think.  I don't know if somehow simply running in debug mode could be contributing to this.  Time to go find a probe.
#5
davea
Super Member
  • Total Posts : 240
  • Reward points : 0
  • Joined: 2016/01/28 13:12:13
  • Location: Tampa Bay FL USA
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/04 22:23:54 (permalink)
0
You could sample the 2 ports
in the middle of read/write
then using 4 counters, record the # of high and low state
and see if there stuck in one state 
 
#6
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 17:47:25 (permalink)
0
Does anyone know how to insert a photo into the chat box?  Connected scope finally and I tried inserting image but it only accepts a URL so I can't get a desktop image in.  In any case what I am observing is a nominal 0V logic level for both SDA and SCL.  Every 6 ms I am showing that SDA transitions from a 0V to a 5V logic level for a total of 20 us.  Half way through that SDA high I see SCL go high for the same 20 us duration.  So basically two square waves of 20 us duration with rising edge of SCL lagging rising edge of SDA by 10 us.  It does this repeatedly.  Nothing else detectable.
#7
ric
Super Member
  • Total Posts : 27629
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 17:54:59 (permalink)
0
IBrokeIt
Does anyone know how to insert a photo into the chat box?  Connected scope finally and I tried inserting image but it only accepts a URL so I can't get a desktop image in.

Don't use the "Quick Reply" box.
Click the "(Open Full Version)" link just to the right, then use the "Attach image" button.
 
Can you post your entire test program?
It sounds like you have watchdog resets occuring.
SDA and SCL should idle high, and only pulse low when active.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#8
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 18:01:01 (permalink)
0
Picture of scope.

Attached Image(s)

#9
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 18:02:56 (permalink)
0
Beyond this I can't submit the full program.  I think it is too long and getting rejected.
#10
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 18:06:54 (permalink)
0
void DO_Init(void) {
__delay_ms(50); //give PLL time to lock
TRISD = 0b00000000; //PORTD 0 = output, 1 = input
TRISC = 0b00000000;
ANSELB = 0b00000000;
//Timer 0 settings
T0CONbits.TMR0ON = 1; //Enable timer 0
T0CONbits.T08BIT = 0; //Set 16 bit timer
T0CONbits.T0CS = 0; //Set internal instruction cycle clock
T0CONbits.T0SE = 0; //Falling edge on T0CKI (unused for internal)
T0CONbits.PSA = 0; //Pre-scaler; 0 = ON, 1 = OFF
T0CONbits.T0PS0 = 0b111; //000 = 1:2, 111 = 1:256
//INTCONbits.T0IE = 1; //Enable interrupt on TMR0 overflow
//INTCONbits.TMR0IE = 1;
//INTCONbits.GIE = 1;
//INTCON2bits.TMR0IP = 0; //Interrupt priority, 1 = high


OSCCON = 0b01110000; //0b01010100;

UCON = 0b01101100;
UCFGbits.FSEN = 1; //Enable full speed usb - 48 MHZ clock
UCFGbits.PPB = 0b00; //Even/odd ping pong buffers
UCFGbits.UPUEN = 1; //Set on chip pull up to enable
UCFGbits.UTRDIS = 0; //On-chip transceiver active
UCFGbits.UTEYE = 0; //Enable eye pattern test - never enable in actual USB use
//OSCCON2 = 0b10010111;
//CONFIG1L = 0b00000000;
//T1CON = 0x01; //Configure Timer1 interrupt
//PIE1bits.TMR1IE = 1;
//INTCONbits.PEIE = 1; //Peripheral interrupts enabled
//RCONbits.IPEN=0x01;
//IPR1bits.TMR1IP=0x01; // TMR1 high priority ,TMR1 Overflow Interrupt Priority bit
//INTCONbits.GIE = 1;
//PIR1bits.TMR1IF = 0;
}
void I2C_As_Master_Init(unsigned long int clock_freq) {
TRISB |= 0b00000011; //SCL and SDA configured as input pins
SSPCON = 0b00101000; //4: <3:0> I2C master mode
SSPCON2 = 0;
SSPADD = 39; //set SCL clock frequency
SSPSTAT = 0;
//SSPIF = 0;
//SSPCONbits.SSPEN = 1;
}
void I2C_As_Master_Wait(void) {
while (( SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 )); //Check transmission status
}
__bit I2C_As_Master_Start(void) {
BCLIF = 0;
SEN=1; //Initiate start condition
while (SEN);
return BCLIF;
//I2C_As_Master_Wait(); //Wait for completion
}
void I2C_As_Master_Write(unsigned char data) {
SSPBUF = data;
I2C_As_Master_Wait();
}
unsigned char I2C_As_Master_Read(unsigned short acknowledge) {
RCEN=1; //enable receive
ACKDT = (acknowledge)?0:1; //choose NAK, ACK
while (RCEN); //while awaiting receive
//I2C_As_Master_Wait();
ACKEN = 1; //enable acknowledgment receipt
while (ACKEN);
//I2C_As_Master_Wait();
//while(!BF); //Wait till buffer is full
return SSPBUF;
}
void I2C_As_Master_Stop(void) {
PEN=1;
while (PEN);
I2C_As_Master_Wait();
//mssp_wait(); //Wait till completion of event
//SSPEN=0; //Disable I2C operation
}
void I2C_As_Master_RepeatedStart(void) {
RSEN=1; //Initiate restart condition
while (RSEN);
//I2C_As_Master_Wait();
}
#11
ric
Super Member
  • Total Posts : 27629
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 18:07:09 (permalink)
0
You can zip the file and attach it to a message like you did the image.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#12
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 18:08:03 (permalink)
0
The above is my initialization.  Then I basically call this in main() and obtain the results I posted.
I2C_As_Master_Start();
 
#13
ric
Super Member
  • Total Posts : 27629
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 18:09:52 (permalink)
0
Can't see your config bits.
It is much more useful for us to see the entire program.
Then we know what you really did, not just what you think you did...
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#14
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 18:21:58 (permalink)
0
I'm really struggling here.  When I zip my project.X it comes back at 2.4MB.  The max file transfer size allowable is 500KB.  Does this help at all?

Attached Image(s)

#15
ric
Super Member
  • Total Posts : 27629
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 18:36:39 (permalink) ☼ Best Answerby IBrokeIt 2020/06/13 17:56:13
0
You only need the source files (C and H), not everything.
As I guessed, you have the WDT turned on.
If you don't have code specially triggering it regularly, it will be resetting your PIC at rapid intervals.
Turn it off until you understand how it works and how to feed it.
i.e. set WDTEN to OFF
 
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#16
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 19:07:44 (permalink)
0
I am using a USB CDC library.  That and supporting files are 2.4 MB.  Understand you are trying to get at config information.  Do you need the USB CDC files as well?  I tried generating the #pragma statement from the config tool to write the WDT to off but it refused to compile stating the software enable was on or something.  That brings up another question.  Understand all config registers are laid out in the user manual.  However when using the MPLAB X C library, is there a 1:1 mapping between the nomenclature required in the programming vs. what it represents in the user manual?
#17
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 19:25:08 (permalink)
0
This should be the whole thing with a picture of the config tree.
#18
Gort2015
Klaatu Barada Nikto
  • Total Posts : 3937
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/08 21:23:29 (permalink)
0
I think it is more likely the wiring.
 
Start:
Check the P bit in STAT, if it is clear then the
bus is in use.  If set then assert "start"
 
Stop:
Wait until i2c flags ($1F) are not busy.
Assert "stop"
 
Bus collision, if there is only 1 Master
then it cannot happen.
 

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#19
IBrokeIt
Starting Member
  • Total Posts : 42
  • Reward points : 0
  • Joined: 2019/08/13 12:07:00
  • Location: 0
  • Status: offline
Re: PIC18F45K50 & I2C - Need Help Getting Up and Running 2020/06/13 17:55:44 (permalink)
0
ric, you were correct about the watchdog timer.  I finally got around to trying this out again but had a cryptic error about the WDT being set to software on control.  Turns out I had an include file that was forcing this on outside of my awareness of what I thought was my only set configuration bits routine.  Looks like this is a one shot define and if you try to subsequently overwrite it the compiler yells at you.  I am able to turn it off and on and switch between working and not working like clockwork.  I can also trace the bit values that I am sending on scope and looks fine so win.  I have one more issue in that it looks like my startup and write routines are working but my read causes the processor to sit in an infinite loop, but I can go back and debug that as there is probably some device specific slave condition I am violating.  Only question I have now is why does the watchdog timer bomb this out?
#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2020 APG vNext Commercial Version 4.5