View previous topic :: View next topic |
Author |
Message |
Woody
Joined: 11 Sep 2003 Posts: 83 Location: Warmenhuizen - NL
|
i2c_transfer and PIC18F55Q43 |
Posted: Mon Mar 29, 2021 7:01 am |
|
|
Hi all,
I am trying to get i2c running on this chip, to talk to a Sensirion SHT31-DIS temp and RH sensor.
I read the posts on this forum regarding the common pitfalls using the i2c modules on recent PICs but even with that info I cannot get i2c to work on this chip.
I distilled the problem to this:
Code: |
#include <18F55Q43.h>
#device ADC=12
#FUSES NOWDT //No Watch Dog Timer
#use delay(oscillator=18432000)
#pin_select SDA1=PIN_C4
#pin_select SCL1=PIN_C3
#use i2c(Master,Fast, I2C1)
#define LED_Y PIN_D6
#define DELAY 500
#define SHT31_I2C_ADDRESS 0x44
int8 wdata[2] = {0x30,0xa2};
void main()
{
while(TRUE)
{
output_low(LED_Y);
i2c_transfer(SHT31_I2C_ADDRESS, wdata, sizeof(wdata)+1);
output_high(LED_Y);
while(1);
}
}
|
Compiler version 5.103
The sensor has address 0x44. The command I try to submit is a two-byte command, a reset. Both SDA and SCL are pulled up to 3v3 by a 2k resistor.
When I run the code the yellow led comes on and stays on. On my scope I see (what looks like a) a start condition: SDA drops to 0, then 360 ns later SCL drops to 0. I see what looks like 2 clock pulses (~750kHz) on SCL after which both SDA and SCL return to 3v3. Nothing else happens.
The PCB is a new prototype. The 2x2mm chip has all its connections correctly wired. I tried a second PCB which gives me the same outcome. That does not mean that it could not be the source of the problem but the main issues are checked.
I tried a number of options on #USE i2c; force_hw, sda/scl= etcetera, but to no avail. What I am a bit uncertain about is: am I right in assuming that I should see a train of bits on SDA being clocked to the sensor, whether this is connected correctly or not? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
Woody
Joined: 11 Sep 2003 Posts: 83 Location: Warmenhuizen - NL
|
|
Posted: Mon Mar 29, 2021 7:40 am |
|
|
I added
Code: | #pin_select SCL1OUT = PIN_C3
#pin_select SCL1IN = PIN_C3
#pin_select SDA1OUT = PIN_C4
#pin_select SDA1IN = PIN_C4
|
and that made no difference. Same outcome on the scope. The program hangs on the i2c_transfer.
btw I also tried i2c_transfer_out(), with the same outcome. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Mon Mar 29, 2021 7:53 am |
|
|
One key thing wrong:
Quote: |
The sensor has address 0x44
|
No it doesn't.....
Key thing. Difference between a 7bit I2C address and an 8bit PIC I2C
address.
The 0x44, is the upper 7 bits of the address byte.
In PIC terms, this is address 0x88.
This is why we repeatedly suggest that people always start with PCM
programmer's I2C test program, and verify what address their device is
actually on....
Last edited by Ttelmah on Mon Mar 29, 2021 7:54 am; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Mar 29, 2021 7:54 am |
|
|
Quote: |
#define SHT31_I2C_ADDRESS 0x44 |
It's my belief that this is the 7-bit address. CCS uses 8-bit addresses.
So you should change it to 0x88. |
|
|
Woody
Joined: 11 Sep 2003 Posts: 83 Location: Warmenhuizen - NL
|
|
Posted: Mon Mar 29, 2021 8:04 am |
|
|
I'll look at that suggestion later tonight, unfortunately I have to run now.
I was toying with the i2C clock settings and I2C Pad Rxy Control Register settings and then suddenly got a consistent signal on SCL.
Thanks for your suggestions!
Paul |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Mon Mar 29, 2021 8:29 am |
|
|
Download PCMP's I2C scanner program from theh 'code library' !
Use it to 'find' any I2C devices. It'd report 0x88, not 0x44, as CCS uses 8 bit addresses not 7 bit, as others have said.....
I prefer 8 bit mode, makes more sense to me..... |
|
|
Woody
Joined: 11 Sep 2003 Posts: 83 Location: Warmenhuizen - NL
|
|
Posted: Mon Mar 29, 2021 1:08 pm |
|
|
Tried the scanner a couple of days ago. It starts and then returns "nothing found". That is when I got the scope out.
With the scanner code as well as my own code I just do not see _any_ traffic on either SDA or SCL. So far nobody told me that that is expected; I think that no matter what you attach to the I2C bus, as long as I have some pullups connected I should see some traffic when a master device sends something to a slave.
But I could be mistaken. I was mistaken about the address needed to shift left |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Mon Mar 29, 2021 2:28 pm |
|
|
hmmm.. I don't use that PIC , or any with PPS, but...
providing there are pullups( 4k7 for 5V, 3k3 for 3V), you should see squiggles on a scope !
Maybe the compiler doesn't route the I2C pins to the I2C correctly with PPS ??
Then there's the 5v PIC vs 3V peripheral device problem..... Most 'peripheral modules' today are 3 volt devices and may not be signal compatible with a 5 volt PIC. The datasheet may say '5 volt tolerant' but that just means no black magic smoke will occour.
others who do this for a living will KNOW....I'm jes a dinosaur these dayze.... |
|
|
Woody
Joined: 11 Sep 2003 Posts: 83 Location: Warmenhuizen - NL
|
|
Posted: Mon Mar 29, 2021 2:31 pm |
|
|
It now works.
This has something to do with timing. I selected tmr2 as the clock source in the #use i2c() and that got me nice pulses on both SDA and SCL. And data to and from the SHT31 (on address 0x88). I can vary tmr2 to increase or decrease the I2C speed. If I remove the clock_source statement, everything stops.
Apparently I _need_ to state the clock source in the #use statement otherwise I end up with no (or too fast) an I2C clock.
Paul |
|
|
Woody
Joined: 11 Sep 2003 Posts: 83 Location: Warmenhuizen - NL
|
|
Posted: Mon Mar 29, 2021 2:41 pm |
|
|
temtronic wrote: | hmmm.. I don't use that PIC , or any with PPS, but...
providing there are pullups( 4k7 for 5V, 3k3 for 3V), you should see squiggles on a scope |
That was my idea too. Although you may forget the pullups with this chip; it has them on the I2C pins, selectable. Which btw set me on the solution, as I was toying with the pullup and slew rate settings I started to get at least a couple of 'squiggles' on the scope. Which made me wonder about the I2C clock speed.
Quote: |
others who do this for a living will KNOW....I'm jes a dinosaur these dayze.... |
Not to worry, we all will be sooner or later |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Mon Mar 29, 2021 4:19 pm |
|
|
hmm, never thought about the I2C clock speed....as I tend to test my PICs at 8MHz, only bump it up if I need to....probably explains why everything works for me...doesn't exceed 'speed limits'
The 'peripheral device' might only be good to say 400KHz. Some newer chips 1MHz ??
dang, waaay too much to read
sure happy it's 'up and running' !
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Tue Mar 30, 2021 1:09 am |
|
|
General thing is to always specify the clock rate you want in the #use.
The compiler always tends to select the fastest rate supported by the
clock it is using. This is often faster than the hardware actually supports.
Now in this case, the poster talks about the lines having 2K resistors. On
3.3v I2c, these would support 400KHz up to about 150pF. So these are
'OK', provided there is not too much track/wire present. Going above
400K, requires active pull-ups.
So first thing is to ensure that the compiler is not selecting above 400K
So:
FAST=400000
in the #use.
Then as you haver already been told, the address needs to be 0x88 in
the PIC code.
Then, this is one of the nasty modern chips that doesn't have the MSSP
module, instead having the separate I2C peripheral. These are very
annoying to work with. One key thing is that the chip has slew rate
limiting on a per pin basis, not on the standard I2C basis. By default
this will be enabled.
Quote: |
Important: The pin locations for SDA and SCL are remappable through the Peripheral Pin Select (PPS)
registers. If new pin locations for SDA and SCL are desired, user software must configure the INLVLx,
SLRCONx, ODCONx, and TRISx registers for each new pin location. The RxyI2C registers cannot be
used since they are dedicated to the default pin locations. Additionally, the internal pull-ups for non-I2C
pins are not strong enough to drive the pins; therefore, external pull-up resistors must be used
|
So the slew rate control has to change according to what pin is used. Now
I would suspect that this might well cause the compiler issues. Is it using
the I2C RxyI2C slew rate setting, or the SLRCONx setting?. You are on
the default pins, so the former needs to be used. I'd therefore say that
you should set this manually. So:
Code: |
#byte ODCCON=getenv("SFR:ODCCON")
#byte RC4I2C=getenv("SFR:RC4I2C")
#byte RC3I2C=getenv("SFR:RC3I2C")
#define 400KI2C 0x61
//then after the compiler I2C setup, before using the port, add:
RC4I2C=400KI2C;
RC3I2C=400KI2C;
bit_set(ODCCON,3);
bit_set(ODCCON,4); //these two explicitly set the pins as OD drive
|
Now the first two settings program C3 and C4 for 400KI2C. The last two
explicitly set the pins to open drain drive.
The data sheet says:
Quote: |
Important: It is necessary to set open-drain control when using the pin for I2C.
|
This latter differs from older chips, where you simply had to set the pins
as inputs. Hence worth setting this yourself...
These should get rid of any potential compiler problems with the oddities on
this chip!... |
|
|
Woody
Joined: 11 Sep 2003 Posts: 83 Location: Warmenhuizen - NL
|
|
Posted: Tue Mar 30, 2021 1:34 pm |
|
|
Hi ttelmah,
This problem is not completely solved yet
Turns out that as soon as I remove my scope leads (yes, set for 10x) the second value from the SHA31 fails to read in. And every now and then the entire i2c_transfer hangs (yellow led is lit instead of flashing). And sometimes it works.
I am on the default pins. After consulting the data sheet it looked like a splendid idea not to pps them to other pins, to prevent problems...
I had the
Code: |
byte SDA_CONTROL=getenv("SFR:RC4I2C")
#byte SCL_CONTROL=getenv("SFR:RC3I2C")
|
figured out earlier; I had them both set for 0xc1 (fast mode+ and no pullup, as these are in the circuit and that circuit is only 3 inches long) instead of your 0x61 suggestion. Using the latter also hangs up the i2c_transfer. 0xc1 worked quite nicely, that is, until I removed the scope leads
It might mean that the 2k pullups, although not too stupid a guess, are out of range here.
Your suggestion of
Code: |
#byte ODCON=getenv("SFR:ODCON")
bit_set(ODCON,3);
bit_set(ODCON,4);
|
(ODCCON is a bad SFR name according to my compiler)
made no difference that I could see.
And finally the option fast=400000 in the #use statement does not seem to do anything. If set by itself I measure frequencies well in excess of 1.3MHz on the few erratic SCL pulses I then see on the scope. The only way I found to get the frequency down to 400K or lower is using the clock_source=tmr2 statement in the #use i2c, and then set the timer2 frequency.
Somehow it looks like the compiler does not do anything with the 'fast=xxxx' option. or something else entirely is biting me in the backside.
Tomorrow morning (when I'm awake again) I'll see if I can make any sense of the #use I2C code in the list file.
Boy, I just HAD to get that new chip with the many legs, more PWMs I would ever need and the shiny new I2C module, hadn't I? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Tue Mar 30, 2021 11:37 pm |
|
|
Hmm. ODCCON should exist. It's the open drain control for port C.
However the CCS function to do the same, is:
set_open_drain_c(0b00001100);
Which will set bits C3 and C4 to open drain.
Ah. Just looked inside the compiler, and CCS use ODCONC instead of
ODCCON for the register name. |
|
|
|