View previous topic :: View next topic |
Author |
Message |
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
SOLVED: i2c_transfer not working |
Posted: Thu Jun 01, 2023 12:07 am |
|
|
Good day.
Have a problem where I can not get i2c_transfer to work.
Old i2c_start works fine. Needed to change to i2c_transfer as the compiler complains on a new chip
Old PIC: PIC16F18325
New PIC: PIC18F04Q41
Code: |
#include <18F04Q40.h>
#FUSES NOMCLR, NOPROTECT
#use delay(internal=8000000)
#include <stdint.h>
#pin_select SDA1 = PIN_C5
#pin_select SCL1 = PIN_C4
#use I2C(Master,I2C1,stream = MPU6050)
void main(void) {
int8_t reg_addr[2];
output_toggle(LED_CHARGING);
delay_ms(500);
output_toggle(LED_CHARGING);
delay_ms(500);
output_toggle(LED_CHARGING);
delay_ms(100);
// i2c_start();
// i2c_write(MPU6050_SLAVE_WRT);
// i2c_write(MPU6050_SMPLRT_DIV);
// i2c_write(0x07);
// i2c_stop();
reg_addr[0] = MPU6050_SMPLRT_DIV;
reg_addr[1] = 0x07;
i2c_transfer(MPU6050,MPU6050_SLAVE_WRT,reg_addr,2);
while (TRUE) {
output_toggle(LED_CHARGING);
delay_ms(500);
}
|
Stop just after i2c_transfer
Last edited by alan on Thu Jun 01, 2023 6:47 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Jun 01, 2023 1:21 am |
|
|
What compiler version???
Vital when asking almost any question.
Particularly vital here, since the behaviour of I2C_transfer changed with
compiler version.
When this function was first added, the 'count' at the end was the value
put into the count register on the chip. This needs to be one greater than
the number of bytes you want to send, since the address byte also counts.
However it now only requires the number of bytes you want to send.
So on a recent compiler, what you post is right, but on older compilers,
you need 3, instead of 2 for the byte count.....
Some other little thoughts.
On the old chip, was the clock rate the same?. The I2C might be running
faster now. Add a baud value to the I2C setup so this is fixed.
You say 18F04Q41, but the code shows 18F04Q40.
You are running at 3.3v?. Both chips accept this, but nice to know.
On I2C_transfer, you don't have to worry about read and write addresses.
The command just takes the device address and automatically sets the
low bit of this for a read. So change to just having the device address
rather than read/write addresses.
On some of these later chips, there are slew rate controls on the pins.
Yours is one where this applies. So you need to turn this off
set_slow_slew_c(FALSE);
near the start of the code, before the I2C is used. It defaults to on. |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Thu Jun 01, 2023 4:43 am |
|
|
Oh sorry Ver 5.116
Should be 18F04Q40
Same clk rate
Both at 3.3V
Will try the slew rate
Thank you |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Jun 01, 2023 6:21 am |
|
|
Er.
5.115 is the latest compiler on the download site.
If you have 5.116, it'll be a beta, and you should talk to CCS, |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Thu Jun 01, 2023 6:42 am |
|
|
Got a new version yesterday from CCS as there were faults in 5.115 |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Thu Jun 01, 2023 6:46 am |
|
|
Got it working.
I know the old hands here don't like the #USE fast_io, but I do. Previously you need to set the i2c pins as inputs to work, yet it looks like when using dedicated i2c you have to set them as outputs to work. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Jun 01, 2023 7:00 am |
|
|
Most of the long term posters will use fast_io _sometimes_. The point is
very rarely. What is hated is people routinely using it, because it
makes errors vastly more likely.
Normally when a peripheral is attached to the pins on a PPS chip, it
overrides the TRIS settings.
On your chip the data sheet says that the pins must be set as open drain
outputs. So the pins actually need their TRIS bits set to 0, but also
the ODCON bits, otherwise the pins will be driven high, which invalidates
things like clock stretching from the slave.
So using FAST_IO without setting ODCON risks drawing excessive current.
So get rid of your fast_io setting, and use:
Code: |
output_drive(PIN_C4); //These set the two TRIS bits to 0
output_drive(PIN_C5); //without affecting anything else
set_open_drain_c(0B00110000); //set these two bits as open_drain
|
|
|
|
|