|
|
View previous topic :: View next topic |
Author |
Message |
davey
Joined: 04 May 2006 Posts: 17 Location: Sweden
|
i2c...arrgghh....help!!! |
Posted: Mon May 08, 2006 6:51 am |
|
|
Hi can someone please take a look at my code before I totally lose it over here:
What I want to is: send two bytes of data from a master-PIC to a slave-PIC. Nothing more. I΄ve tried looking at some examples but it just doesn΄t work.
Hopefully you can see what belongs to i2c and not. The master uses send_to_slave() to send the two bytes, The slave uses an interrupt-routine to receive them. What am I doing wrong?
MASTER-code:
================
Code: | #include <puls.H>
#fuses NOWDT
#use i2c(master,sda=PIN_C4,scl=PIN_C3)
int16 freq=20; //aktuell frekvens fφr mastern
int8 step=1; //Vald steg-nivε (1-4)
int8 channel=1; //Vald kanal (1-3)
byte pressed=0; //nedtryckt tangent
byte tmp4; //anv av lcd_write_as_hex
byte tmp3; //anv av timer1_isr()
byte tmp2; //anv av lcd_info()
byte tmp1;
int16 temp;
int16 temp2=0;
int16 temp3=0;
boolean write_zero=false;
struct lcd_map
{
int data:8;
boolean rs;
boolean enable;
boolean rw;
int unused:5;
}
lcd;
#byte lcd = 0x08
//CPU1 - Timer 1
int16 t1sv=3035; //Start-vδrde (65535-3035=62500) fφr Timer1 (ger 20Hz)
int16 t1svmod;
//Fφr de andra processorerna
int16 freq2=20; //frekvens - CPU2
int8 step2=4; //stegnivε - CPU2
int16 freq3=20; //frekvens - CPU3
int8 step3=1; //stegnivε - CPU3
//(((((((((((((((((((((((( INTERRUPTS ))))))))))))))))))))))))))))
#int_timer1 //KANAL 1
timer1_isr()
{
tmp3=TIMER1_CTRL;
TIMER1_CTRL=0x00;
t1svmod=t1sv;
TIMER_1_LOW=t1svmod&0x00FF; //laddar med den fφrsta byten av t1sv
t1svmod >>= 8; //shiftar 8 bitar till hφger
TIMER_1_HIGH=t1svmod&0x00FF;//laddar med den andra byten av t1sv
port_c ^= 1; //0->1 el. 1->0
TIMER1_CTRL=tmp3;
}
//%%%%%%%%%%%%%%%%%%%%%%%% FUNKTIONER %%%%%%%%%%%%%%%%%%%%%%%%%%%%
byte keyboard_in() //en funktion som kollar vilken knapp som δr intryckt och returnerar motsvarande vδrde
{
set_tris_b(0xF0); //vδljer de fφrsta εtta benen pε port_b som ingεngar, vilket gφr att de interna pull_up-mostεnden kopplas hit
port_b_pullups(true); //drar upp pull_up-motstεnden till ettor
port_b = 0x0E; //aktiverar fφrsta kolumnen fφr att sedan fφrsφka hitta den knapp som δr nedtryckt genom bit-testing...
if(!bit_test (port_b,7))
return 3; //betyder att knapp 3 δr nedtryckt -> avsluta intruktionen och returnera vδrdet 3
if(!bit_test (port_b,4))
return 0;
if(!bit_test (port_b,5))
return 1;
if(!bit_test (port_b,6))
return 2;
port_b = 0x0D; //se ovan
if(!bit_test (port_b,7))
return 7;
if(!bit_test (port_b,4))
return 4;
if(!bit_test (port_b,5))
return 5;
if(!bit_test (port_b,6))
return 6;
port_b = 0x0B; //se ovan
if(!bit_test (port_b,7))
return 11;
if(!bit_test (port_b,4))
return 8;
if(!bit_test (port_b,5))
return 9;
if(!bit_test (port_b,6))
return 10;
port_b = 0x07; //se ovan
if(!bit_test (port_b,7))
return 15;
if(!bit_test (port_b,4))
return 12;
if(!bit_test (port_b,5))
return 13;
if(!bit_test (port_b,6))
return 14;
}
void lcd_waitbusy()
{
set_tris_d(0xFF);
lcd.rw = true;
while(1)
{
delay_us(50);
if(bit_test(lcd.data,7)==0)
{
set_tris_d(0x00);
lcd.rw = false;
return;
}
}
}
void lcd_control(byte ctrl_in)
{
lcd_waitbusy();
lcd.rs=false;
lcd.rw=false;
lcd.data = ctrl_in;
lcd.enable=true;
delay_cycles(4);
lcd.enable=false;
delay_ms(2);
lcd.data = 0x00;
}
void lcd_data(byte data_in)
{
lcd_waitbusy();
lcd.rs=true;
lcd_waitbusy();
lcd.data=data_in;
lcd.enable=true;
delay_cycles(4);
lcd.enable=false;
delay_ms(2);
lcd.data = 0x00;
}
void lcd_write_as_hex(byte b) //funktion som skriver ut en byte i hex-form
{
tmp4=b>>4;
if(tmp4>9)
lcd_data(tmp4+0x37);
else
lcd_data(tmp4+0x30);
tmp4=b&0xF;
if(tmp4>9)
lcd_data(tmp4+0x37);
else
lcd_data(tmp4+0x30);
}
void calc_write_freq() //skriver ut frekvens pε LCD:n
{
switch(channel)
{
case 1:
temp2=freq;
break;
case 2:
temp2=freq2;
break;
case 3:
temp2=freq3;
break;
}
temp3=temp2/1000;
if(temp3>0)
{
write_zero=true;
lcd_data(temp3+0x30);
temp3=temp3*1000;
temp2=temp2-temp3;
}
temp3=temp2/100;
if(temp3>0 || write_zero)
{
lcd_data(temp3+0x30);
write_zero=true;
temp3=temp3*100;
temp2=temp2-temp3;
}
temp3=temp2/10;
if(temp3>0 || write_zero)
{
lcd_data(temp3+0x30);
temp3=temp3*10;
temp3=temp2-temp3;
}
write_zero=false;
lcd_data(temp3+0x30);
lcd_data(' ');
lcd_data('H');
lcd_data('z');
}
void info_lcd() //Skriver ut vald kanal, stegnivε och frekvens till LCD:n
{
lcd_control(0x01);
lcd_data('K');
lcd_data('a');
lcd_data('n');
lcd_data('a');
lcd_data('l');
lcd_data(':');
lcd_write_as_hex(channel);
lcd_data(' ');
lcd_data('S');
lcd_data('t');
lcd_data('e');
lcd_data('g');
lcd_data(':');
switch(channel)
{
case 1:
lcd_write_as_hex(step);
break;
case 2:
lcd_write_as_hex(step2);
break;
case 3:
lcd_write_as_hex(step3);
break;
}
lcd_control(0x41 + 0x80);
lcd_data('F');
lcd_data('r');
lcd_data('e');
lcd_data('k');
lcd_data('v');
lcd_data('e');
lcd_data('n');
lcd_data('s');
lcd_data(':');
calc_write_freq();
}
void send_to_slave() //I2C-funktion
{
switch(channel)
{
case 2: //skicka till slav-1
i2c_start();
i2c_write(0xa0); //adress
i2c_write(freq2>>8); //data
i2c_write(freq2&0x00FF);
i2c_stop();
break;
case 3: //skicka till slav-2
i2c_start();
i2c_write(0x50); //adress
i2c_write(freq3>>8); //data
i2c_write(freq3&0x00FF);
i2c_stop();
break;
default:
break;
}
}
//
// MAIN
//
main()
{
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_port_a(NO_ANALOGS);
setup_adc(ADC_CLOCK_INTERNAL);
setup_psp(PSP_DISABLED);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
setup_spi(spi_master | SPI_L_TO_H | spi_clk_div_4);
//====================== I/O ============================
set_tris_e(0x00); // PORT-E: alla utgεngar
set_tris_d(0x00); // PORT-D: alla utgεngar
set_tris_c(0x00); // PORT-C: alla utgεngar
//=======================================================
//================== SETUP - Timer1 =====================
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
TIMER1_CTRL=0x11;
//=======================================================
//=================== SETUP - LCD =======================
lcd_control(0x38);
lcd_control(0x06);
lcd_control(0x0C);
lcd_control(0x01);
info_lcd();
//=======================================================
while(1)
{
pressed=keyboard_in();
//UPP
if(pressed==1)
{
pressed=0;
switch(channel)
{
case 1:
if(step==4 || freq>7000) freq=freq+200;
else if(step==3 || freq>6000) freq=freq+100;
else if(step==2 || freq>5000) freq=freq+50;
else freq=freq+5;
if(freq>13000) freq=13000;
//................................
if(freq>40 && TIMER1_CTRL==0x11) TIMER1_CTRL=0x01;
temp=2*freq;
if(TIMER1_CTRL==0x11) temp=2495000/temp;
else temp=4990000/temp;
t1sv=65535-temp;
break;
case 2:
if(step2==4 || freq2>7000) freq2=freq2+200;
else if(step2==3 || freq2>6000) freq2=freq2+100;
else if(step2==2 || freq2>5000) freq2=freq2+50;
else freq2=freq2+5;
if(freq2>13000) freq2=13000;
send_to_slave();
break;
case 3:
if(step3==4 || freq3>7000) freq3=freq3+200;
else if(step3==3 || freq3>6000) freq3=freq3+100;
else if(step3==2 || freq3>5000) freq3=freq3+50;
else freq3=freq3+5;
if(freq3>13000) freq3=13000;
send_to_slave();
break;
}
info_lcd();
delay_ms(500);
}
//NER
if(pressed==2)
{
pressed=0;
switch(channel)
{
case 1:
if(step==4 || freq>7000) freq=freq-200;
else if(step==3 || freq>6000) freq=freq-100;
else if(step==2 || freq>5000) freq=freq-50;
else freq=freq-5;
if(freq<20) freq=20;
//.....................................
if(freq<=40 && TIMER1_CTRL==0x01) TIMER1_CTRL=0x11;
temp=2*freq;
if(TIMER1_CTRL==0x11) temp=2495000/temp;
else temp=4990000/temp;
t1sv=65535-temp;
break;
case 2:
if(step2==4 || freq2>7000) freq2=freq2-200;
else if(step2==3 || freq2>6000) freq2=freq2-100;
else if(step2==2 || freq2>5000) freq2=freq2-50;
else freq2=freq2-5;
if(freq2<20) freq2=20;
send_to_slave();
break;
case 3:
if(step3==4 || freq3>7000) freq3=freq3-200;
else if(step3==3 || freq3>6000) freq3=freq3-100;
else if(step3==2 || freq3>5000) freq3=freq3-50;
else freq3=freq3-5;
if(freq3<20) freq3=20;
send_to_slave();
break;
}
info_lcd();
delay_ms(500);
}
//STEP
if(pressed==5)
{
switch(channel)
{
case 1:
step++;
if(step>4) step=1;
break;
case 2:
step2++;
if(step2>4) step2=1;
break;
case 3:
step3++;
if(step3>4) step3=1;
break;
}
info_lcd();
delay_ms(500);
}
//KANAL
if(pressed==4)
{
channel++;
if(channel>3) channel=1;
info_lcd();
delay_ms(500);
}
}
}
// |
SLAVE-code:
============
Code: | #include <puls.H>
#fuses HS,NOWDT,NOPROTECT
#use i2c(slave,sda=PIN_C4,scl=PIN_C3,address=0xa0)
int16 freq=20; //aktuell frekvens fφr denna slav
int16 freq_tmp=20;
int16 temp;
byte tmp3; //anv av timer1_isr()
byte received;
typedef enum {FIRST_READ, LAST_READ} I2C_STATE;
I2C_STATE i2c_status=FIRST_READ;
//Timer 1
int16 t1sv=3035; //Start-vδrde (65535-3035=62500) fφr Timer1 (ger 20Hz)
int16 t1svmod;
//(((((((((((((((((((((((( INTERRUPTS ))))))))))))))))))))))))))))
#int_timer1 //KANAL 1
timer1_isr()
{
tmp3=TIMER1_CTRL;
TIMER1_CTRL=0x00;
t1svmod=t1sv;
TIMER_1_LOW=t1svmod&0x00FF; //laddar med den fφrsta byten av t1sv
t1svmod >>= 8; //shiftar 8 bitar till hφger
TIMER_1_HIGH=t1svmod&0x00FF;//laddar med den andra byten av t1sv
port_c ^= 1; //0->1 el. 1->0
TIMER1_CTRL=tmp3;
}
#int_ssp
receive_isr()
{
//ladda freq med mottaget vδrde
if(i2c_poll())
{
if(i2c_status==FIRST_READ)
{
received=i2c_read();
freq_tmp=received;
i2c_status=LAST_READ;
}
else if(i2c_status==LAST_READ)
{
received=i2c_read();
freq_tmp=(freq_tmp<<8)&0xFF00;
freq_tmp=freq_tmp+received;
i2c_status=FIRST_READ;
freq=freq_tmp;
if(freq>40) TIMER1_CTRL=0x01;
else TIMER1_CTRL=0x11;
temp=2*freq;
if(TIMER1_CTRL==0x11) temp=2495000/temp;
else temp=4990000/temp;
t1sv=65535-temp;
}
port_d ^= 1; //indikator
}
}
//
// MAIN
//
main()
{
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_port_a(NO_ANALOGS);
setup_adc(ADC_CLOCK_INTERNAL);
setup_psp(PSP_DISABLED);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
setup_spi(spi_slave | SPI_L_TO_H | SPI_SS_DISABLED);
//====================== I/O ============================
set_tris_d(0x00); // PORT-D: alla utgεngar
set_tris_c(0xFE); // PORT-C: alla ingεngar, utom C0(puls)
//=======================================================
//========================I2C============================
enable_interrupts(INT_SSP);
//=======================================================
//================== SETUP - Timer1 =====================
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
TIMER1_CTRL=0x11;
//=======================================================
while(1){};
}
//
|
|
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Mon May 08, 2006 9:08 am |
|
|
Your more likley to get assisatance is you post the minimal code necessary to demonstrate the problem. Not many have the time to debug someone elses long code listing. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
new2pic
Joined: 02 May 2006 Posts: 16
|
|
Posted: Mon May 08, 2006 11:18 am |
|
|
i dont know if this helps but this works for me:
SEN = 1;
while(comm_not_finished);
bit comm_not_finished (data passed to function)
while(!SSPIF);
SSPIF = 0;
switch (x)
{
case 0:
SSPBUF = <insert data1>;
x = 1;
break;
case 1:
if (ACKSTAT) {
x = 0;
SEN = 1;
break;
}
SSPBUF = <insert data2>;
x = 2;
break;
case 2:
if (ACKSTAT)
{
x = 0;
SEN = 1;
break;
}
PEN = 1;
x = 3;
break;
case 3:
x = 0;
return 1;
}
return FALSE;
} |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon May 08, 2006 12:51 pm |
|
|
A huge listing and not even complete, puls.h is missing.
I can't find some #fuse settings and the #device setting, are these in the missing puls.h file?
Code: | setup_spi(spi_slave | SPI_L_TO_H | SPI_SS_DISABLED); | You are using I2C, not SPI. This line seems tricky to me and I would remove it.
Sorry, I'm too lazy to study the rest of your huge program.
Have a look at ex_slave.c in the examples directory for how CCS sets up an I2C slave. |
|
|
|
|
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
|