|
|
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: 1635 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
|