|
|
View previous topic :: View next topic |
Author |
Message |
elb0m
Joined: 20 Jan 2011 Posts: 3
|
I2C Master - Slave problem |
Posted: Thu Jan 20, 2011 8:14 am |
|
|
Hello.
I want to connect 2 PIC16F876A motors with I2C protocol.
On the breadboard I have 2 resistors 2.2 Kohms, one IC by Philips called PCF8574, 4 Yellow LEDS and the 2 PICS.
I have setup one as a master and the other one as a slave.
Also the IC is slave with address 0x40.
MASTER CODE:
Code: |
#include <16f876A.H>
#device adc=8
#fuses HS, NOWDT, NOBROWNOUT, NOPROTECT, PUT, NOLVP
#use delay(clock=40000000)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#define SLAVE1_WRT_ADDR 0x40
#define BUF_SIZE 8
//====================================
int trans;
void main()
{
trans=0;
while(1){
trans = trans + 1;
delay_ms(300);
i2c_start();
i2c_write(SLAVE1_WRT_ADDR);
i2c_write(trans);
i2c_stop();
delay_ms(300);
i2c_start();
i2c_write(0xA0);
i2c_write(trans);
i2c_stop();
}
}
|
SLAVE
Code: |
#include <16F876A.H>
#device adc=8
#fuses HS, NOWDT, NOBROWNOUT, NOPROTECT, PUT, NOLVP
#use delay(clock=4000000)
BYTE address, buffer[0x10];
#include <lib_mot_moway.h>
void motor_move_for();
void motor_move_back();
#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
state = i2c_isr_state(TB);
if(state <= 0x80) //Master is sending data
{
incoming = i2c_read(TB);
if(state == 1) //First received byte is address
{address = incoming;
motor_move_for();}
if(state == 2){
motor_move_back();
buffer[address] = incoming;}
}
if(state == 0x80) //Master is requesting data
{
i2c_write(TB,buffer[address]);
}
}
void main ()
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE) {}
}
void motor_move_for()
{
MOT_STR(30, FWD, TIME, 10);
while(!input(MOT_END)){}
}
void motor_move_back(){
MOT_STR(30, BACK, TIME, 10);
while(!input(MOT_END)){}
}
|
The leds connected on the PCF 8574, light on like a charm(count right) but the slave PIC has a problem. It doesn't get interrupted at once. It gets after several times (if it does) and only executes the routine move_motor_forward.
I have no clue why this is happening. Thanks.
edit
_
Even without the part where I send to pcf I still have the same problem. _________________ sins can't be undone |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19509
|
|
Posted: Thu Jan 20, 2011 9:09 am |
|
|
You don't appear to have a #use I2C, telling the slave that it's address is 0x40....
Take the movement commands out of the I2C handler. Set a flag, to say move forwards/back, and have the main code do this. Problem here is that your movements could last 'for ever', and the I2C slave receive code is _hung_ while this is happening. The bus is effectively 'jammed'....
Old 'mantra' repeated here many times. In an interrupt handler _handle_ the hardware event, and get out again ASAP. This is _essential_....
Best Wishes |
|
|
elb0m
Joined: 20 Jan 2011 Posts: 3
|
|
Posted: Thu Jan 20, 2011 10:12 am |
|
|
The use #i2c is included in the .h file that I have.
So I must set a flag, in the int_ssp and in the main program check the flag?
Ok I will do that as soon as I get back home!
Didn't understand what you said about that old mantra:/
And on that interrupt handler you mean the int_ssp right? _________________ sins can't be undone |
|
|
elb0m
Joined: 20 Jan 2011 Posts: 3
|
|
Posted: Fri Jan 21, 2011 6:37 am |
|
|
OK.
I've changed the code as you told me.
Some problems occur though.
Here is the code.
MASTER
Code: |
#include <16f876A.H>
#device adc=8
#fuses HS, NOWDT, NOBROWNOUT, NOPROTECT, PUT, NOLVP
#use delay(clock=40000000)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#define SLAVE1_WRT_ADDR 0x40
#define BUF_SIZE 8
//====================================
void main()
{
i2c_start();
i2c_write(0xA0);
i2c_write(0x13);
i2c_stop();
}
|
SLAVE
Code: |
#include <16F876A.H>
#device adc=8
#fuses HS, NOWDT, NOBROWNOUT, NOPROTECT, PUT, NOLVP
#use delay(clock=4000000)
BYTE address,data, buffer[0x10];
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xA0,stream=TB)
#include <lib_sen_moway.h>
int flag;
#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
state = i2c_isr_state(TB);
if(state <= 0x80) //Master is sending data
{
incoming = i2c_read(TB);
if(state == 1) //First received byte is address
{
flag = 1;
address = incoming;
}
if(state == 2){
flag = 2;
data = incoming;}
}
if(state == 0x80) //Master is requesting data
{
i2c_write(TB,buffer[address]);
}
}
void main ()
{ flag =0;
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE) {
if (flag==1){ LED_R_ON(); }
if (flag==2){ LED_L_ON(); if (data==0x13){LED_TOP_GREEN_ON();} }
}
}
|
So, i have both processors OFF.
I turn the slave ON(while(TRUE) loop waits for the flag, and the interrupt).
then
I turn the master ON.
Results:
Sometimes on the first time i turn the master ON the LED Right(LED_R_ON) turns on. I may have to turn several times master on-off-on-off to get that LED Right on. It doesn't get INTERRUPTED at once. When i have in while loop it works(LED_R_ON).
I don't see thought the LED_L to be turning on,neither the TOP_GREEN.
I can't understand the problem.
It might be the voltage, the resistors?
2.8V and 2.2K Resistors.
Thanks _________________ sins can't be undone |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19509
|
|
Posted: Fri Jan 21, 2011 10:55 am |
|
|
First, what powers the pull-ups?.
If it is the master, then the slave _needs_ to wait for the lines to go high, before enabling the bus. So something like:
Code: |
while ( (input(PIN_C4)==0 || input(PIN_C3)==0) ;
//Now start the interrupt
|
Otherwise it could easily see the bus as in an indeterminate start/stop condition, and get into a hung state, before starting.....
2.2K, is 'highish', if your bus really is at 2.8v. Depends on your likely bus capacitance, but for 2.8v, the minimum value for the pull-ups, is just 800R. I'd suggest something like 1.2K, would be safer at such a low voltage.
When the 876A, was designed, the _minimum_ specified voltage for I2C, was 3V (it has since been reduced), and I'd be significantly worried whether this chip is actually going to be happy running I2C at such a low voltage...
Best Wishes |
|
|
|
|
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
|