DeltaElectronics
Starting Member
- Total Posts : 53
- Reward points : 0
- Joined: 2016/06/24 07:25:46
- Location: 0
- Status: offline
I2C with PIC16F18323
Hello to everybody, I am trying to implement a simple I2C communication library as done in the following tutorials: https://www.electrosome.c...1_MSSP_Status_Registerhttps://www.teachmemicro.com/pic16-i2c/#So I decided to make a simple test circuit like the image file 'Immagine.png' And I write the following test code: #define _XTAL_FREQ 4000000
void I2C_Master_Init(const unsigned long speed) { SSP1CON1 = 0b00101000; SSP1CON2 = 0; SSP1ADD = (_XTAL_FREQ/(4*speed))-1; SSP1STAT = 0; TRISC0 = 1; //SCL TRISC1 = 1; //SDA }
void I2C_Master_Wait() { while ((SSP1STAT & 0x04) || (SSP1CON2 & 0x1F)); //Transmit is in progress }
void I2C_Master_Start() { I2C_Master_Wait(); SEN = 1; while (SEN); }
void I2C_Master_Repeated_Start() { I2C_Master_Start(); }
void I2C_Master_Stop() { I2C_Master_Wait(); PEN = 1; while(PEN); }
_Bool I2C_Master_Write(unsigned d) { I2C_Master_Wait(); SSP1BUF = d; //Write data to SSPBUF SSP1IF = 0; // while (!SSP1IF); return ACKSTAT; }
unsigned short I2C_Master_Read(unsigned short a) { unsigned short temp; I2C_Master_Wait(); RCEN = 1; I2C_Master_Wait(); temp = SSPBUF; //Read data from SSPBUF I2C_Master_Wait(); ACKDT = (a)?0:1; //Acknowledge bit ACKEN = 1; //Acknowledge sequence return temp; }
void main(void) { OSCCON1 = 0x60;; OSCFRQbits.HFFRQ = 0b011; TRISC4 =0; TRISC3 =0; I2C_Master_Init(100000); __delay_ms(3000); while(1) { LATCbits.LATC4 = 1; LATCbits.LATC3 = 0; I2C_Master_Start(); I2C_Master_Write(0x3C); I2C_Master_Stop(); __delay_ms(1000); LATCbits.LATC4 = 0; LATCbits.LATC3 = 1; I2C_Master_Start(); I2C_Master_Write(0x3E); I2C_Master_Stop(); __delay_ms(1000); } } But, while the two LEDS blinks regularly as a square wave at 0,5Hz & duty 50%, at SDA and SCK pins I never see anything when I attach them on my oscilloscope probes. Because it's been for many days now I am stuck on this problem, I will be very grateful to everybody will help me to solve this problems. Enclosed: file 'Immagine.png' the test circuit drawing file 'HelloI2C.zip' my test program and library DeltaElectronics
Attached Image(s)
|
ric
Super Member
- Total Posts : 24593
- Reward points : 0
- Joined: 2003/11/07 12:41:26
- Location: Australia, Melbourne
- Status: offline
Re: I2C with PIC16F18323
2019/06/05 16:54:07
(permalink)
☄ Helpfulby DeltaElectronics 2019/06/19 03:08:17
You neglected to switch RC0 and RC1 from analog to digital mode. This is always required when using analog capable pins on a PIC. Change _Bool I2C_Master_Write(unsigned d) { I2C_Master_Wait(); SSP1BUF = d; //Write data to SSPBUF SSP1IF = 0; // while (!SSP1IF); return ACKSTAT; } to _Bool I2C_Master_Write(unsigned char d) { I2C_Master_Wait(); SSP1IF = 0; SSP1BUF = d; //Write data to SSPBUF while (!SSP1IF); // wait until the transfer has completed return ACKSTAT; } as your version was reading ACKSTAT too early. Then, get your main code to check the return value. If it is 1, the slave did not respond to the transfer => you got a NAK. I also don't see the need to use "_Bool". Why not just use "unsigned char" or "bit" as the return value type.
post edited by ric - 2019/06/05 16:59:08
To get a useful answer, always state which PIC you are using!
|
DeltaElectronics
Starting Member
- Total Posts : 53
- Reward points : 0
- Joined: 2016/06/24 07:25:46
- Location: 0
- Status: offline
Re: I2C with PIC16F18323
2019/06/05 23:14:38
(permalink)
Hello ric, thanks for replying me... In the first version, I left this line WHILE (!SSP1F);
uncommented, but then I noticed that programs always blocks indefinitely on this line; i.e. SSP1F flag never turns to 1 but it still continues to stay at 0 value
you wrote You neglected to switch RC0 and RC1 from analog to digital mode. This is always required when using analog capable pins on a PIC. How to do it ? In the tutorials I read it is not indicated to do it, why ?
|
ric
Super Member
- Total Posts : 24593
- Reward points : 0
- Joined: 2003/11/07 12:41:26
- Location: Australia, Melbourne
- Status: offline
Re: I2C with PIC16F18323
2019/06/05 23:22:42
(permalink)
☄ Helpfulby DeltaElectronics 2019/06/19 03:08:31
Have you read the datasheet for your PIC device? Analog/digital on PORTC is controlled by the ANSELC register. Did you notice that I moved your line that clears SSPIF? You must clear it BEFORE you write to SSPBUF.
To get a useful answer, always state which PIC you are using!
|
DeltaElectronics
Starting Member
- Total Posts : 53
- Reward points : 0
- Joined: 2016/06/24 07:25:46
- Location: 0
- Status: offline
Re: I2C with PIC16F18323
2019/06/05 23:40:20
(permalink)
Another silly question... but, by default, it seems me that PORTC is digital, not analog. On RC4 and RC3 pins I attached two led which regularly blinks, without problems. So I should add the following lines ANSELC0 = 0; ANSELC1 = 0;
before to start I2C communications ?
|
ric
Super Member
- Total Posts : 24593
- Reward points : 0
- Joined: 2003/11/07 12:41:26
- Location: Australia, Melbourne
- Status: offline
Re: I2C with PIC16F18323
2019/06/05 23:47:11
(permalink)
DeltaElectronics Another silly question... but, by default, it seems me that PORTC is digital, not analog. What leads you to that conclusion? Examine the "Power On" status of the ANSELC register. If you are talking about being able to control the LEDs, that's an OUTPUT function, and has nothing to do with the INPUT mode (so long as you correctly write to LATC, and not PORTC, which you are doing.)
post edited by ric - 2019/06/05 23:59:09
To get a useful answer, always state which PIC you are using!
|
DeltaElectronics
Starting Member
- Total Posts : 53
- Reward points : 0
- Joined: 2016/06/24 07:25:46
- Location: 0
- Status: offline
Re: I2C with PIC16F18323
2019/06/05 23:59:26
(permalink)
Hello Ric, thanks you very much once again for your attention in helping me.... Surey I'll immediately try to do as you have suggested me when I will return back home (now I am at work); aniway I am very surprised because every tutorial I read (for esample the official Microchip AN735 http://ww1.microchip.com/downloads/en/appnotes/00735a.pdf) does not mention to change ANSELC register. Thank again for your help.
|
ric
Super Member
- Total Posts : 24593
- Reward points : 0
- Joined: 2003/11/07 12:41:26
- Location: Australia, Melbourne
- Status: offline
Re: I2C with PIC16F18323
2019/06/06 00:05:22
(permalink)
What device are those tutorials targeting? Many older PICs don't have analog capability on PORTC, so it wouldn't matter. Edit: I just checked. That App Note was written in 2000, i.e. nineteen years ago. Most new PIC16F devices now have analog capability on almost every pin.
post edited by ric - 2019/06/06 00:11:34
To get a useful answer, always state which PIC you are using!
|
mbrowning
USNA79
- Total Posts : 1564
- Reward points : 0
- Joined: 2005/03/16 14:32:56
- Location: Melbourne, FL
- Status: offline
Re: I2C with PIC16F18323
2019/06/06 00:10:48
(permalink)
You are presenting a 20 year old document as evidence but apparently are unwilling to study the datasheet which has nearly all the information you need for your very modern device. Amazing, but unfortunately common.
Follow ric’s advice and read the datasheet (and any errata) before messing with random “tutorials” from the last century.
|
DeltaElectronics
Starting Member
- Total Posts : 53
- Reward points : 0
- Joined: 2016/06/24 07:25:46
- Location: 0
- Status: offline
Re: I2C with PIC16F18323
2019/06/15 08:43:01
(permalink)
Hello to everybody, As previuosly suggested by @Ric and other, I modified my code as following void I2C_Master_Init(const unsigned long speed) { SSP1CON1 = 0b00101000; SSP1CON2 = 0; SSP1CON3 = 0b01100000; SSP1DATPPS = 0x13; SSP1CLKPPS = 0x12; INTCONbits.GIE = 1; SSP1ADD = (_XTAL_FREQ/(4*speed))-1; SSP1STAT = 0; ANSC0 = 0; ANSC1 = 0; TRISC0 = 1; //SCL TRISC1 = 1; //SDA } _Bool I2C_Master_Write(unsigned d) { I2C_Master_Wait(); SSP1BUF = d; //Write data to SSPBUF SSP1IF = 0; while (!SSP1IF); return ACKSTAT; }
But I noticed that code stops at this instruction while (!SSP1IF);
i.e. SSP1IF flag never sets... and at oscilloscope I continue to watch any I2C signal, only 5V. What's the problem ?
post edited by DeltaElectronics - 2019/06/15 09:15:20
|
1and0
Access is Denied
- Total Posts : 9989
- Reward points : 0
- Joined: 2007/05/06 12:03:20
- Location: Harry's Gray Matter
- Status: offline
Re: I2C with PIC16F18323
2019/06/15 10:36:12
(permalink)
Read Ric's Post #2 again carefully. Compare the code there with yours lines by lines.
|
DeltaElectronics
Starting Member
- Total Posts : 53
- Reward points : 0
- Joined: 2016/06/24 07:25:46
- Location: 0
- Status: offline
Re: I2C with PIC16F18323
2019/06/15 10:55:37
(permalink)
Hello @1and0My current code is here: //file i2c.h #include <xc.h> #include "config.h"
void I2C_Master_Init(const unsigned long speed) { SSP1CON1 = 0x28; SSP1CON1bits.SSPEN=1; SSP1CON2 = 0; SSP1CON3 = 0b01100000; INTCONbits.GIE = 1; PIR1bits.SSP1IF = 1; SSP1CON3bits.SCIE = 1; SSP1CON3bits.PCIE = 1;
SSP1ADD = (_XTAL_FREQ/(4*speed))-1; SSP1STAT = 0; ANSELC = 0x00; TRISC0 = 1; //SCL TRISC1 = 1; //SDA } void I2C_Master_Wait() { while ((SSP1STAT & 0x04) || (SSP1CON2 & 0x1F)); //Transmit is in progress }
void I2C_Master_Start() { I2C_Master_Wait(); SEN = 1; while (SEN); } void I2C_Master_Repeated_Start() { I2C_Master_Start(); } void I2C_Master_Stop() { I2C_Master_Wait(); PEN = 1; while(PEN); } _Bool I2C_Master_Write(unsigned d) { I2C_Master_Wait(); SSP1IF=0; SSP1BUF = d; //Write data to SSPBUF while (!SSP1IF); return ACKSTAT; } unsigned short I2C_Master_Read(unsigned short a) { unsigned short temp; I2C_Master_Wait(); RCEN = 1; I2C_Master_Wait(); temp = SSPBUF; //Read data from SSPBUF I2C_Master_Wait(); ACKDT = (a)?0:1; //Acknowledge bit ACKEN = 1; //Acknowledge sequence return temp; } /code]and /file main.c #include <xc.h> #include "config.h" #include "i2c.h" void main(void) { OSCCON1 = 0x60;; OSCFRQbits.HFFRQ = 0b011; TRISC4 =0; TRISC3 =0; I2C_Master_Init(100000); _Bool green = 1; while(1) { __delay_ms(500); if (green) { LATCbits.LATC4 = 1; LATCbits.LATC3 = 0; green = 0; } else { LATCbits.LATC4 = 0; LATCbits.LATC3 = 1; green = 1; } I2C_Master_Start(); I2C_Master_Write(0x3C); I2C_Master_Stop(); } }
but it continue stops at the following instruction
while (!SSP1IF);
and olnly a LED is on. If instaeas I commemt the infinete loop, two led regularly blinks, at oscilloscope display I see only two plain line.
post edited by DeltaElectronics - 2019/06/15 11:30:25
|
davekw7x
Entropy++
- Total Posts : 1827
- Reward points : 0
- Joined: 2012/01/16 12:01:07
- Location: Second star on the right, straight on till morning
- Status: offline
Re: I2C with PIC16F18323
2019/06/15 14:11:54
(permalink)
You must make both Output and Input PPS assignments for the I2C Signals: For example to use pin RC0 as I2C SCL and RC1 as I2C SDA: Assign Output Pins: Look at the Register 13-2 description in the Data sheet to see values for pins RC0 and RC1 on the right hand side. I use binary notation right off of the data sheet instead of hex; use whatever suits your fancy, but make sure to get it right! RC0PPS = 0b?????; // SCL1 output sent to RC0 RC1PPS = 0b?????; // SDA1 output sent to RC1
You must assign the same pins to I2C input signals. Look in Table 13-1 to see values for SCL1 and SDA1 SSP1CLKPPS = 0b?????; // RC0 sent to SCL1 input SSP1DATPPS = 0b?????; // RC1 sent to SDA1 input
Regards, Dave
post edited by davekw7x - 2019/06/15 18:23:28
Attached Image(s)
Sometimes I just can't help myself...
|
DeltaElectronics
Starting Member
- Total Posts : 53
- Reward points : 0
- Joined: 2016/06/24 07:25:46
- Location: 0
- Status: offline
Re: I2C with PIC16F18323
2019/06/17 09:48:33
(permalink)
@davekw7x Like this void I2C_Master_Init(const unsigned long speed) { SSP1CON1 = 0x28; SSP1CON1bits.SSPEN=1; SSP1CON2 = 0; SSP1CON3 = 0b01100000; SSP1DATPPS = 0x13; SSP1CLKPPS = 0x12; INTCONbits.GIE = 1; PIR1bits.SSP1IF = 1; SSP1CON3bits.SCIE = 1; SSP1CON3bits.PCIE = 1; RC0PPSbits.RC0PPS = 0x19; //RC0->SDA1 RC1PPSbits.RC1PPS = 0x18; //RC1->SCL1*/ SSP1DATPPS = 0x11; SSP1CLKPPS = 0x10; SSP1ADD = (_XTAL_FREQ/(4*speed))-1; SSP1STAT = 0; ANSELC = 0x00; TRISC0 = 1; //SCL TRISC1 = 1; //SDA }
I just tried, but nothing happens.
post edited by DeltaElectronics - 2019/06/17 09:50:58
|
davekw7x
Entropy++
- Total Posts : 1827
- Reward points : 0
- Joined: 2012/01/16 12:01:07
- Location: Second star on the right, straight on till morning
- Status: offline
Re: I2C with PIC16F18323
2019/06/17 10:44:52
(permalink)
☼ Best Answerby DeltaElectronics 2019/06/19 03:07:50
DeltaElectronics ...nothing...
Here are your assignments with my comments on the right RC0PPSbits.RC0PPS = 0x19; //RC0->SDA1 <--- 0b11001: SDA output to RC0 RC1PPSbits.RC1PPS = 0x18; //RC1->SCL1*/ <--- 0b11000: SCL output to RC1 SSP1DATPPS = 0x11; // <--- 0b10001: RC1 to SDA input SSP1CLKPPS = 0x10; // <--- 0b10000: RC0 to SCK input
Bottom line: Which is SCL and which is SDA? Assignments must be consistent. Note that, for this particular chip,you don't have to make assignments to default input PPS functions, but I always put them there for documentation purposes. Not all devices have the default input assignments, and sometimes I use other than default pins. Putting the instructions as a Placeholder makes it easier for me to see the setup in case I want to change anything. But you gotta get it right! You always have to make output PPS pin assignments. [ /Begin Edit] Please clean up your code. Superfluous instructions make debugging a bigger nightmare than you (or I) deserve. For starters, remove these SSP1CON3 = 0b01100000; // <--- Why the heck are you messing with these "slave-only" bits? SSP1DATPPS = 0x13; // <--- Incorrect and Superfluous; overwritten by later instruction SSP1CLKPPS = 0x12; // <--- Incorrect and Superfluous; overwritten by later instruction
[ /End Edit] Regards, Dave
post edited by davekw7x - 2019/06/17 17:10:30
Sometimes I just can't help myself...
|
DeltaElectronics
Starting Member
- Total Posts : 53
- Reward points : 0
- Joined: 2016/06/24 07:25:46
- Location: 0
- Status: offline
Re: I2C with PIC16F18323
2019/06/19 03:07:00
(permalink)
@davekw7x Tombola !!!! Or better 'Bingo' as you americans calls this italian game :-) It works fine; thank you very much for your comments very helpful. Another silly question: As it seems me to understand reading from DS and you comments, it seems me there is the possibility to choose fon whic MCU pins put I2C clk and sda; i.e. for example this chunk of code
RC2PPSbits.RC2PPS = 0x19; //RC2->SDA1 <--- 0b11001: SDA output to RC2 RC3PPSbits.R31PPS = 0x18; //RC3->SCL1*/ <--- 0b11000: SCL output to RC3 SSP1DATPPS = 0b10010; // <--- 0b10001: RC2 to SDA input SSP1CLKPPS = 0b10011; // <--- 0b10000: RC3 to SCK input [/code] configures SDA channel on RC2 and CLK one on RC3; right ? But in reading from table 2 PIN Allocation Table, it seems that only RC0 can be dedicated to SDA channel and RC1 to CLK. It puzzles me a lot !!!Smile: 
|
pcbbc
Super Member
- Total Posts : 1381
- Reward points : 0
- Joined: 2014/03/27 07:04:41
- Location: 0
- Status: online
Re: I2C with PIC16F18323
2019/06/19 04:57:43
(permalink)
DeltaElectronicsTombola !!!! Or better 'Bingo' as you Americans calls this Italian game :-) No, in Britain we say "Bingo" when we finally get something right also, and it is also used for the name of the Italian "Tombola" game. Tombola is a completely different game for both US and UK. Seems there has been a mix-up coming over to the British English. So not just an American misunderstanding.
|
ric
Super Member
- Total Posts : 24593
- Reward points : 0
- Joined: 2003/11/07 12:41:26
- Location: Australia, Melbourne
- Status: offline
Re: I2C with PIC16F18323
2019/06/19 06:46:35
(permalink)
DeltaElectronics ... Another silly question: As it seems me to understand reading from DS and you comments, it seems me there is the possibility to choose fon whic MCU pins put I2C clk and sda; i.e. for example this chunk of code ... configures SDA channel on RC2 and CLK one on RC3; right ? Yes But in reading from table 2 PIN Allocation Table, it seems that only RC0 can be dedicated to SDA channel and RC1 to CLK. It puzzles me a lot !!!Smile: 
No it doesn't. Read "Note 4" underneath. You can use any pin, but you are restricted to TTL/ST voltage levels if you use the other pins. RC0 and RC1 support I2C/SMBUS specific voltage thresholds. If you're just using 5V I2C, then it really doesn't matter.
To get a useful answer, always state which PIC you are using!
|
davekw7x
Entropy++
- Total Posts : 1827
- Reward points : 0
- Joined: 2012/01/16 12:01:07
- Location: Second star on the right, straight on till morning
- Status: offline
Re: I2C with PIC16F18323
2019/06/19 06:54:48
(permalink)
[Edit]Ric beat me to it. Oh, well...[/Edit] DeltaElectronics But in reading from table 2 PIN Allocation Table, it seems that only RC0 can be dedicated to SDA channel and RC1 to CLK. It puzzles me...
Look at note (4) at the bottom of the table: 4: These pins are configured for I2C logic levels as described in Section 13.3 “Bidirectional Pins”; clock and data signals may be assigned to any of these pins. Assignments to the other pins (e.g., RA5) will operate, but logic levels will be standard TTL/ST as selected by the INLVL register.
The specially-dedicated SDA and SCL pins have slightly different electrical characteristics specifically tailored to I2C/SMB signals, but in my experience, using PPS to select other pins with standard logic levels is no problem with my usual connections. Regards, Dave Footnote: Never heard of Trombola. My slightly younger nephew would probably say, "Right on!" My slightly older brother would probably say, "Huzzah!" I just say, "Whew!"
post edited by davekw7x - 2019/06/19 07:03:03
Sometimes I just can't help myself...
|