|
|
View previous topic :: View next topic |
Author |
Message |
chentou Guest
|
i2c slave can either send or receive but can not do both |
Posted: Wed Jan 02, 2008 11:14 am |
|
|
i am using 18f8722 for both master and slave. the master clock is 10mhz and the master code has been written and tested by another guy (using mplab compiler). the clock for the slave is 40mhz. the following code has been tested, and the sending part and the receiving part works well individually (sending or receiving data every 100ms), but when both sending and receiving are enabled in the master program, we saw that the data were sent or received for only one time, not continuously sending and receiving every 100ms.
EX_SLAVE.C has been tried, the result is the same.
can anybody tell me why? first time use i2c.
#include <18F8722.h>
//#device HIGH_INTS = TRUE
#device ICD=TRUE
#device adc=10
#use delay(clock=40000000)
#fuses HS
#fuses FCMEN , NOSTVREN, LVP, IESO, MCLR, BORV45, NOWDT, NOPROTECT, DEBUG
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xA0)
BYTE address, buffer[0x10];
//int8 start_stop_master;
//int8 vdc_set_master;
//int8 frequency_master = 3; int8 pulse_master=17;
int8 address_temp;
#byte start_stop_master = 0x20
#byte vdc_set_master = 0x21
#byte frequency_master = 0x22
#byte pulse_master = 0x23
#byte cheksum = 0x24
#byte address_temp1 = 0x25
#byte address_temp2 = 0x26
#byte SSP1CON1 = 0xFC6
#BIT CKP = SSP1CON1.4
#BYTE SSP1ADD = 0xFC8
#BYTE SSP1STAT = 0xFC7
long power1 = 0xaaaa;
long power2 =0xbbbb;
long power3 = 0xcccc;
long power4 = 0xdddd;
int8 Hbridge_status = 1;
int8 protection_status = 0;
#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
TEMP1 = SSP1STAT;
state = i2c_isr_state();
if(state <0x80>>8);
delay_us(100);
i2c_write(power2);
delay_us(100);
i2c_write(power2>>8);
delay_us(100);
i2c_write(power3);
delay_us(100);
i2c_write(power3>>8);
delay_us(100);
i2c_write(power4);
delay_us(100);
i2c_write(power4>>8);
//delay_ms(1);
}
}
void main ()
{
set_tris_c(0xff);
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE) {;)
} |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Jan 02, 2008 11:45 am |
|
|
Some general remarks first:
- When posting code please use the 'code' buttons to preserve formatting and layout of your code. This makes reading the code a lot easier.
- When posting code select the 'disable HTML in this post' option. Now several lines in your code are unreadable because they have been interpreted as HTML. Tip: become a registered user of this forum and you can activate this option as a default in your profile.
- Always mention the version number of your compiler.
Even though your code is garbled there are some comments for improvement:
- Check the LVP fuse. 99% of the people are using a high voltage programmer and set it to NOLVP. Enabling the LVP fuse when you are not using Low Voltage Programming could cause problems: a voltage spike on the PGM pin (B5) will stall your processor. Note: I see you enabled the ICD fuse; the ICD-2 and CCS debuggers are high voltage programmers.
- A clock speed of 40MHz can only be achieved with an external 40MHz clock generator (EC fuse) or a 10MHz crystal in combination with the 4xPLL (H4 fuse). Your HS fuse setting only supports a crystal up to 25MHz, not 40MHz.
- The #use i2c directive uses a software I2C driver by default. Add FORCE_HW to ensure the hardware MSSP module is used, this is compulsory for a slave.
Fix the above mentioned problems and test again. If it still fails then post your code again with the above mentioned suggestions in place and all obsolete lines removed (the #byte lines and all commented code lines). |
|
|
chentou Guest
|
i2c can only send or receive but can not do both |
Posted: Thu Jan 03, 2008 8:05 am |
|
|
Thanks.
PCH compiler v4.057. change to #fuses EC, change to NOLVP, and add FORCE_HW. the result is the same, only do one time sending and receiving.
master sends A0 (address), 78, 56. 34, 12, B4 (cheksum), and the slave receives all of these data, and after B4, the slave receives A1 in address_temp1, which i think is the address master sent for receiving data from slave. |
|
|
chentou Guest
|
code is here |
Posted: Thu Jan 03, 2008 8:14 am |
|
|
Code: |
#include <18F8722.h>
#device ICD=TRUE
#device adc=10
#use delay(clock=40000000)
#fuses EC
#fuses FCMEN , NOSTVREN, NOLVP, IESO, MCLR, BORV45, NOWDT, NOPROTECT, DEBUG
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xA0,FORCE_HW)
#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
TEMP1 = SSP1STAT;
state = i2c_isr_state();
if(state < 0x80)
{
incoming = i2c_read();
if(state == 0)
start_stop_master = incoming;
if(state == 1)
vdc_set_master = incoming;
if (state == 2)
frequency_master = incoming;
if (state ==3)
pulse_master = incoming;
if (state ==4)
cheksum = incoming;
if (state == 5)
address_temp1 = incoming;
if (state == 6)
address_temp2 = incoming;
}
if(state == 0x80)
{
delay_us(100);
i2c_write(0x55);
delay_us(100);
i2c_write(0x33);
delay_Us(100);
i2c_write(protection_status);
delay_us(100);
i2c_write(power_reactor1);
delay_us(100);
i2c_write(power_reactor1>>8);
delay_us(100);
i2c_write(power_reactor2);
delay_us(100);
i2c_write(power_reactor2>>8);
delay_us(100);
i2c_write(power_reactor3);
delay_us(100);
i2c_write(power_reactor3>>8);
delay_us(100);
i2c_write(power_reactor4);
delay_us(100);
i2c_write(power_reactor4>>8);
}
}
void main ()
{
set_tris_c(0xff);
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE) ;
}
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Jan 03, 2008 4:28 pm |
|
|
Your program is not complete, several variable declarations are missing. This tells us you are not showing the exact version you are testing with.
In your first version you declared some variables as Code: | #byte cheksum = 0x24
#byte address_temp1 = 0x25
#byte address_temp2 = 0x26 | This is not the normal way of declaring variables, you only do this when you want to specify the exact memory location for a variable. A problem is that #byte does not prevent C from using the same memory for other (normal declared) variables. This overlapping of variables might be your problem.
If you do want to specify the memory location but for exclusive use you should have used #locate instead.
Quote: | master sends A0 (address), 78, 56. 34, 12, B4 (cheksum), and the slave receives all of these data, and after B4, the slave receives A1 in address_temp1, which i think is the address master sent for receiving data from slave. | You didn't show us the Master code and I'm no I2C expert but it could be you are missing an I2C stop command.
The method you use for sending the reply to the master is quick but very dirty. Check the example codes for a proper implementation. |
|
|
|
|
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
|