|
|
View previous topic :: View next topic |
Author |
Message |
snowbell Guest
|
speed of i2c data transfer |
Posted: Wed Feb 03, 2010 1:08 am |
|
|
Hi, may I know how fast is the data transfer from Master to Slave in I2C? In the code below, I tried to send 0x00 or 0x01 from slave to master and master will light an LED if it receives 0x01, and not light the LED if it receives 0x00. I tested the code and it works, but there is always a delay of about 10s from the time I input a high/low to pin_C0 at the slave to the time the LED is lit/unlit. May I know is I2C supposed to take such a long time? Or am I doing something wrong? Thanks.
Master:
Code: |
#if defined(__PCM__)
#include <18F4620.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#elif defined(__PCH__)
#include <18F4620.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000, internal)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#endif
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3)
#define SLAVE1_WRT_ADDR 0x12 //LSB=0
#define SLAVE1_READ_ADDR 0x13 //LSB=1
//====================================
void main()
{
int8 data;
while(1)
{
i2c_start();
i2c_write(SLAVE1_READ_ADDR);
data = i2c_read(0);
i2c_stop();
//printf("read %X \n\r", data);
if (data == 0x01)
output_high(PIN_C0);
if (data == 0x00)
output_low(PIN_C0);
//delay_ms(1000);
}
}
|
Slave:
Code: |
#if defined(__PCM__)
#include <18F4620.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#elif defined(__PCH__)
#include <18F4620.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000, internal)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#endif
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x12)
int8 adc_result;
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
incoming = i2c_read();
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(adc_result);
}
}
//======================================
void main ()
{
//setup_adc_ports(AN0);
//setup_adc(ADC_CLOCK_DIV_8);
//set_adc_channel(0);
//delay_us(20);
//adc_result = read_adc();
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
//set_tris_c(0x01);
while(1)
{
//adc_result = read_adc();
if(input(PIN_C0))
adc_result = 0x01;
else
adc_result = 0x00;
delay_ms(500);
}
}
|
|
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Feb 03, 2010 3:08 am |
|
|
I would expect up to .5 second delay with your code due to this line:-
delay_ms(500);
If you press the button just after the code has done the check, your code will wait at least .5 second before it tests the button again and updates the value.
I also see you have a delay_ms(1000) which is now commented out.
Comment out the delay_ms(500); and see what happens.
i2c has 2 speeds ratings standard upto 100k and fast upto 400k but as it is clocked it may vary and I don't know how fast your pic will clock it. |
|
|
Ttelmah Guest
|
|
Posted: Wed Feb 03, 2010 4:44 am |
|
|
First, 20% of the code you post, is 'wasted space'.
You have taken an example, designed to work with two chips, one a PIC16, and one a PIC18, and left in place the handling for the compiler switch, but made it not work. The PCM compiler _cannot handle_ the PIC18F4620, so get rid of this code. It is just making your work bulkier , without gaining anything....
There main problem with your oscillator fuses. You have 'HS' selected (which says use an external oscillator), and a delay statement saying use 20MHz, and an internal oscillator. 20MHz, is _not_ available from the internal oscillator, so the settings are 'invalid'. I'd suspect the chip is actually clocking at perhaps the 500KHz rate, making your '500mSec' delay in the slave, actually take 40* as long....
Best Wishes |
|
|
snowbell Guest
|
|
Posted: Fri Feb 05, 2010 9:24 am |
|
|
Thanks for all the help. It is really the oscillator problem which I did not even realise I defined them wrongly. Thanks once again. |
|
|
snowbell Guest
|
|
Posted: Fri Feb 05, 2010 10:54 am |
|
|
I got another problem now. The initial code example I used was the master receiving data from the slave. Now I tried to edit the previous code to have the master send data to the slave instead. But the code doesn't work anymore. Any help would be gladly appreciated. Thanks.
Master:
Code: |
#if defined(__PCH__)
#include <18F4620.h>
#fuses INTRC,NOWDT,NOPROTECT,NOLVP
#use delay(clock=8000000, internal)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#endif
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3)
#define SLAVE1_WRT_ADDR 0x12 //LSB=0
#define SLAVE1_READ_ADDR 0x13 //LSB=1
//====================================
void main()
{
int8 cmd;
while(1)
{
if(input(PIN_C0))
cmd = 0x01;
else
cmd = 0x00;
i2c_start();
i2c_write(SLAVE1_WRT_ADDR);
i2c_write(cmd);
i2c_stop();
//printf("read %X \n\r", data);
}
}
|
Slave:
Code: |
#if defined(__PCH__)
#include <18F4620.h>
#fuses INTRC,NOWDT,NOPROTECT,NOLVP
#use delay(clock=8000000, internal)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#endif
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x12)
int8 data;
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
incoming = i2c_read();
data = incoming;
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(data);
}
}
//======================================
void main ()
{
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
//set_tris_c(0x01);
while(1)
{
if (data == 0x01)
output_high(PIN_C0);
if (data == 0x00)
output_low(PIN_C0);
}
}
|
|
|
|
snowbell Guest
|
|
Posted: Sat Feb 06, 2010 12:28 pm |
|
|
Hi, I've tried to debug my code but it still doesn't work. Anyone knows the reason why? Thanks. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|