View previous topic :: View next topic |
Author |
Message |
Robotix0805
Joined: 08 Nov 2017 Posts: 6 Location: South Africa
|
PIC24FJ64GA004 I2C not working |
Posted: Wed Nov 08, 2017 4:31 pm |
|
|
I seem to have hit a snag in my code development with the PIC24FJ64GA004. All the ports that I require work except for the I2C. I have tried various permutations but can't seem to get any change on the port at all.
These are the use I2C codes I've tried:
Code: |
//#use I2C(MASTER,SCL=SCL1,SDA=SDA1)
//#use i2c(stream=I2C1_STREAM,Master,I2C1,SLOW,FORCE_HW)
//#use i2c(stream=I2C2_STREAM,Master,I2C2,SLOW,FORCE_HW)
//#use i2c(stream = I2C2_Stream, Master,Fast,sda=SDA2,scl=SCL2, FORCE_SW)
//#use i2c(stream = I2C1_Stream, Master,Fast,sda=SDA1,scl=SCL1, FORCE_SW) |
Code I've tried to get the I2C to work:
Code: |
//SET_TRIS_B(0);
//i2c_start();
//i2c_write(0x40);
//i2c_write(I2C1_STREAM, 'a');
//i2c_write(I2C2_STREAM, 'a');
//i2c_stop(); |
Any advice would be much appreciated |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Nov 08, 2017 5:16 pm |
|
|
You really should goto the code library here and download PCM P's 'I2C Scanner' program. Compile, install, run. It WILL confirm the PIC can acess the I2C device, displaying all available device addresess.
Like a 1Hz LED program, the I2C scanner is a 'must have' program to confirm the hardware is goo.
Jay |
|
|
Robotix0805
Joined: 08 Nov 2017 Posts: 6 Location: South Africa
|
|
Posted: Thu Nov 09, 2017 2:41 am |
|
|
Thank you for all the replies and advice. Will try again tonight :-) |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Nov 09, 2017 3:42 am |
|
|
#use i2c(stream=I2C1_STREAM,Master,I2C1,SLOW)
Should have worked.
Using the hardware port name _forces_ the hardware port to be used. Overrides FORCE_HW or FORCE_SW completely.
How are the analog ports configured?. Critical....
The problem Jeremiah was having was that the analog was being left enabled on the pins. Though the default setup will adjust the TRIS, is does not adjust the ANSEL register. You see this on a PIC18Fxx50, where if you have the PortB ANSEL fuse set, it will stop peripherals on PortB working, unless you specifically turn off the ANSEL bits with an analog setup.
It sounds as if your pins may well be set as analog, since otherwise the software I2C would always work. |
|
|
Robotix0805
Joined: 08 Nov 2017 Posts: 6 Location: South Africa
|
|
Posted: Thu Nov 09, 2017 3:59 am |
|
|
Been using
setup_adc(adc_off);
before I even setup the tris registers. Currently the tris registers are set to outputs on the I2C pins. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Nov 09, 2017 4:02 am |
|
|
No.....
That turns off the ADC, but does not release the ports.
setup_adc_ports(NO_ANALOGS);
is needed to release the ANSEL bits. |
|
|
Robotix0805
Joined: 08 Nov 2017 Posts: 6 Location: South Africa
|
|
Posted: Thu Nov 09, 2017 4:08 am |
|
|
Ah cool. Will add it to my code. Did try that earlier as well but then my #use I2C might have been wrong. |
|
|
Robotix0805
Joined: 08 Nov 2017 Posts: 6 Location: South Africa
|
|
Posted: Fri Nov 10, 2017 1:50 am |
|
|
Thank you for all the suggestions. I still can't get the code to work. So decided to attach my code to see if anyone can spot something really obvious I'm doing wrong. Will be changing out the chip later today just to eliminate that as a problem. Tried the I2C Scanner, but all it does is give me a high or ACK on each address. On my logic analyzer it shows the pins staying high. As an absolute last resort (Not keen at all) I'll fall back onto XC16 just to see if I can get the I2C to work.
**********Main File**********
Code: | #include <24FJ64GA004.h>
#include "main.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <interrupts.h>
#use delay (clock = 4000000)
void main()
{
char data;
set_tris_a(0);
set_tris_c(1024);
SET_TRIS_B(780);
setup_adc(adc_off);
setup_adc_ports(NO_ANALOGS );
setup_timer2(TMR_INTERNAL |TMR_DIV_BY_256 ,4096);
enable_interrupts(INT_TIMER2);
output_float(SDA2);
output_float(SCL2);
output_high(wirelessSet);
while(1)
{
//I2C Write to EEPROM 24LC512
i2c_start();
i2c_write(I2C2_STREAM,0xa0);
i2c_write(I2C2_STREAM,1);
i2c_write(I2C2_STREAM,2);
i2c_write(I2C2_STREAM,'a');
i2c_stop();
//i2c_write(I2C1_STREAM, 'a');
i2c_write(I2C2_STREAM, 'a');
i2c_stop();
//I2C Read from EEPROM 24LC512
i2c_start();
i2c_write(0xa0);
i2c_write(I2C2_STREAM,1);
i2c_write(I2C2_STREAM,2);
i2c_start();
i2c_write(0xa1);
data=i2c_read(0);
i2c_stop();
printf("Response: %c\r\n", data);
delay_ms(100);
}
} |
**************interrupts.h************
Code: | #int_TIMER2
void TIMER2_isr()
{
output_toggle(heartbeatLED);
} |
************main.h****************
Code: |
#device ADC=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOJTAG //JTAG disabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#FUSES ICSP1 //ICD uses PGC1/PGD1 pins
//#FUSES IOL1WAY //Allows only one reconfiguration of peripheral pins
#FUSES NOIOL1WAY //Allows multiple reconfigurations of peripheral pins
#FUSES NOWINDIS //Watch Dog Timer in Window mode
#FUSES WPRES128 //Watch Dog Timer PreScalar 1:128
#FUSES WPOSTS16 //Watch Dog Timer PostScalar 1:32768
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES OSCIO //OSC2 is general purpose output
#FUSES NOPR //Pimary oscillaotr disabled
#FUSES I2C1SELD
//Serial UART1
#pin_select U1TX= PIN_B13
#pin_select U1RX= PIN_B12
#define wirelessSet PIN_A1
#define cts PIN_A3
#define dts PIN_A2
//I2C1
#define SDA1 PIN_B8
#define SCL1 PIN_B9
//I2C2
#define SDA2 PIN_B2
#define SCL2 PIN_B3
//General IO
#define heartbeatLED PIN_A0
#use i2c(stream=I2C1_STREAM,Master,I2C1,SLOW,FORCE_HW)
#use i2c(stream=I2C2_STREAM,Master,I2C2,SLOW,FORCE_HW)
#use rs232(UART1,baud=9600,parity=N,bits=8) |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Nov 10, 2017 9:40 am |
|
|
1. Do you have pull-up resistors on SDA and SCL ? What are the values ?
2. Problem: You have no delay after your write operation.
Look in the 24LC512 data sheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/21754M.pdf
Look at the table on page 4, at this parameter:
Quote: | TWC Write cycle time (byte or page) 5 ms |
It takes time for the eeprom to do a write operation.
You have to handle this delay in your driver program. It's not done
automatically.
You could add a delay statement after the eeprom write code ends.
Example:
Code: |
i2c_start();
.
.
.
i2c_stop();
delay_ms(5);
|
But this isn't the best way. The 5 ms number is the max possible delay.
The eeprom could finish it earlier than that.
Let's look at the code in the supplied CCS driver file, 24512.c.
This file is in your CCS installation \Drivers folder.
Note how it's logically laid out. It doesn't have 1's and 2's. It has
parameters for address and data. Then note the section shown in bold
below. This a way of doing the Write Cycle delay more exactly. It's called
"Ack polling". It polls (reads) the eeprom chip until it gets an Ack.
When it gets an Ack, the eeprom write cycle is done.
Quote: | void write_ext_eeprom(long int address, BYTE data)
{
short int status;
i2c_start();
i2c_write(0xa0);
i2c_write(address>>8);
i2c_write(address);
i2c_write(data);
i2c_stop();
i2c_start();
status=i2c_write(0xa0);
while(status==1)
{
i2c_start();
status=i2c_write(0xa0);
}
i2c_stop();
} |
You can read about Ack polling in this section of the 24LC512 data sheet:
Quote: | 7.0 ACKNOWLEDGE POLLING |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Fri Nov 10, 2017 10:22 am |
|
|
He is also writing to the port after sending stop.
Not actually sure what this will do. Suspect it'll cause an error though....
Code: |
i2c_stop();
//i2c_write(I2C1_STREAM, 'a');
i2c_write(I2C2_STREAM, 'a');
i2c_stop();
|
Also he should be using the stream names for the start and stop as well.
If you setup multiple I2C's, the stream names need to be used for everything. |
|
|
Robotix0805
Joined: 08 Nov 2017 Posts: 6 Location: South Africa
|
|
Posted: Mon Nov 13, 2017 3:38 am |
|
|
So over the weekend I replaced the micro with a new one and the I2C1 port works like a charm. However the I2C2 port still seems to be giving issues. It'll work and then not work and then work again and so on.
As for the strange I2C commands. I'm not for the moment attempting to connect to the I2C devices on the bus. Infact they are still in the components bin. I'm only trying to get the I2C to work. Using my logic analyzer and pull up resistors I can observe the stability of the bus.
Now attempting to make the I2C2 bus to work. Will update if I find a solution that makes the bus work consistently. |
|
|
|