|
|
View previous topic :: View next topic |
Author |
Message |
Markdem
Joined: 24 Jun 2005 Posts: 206
|
I2C master\slave |
Posted: Sat Aug 06, 2005 5:59 am |
|
|
Hi All, after spending the last 4 hours on this fourm and google, i still do not understand what i am doing :(
All i want to do is turn on and off two LED every 2 seconds (this works)
I also want to display whether the LEDs are on or off on a LCD. I can write to the lcd, but my I2C code will not work. I have added a line to show when the slave starts the interrupt, but i never does.
Can somebody please, please help me...
Thank you
Mark
Code: |
//Master
#include <16f877a.h>
#fuses NOWDT,HS, NOPROTECT, BROWNOUT, NOPUT, NODEBUG, NOLVP
#use delay(clock=20000000)
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3, FORCE_HW)
int light1stat;
int light2stat;
void main()
{
light1stat = 1;
while(1){
light1stat++;
i2c_start();
i2c_write(0xa0);
i2c_write(light1stat);
i2c_stop();
output_low(PIN_D7);
delay_ms(1000);
light2stat = 1;
output_low(PIN_D6);
delay_ms(1000);
light1stat = 0;
output_high(PIN_D7);
delay_ms(1000);
light1stat = 0;
output_high(PIN_D6);
delay_ms(1000);
}
}
|
Code: |
//slave
#include <16f877a.h>
#include <marklcd420.c>
#fuses NOWDT,HS, NOPROTECT, BROWNOUT, NOPUT, NODEBUG, NOLVP
#use delay(clock=20000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, FORCE_HW, address=0xa0)
int light1stat;
int light2stat;
int count;
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
void main()
{
count=1;
lcd_init();
printf(lcd_putc,"Ready");
lcd_gotoxy(1,2);
printf(lcd_putc,"Light1: %U",light1stat);
lcd_gotoxy(1,3);
printf(lcd_putc,"Light2: %U",light2stat);
while(1){
}
}
#INT_SSP
void ssp_interupt ()
{
count++;
lcd_gotoxy(1,4);
printf(lcd_putc,"Count: %U",count);
i2c_start();
light1stat = i2c_read();
//light1stat = i2c_read();
i2c_stop();
}
|
|
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sat Aug 06, 2005 8:14 am |
|
|
Look at the example programs. Your slave receive is totally wrong. There is an example slave program that will work for you. |
|
|
Markdem
Joined: 24 Jun 2005 Posts: 206
|
|
Posted: Sun Aug 07, 2005 12:59 am |
|
|
I have spent the time looking at the example programs, both on the web and in the example folder in CCS, but i dont understand how they work. I need somthing "more" basic. Is the master code at least OK? |
|
|
Markdem
Joined: 24 Jun 2005 Posts: 206
|
|
Posted: Sun Aug 07, 2005 6:18 am |
|
|
I have now tired some more debugging on this. My slave programe will never enter the interrupt part. Am i doing somthing wrong here?? |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sun Aug 07, 2005 6:59 am |
|
|
Look at ex_slave.c That program is meant to emulate a serial eeprom. It could be changed a bit to suit your needs.
I suspect that since you never enter the interrupt, maybe you forgot to add the pullups to the lines.
Also you might try this code out
http://www.ccsinfo.com/forum/viewtopic.php?t=21456 |
|
|
Markdem
Joined: 24 Jun 2005 Posts: 206
|
|
Posted: Sun Aug 14, 2005 3:16 am |
|
|
Hi All, after retring for a long time to get this working, i am so close, but yet so far.
When i run my new code, it works, but it will only run for a few seconds. After tht, both PIC will just stop. The LEDs on the master stop flashing, and my cound on the LCD on the master will stop. If i run the master without the slave, it will run OK. If i run the slave without the master, it is OK. the problem is only when two chips are on the bus at te same time.
I have looked at all the example programs, but they are all to complex for me and my project, so i cant use them. I just dont understand what they are doing.
The printf statments in the interrupt are only for debugging.
Can sombody please help
Thank you , mark
Code: |
#include <16f877a.h>
#fuses NOWDT,HS, NOPROTECT, BROWNOUT, NOPUT, NODEBUG, NOLVP
#use delay(clock=20000000)
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3, FORCE_HW)
int light1stat;
int light2stat;
void main()
{
delay_ms(1000);
while(1)
{
i2c_start();
delay_ms(100);
i2c_write(0xa0);
delay_ms(100);
i2c_write(0x07);
delay_ms(100);
i2c_stop();
output_low(PIN_D7);
delay_ms(1000);
light2stat = 1;
output_low(PIN_D6);
delay_ms(1000);
light1stat = 0;
output_high(PIN_D7);
delay_ms(1000);
light1stat = 0;
output_high(PIN_D6);
delay_ms(1000);
}
} |
Code: |
#include <16f877a.h>
#include <marklcd420.c>
#fuses NOWDT,HS, NOPROTECT, BROWNOUT, NOPUT, NODEBUG, NOLVP
#use delay(clock=20000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0, FORCE_HW)
#use rs232(baud=9600,parity=N,bits=8,xmit=PIN_C6,rcv=PIN_C7)
#byte PIC_SSPBUF=0x13
#byte PIC_SSPADD=0x93
int isrcount;
char dummy;
int light1stat;
int count;
#INT_SSP
void ssp_interupt ()
{
dummy = i2c_read();
printf("sspbuf=%Lx\r\n",PIC_SSPBUF);
printf("sspadd=%Lx\r\n",PIC_SSPADD);
light1stat = i2c_read();
printf("sspbuf2=%Lx\r\n",PIC_SSPBUF);
printf("sspadd2=%Lx\r\n",PIC_SSPADD);
isrcount++;
}
void main()
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
lcd_init();
light1stat = 0;
while(1)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"Count: %U",count);
lcd_gotoxy(1,2);
printf(lcd_putc,"Light1: %S",light1stat);
lcd_gotoxy(1,3);
printf(lcd_putc,"dummy: %U",dummy);
lcd_gotoxy(1,4);
printf(lcd_putc,"ISR count: %U",isrcount);
count++;
}
}
|
|
|
|
ddscott
Joined: 17 Aug 2005 Posts: 4 Location: Livermore, CA
|
|
Posted: Tue Aug 23, 2005 9:01 am |
|
|
I don't know if you ever got a solution to your problem, but this is what I use to handle the i2c interrupt. It seems to work as desired, I use an Aardvark I2C emulator to communicate with the slave PIC.
Hope this helps.
Code: | include "C:\Program Files\PICC\Projects\Bio_Briefcase\i2c_0816.h"
int8 buffer;
boolean rec;
long j;
#int_SSP
void SSP_isr()
{
if (i2c_poll() == TRUE)
{
rec=true;
buffer=i2c_read();
}
}
void check_int()
{
long j;
if (buffer == 0x11)
{
rec = false;
buffer = 0;
for (j=0; j<10000; j++)
{
output_toggle(pin_a1);
delay_ms(1);
}
}
return;
}
void main()
{
int8 data;
long i;
rec=false;
buffer = 0;
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(VREF_LOW|-2);
setup_oscillator(False);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
#priority ssp
while (true) {
data = buffer;
rec=false;
buffer = 0;
if (data == 0x33)
{
data = 0;
for (i=0; i<30000; i++)
{
output_toggle(pin_a0);
delay_ms(1);
if (rec == true)
{
check_int();
}
}
}
}
} |
|
|
|
ella Guest
|
|
|
ddscott
Joined: 17 Aug 2005 Posts: 4 Location: Livermore, CA
|
I2C emulators |
Posted: Wed Aug 24, 2005 10:28 am |
|
|
It should work just fine with any emulator. Just be wary that the way PIC stores it's address might be different than how the emulator sends the address. If I want my i2c emulator to talk to address 0x20, I need to set the PIC to respond to address 0x40.
I was able to get the PIC to write data to the emulator yesterday. I monitor bit 2 in the SSPSTAT register. When it is a 1, the master has sent a read cmd, and I jump to a routine that writes data. Don't use i2c_start and i2c_stop instructions with the slave.
If you disable the interrupts to perform a high priority task, you need to reset the SSPCON register in software. For the PIC I am using, 16f767, I load the register with 0x36.
Hope this helps. |
|
|
|
|
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
|