|
|
View previous topic :: View next topic |
Author |
Message |
luqman82303
Joined: 17 Feb 2020 Posts: 7
|
I2c communication arduino master pic slave |
Posted: Mon Feb 17, 2020 9:37 am |
|
|
I am working on I2c communication between Arduino master and slave pic18f4520. The code I use works well on Proteus but when I implement on hardware it doesn't work. I don't get what the problem behind that can be. Anyone please help...
In the master there is simple LCD code is merged so sorry for that.
Slave PIC:
Code: |
#include <18F4520.h>
#fuses HS, NOWDT,PUT,BROWNOUT,NOLVP
#fuses HS, PR, NOWDT
#use delay(clock=16000000)
#include <lcd.c>
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, ADDRESS=0x30, force_hw)
#INT_SSP
void ssp_interrupt()
{
//Clear Display
int8 incoming, state;
state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
for(int i=0; i<=3 ; i++)
{
incoming = i2c_read();
output_high(PIN_B1);
printf(lcd_putc,"recev = %d",incoming);
delay_ms(1000);
//lcd_putc("Hello World");
output_low(PIN_B1);
}
}
if(state >= 0x80) // Master is requesting data from slave
{
output_high(PIN_A1);
lcd_putc("master WANT READ");
i2c_write(1);
delay_ms (1000);
output_low(PIN_A1);
}
}
//======================================
void main ()
{
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
}
|
Master:
Code: |
// Include Arduino Wire library for I2C
#include <Wire.h>
#include <LiquidCrystal.h>
//#include <twi.h>
// Define Slave I2C Address
//#define SLAVE_ADDR
#define SLAVE_ADDR 0x30
//#define TWI_FREQ 16000000
// Define Slave answer size
#define ANSWERSIZE 1
// Define LED Pin
int LED = 13;
int b ;
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup()
{
Wire.begin();
Wire.setClock(200000);
//Serial.begin(9600);
Serial.begin(115200);
//lcd
lcd.begin(16, 2); // set up the LCD's number of columns and rows:
// Print a message to the LCD.
// lcd.print("hello, world!");
//master
pinMode(LED, OUTPUT);
//Wire.setClock(400); // Initialize I2C communications as Master
}
void loop()
{
lcd.noDisplay();
delay(50);
lcd.display();////////display on
////////////////////////////////////////////////////////////////
// Write a character to the Slave
// Wire.beginTransmission(SLAVE_ADDR);
Wire.beginTransmission((SLAVE_ADDR<<1)|0x00);
//lcd.print("master write");
//delay(500);
for(int i =0;i <=3 ;i++)
{
Serial.println("Write data to slave");
lcd.print("master write");
Wire.write(i);
delay(500);
lcd.clear();
}
delay(500);
lcd.clear();
Wire.endTransmission();
////////////////////////////////////////////////////////////////////////////////////// Serial.println("ENG");
Wire.requestFrom(SLAVE_ADDR,ANSWERSIZE); // // Read response from Slave
String response = ""; // // Add characters to string
while (Wire.available())
{
Serial.println("READ data FROM slave");
//lcd.print("read from slave");// print the character
//delay(500);
// slave may send less than requested
int c = Wire.read(); // receive a byte as character
lcd.print("read from slave");// print the character
delay(500);
digitalWrite(LED, HIGH);
lcd.clear();
if(c == 1)
{
lcd.print("read done");
delay (500);
}
// response++;
lcd.clear(); // Turn off the display
digitalWrite(LED, LOW);
}
delay(500);
} |
|
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Mon Feb 17, 2020 9:43 am |
|
|
Forget proteus/ISIS, unlikely anyone here can help.
Use real hardware instead.
Mike |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Mon Feb 17, 2020 9:47 am |
|
|
What Mike says...
Please read sticky above, PIC101, http://www.ccsinfo.com/forum/viewtopic.php?t=47549
It's well known that Proteus is defective, busted, corrupt, damaged, doesn't work reliably. NO Proteus schematic EVER presented here will work in the Real World.......NONE !
OK, with real hardware, what's the VDD of the system ?
These 2 lines of code inside the ISR:
Quote: |
printf(lcd_putc,"recev = %d",incoming);
delay_ms(1000);
|
are a HUGE problem. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Mon Feb 17, 2020 10:38 am |
|
|
On state==80, you must read, then write.
If you don't, it causes an issue in the I2C hardware that Proteus doesn't
know about.....
It''s the only state where this has to happen.
The INT_SSP means _one_ transaction is occurring. Not 3. You need to
read/write just one byte.
Don't print in the ISR. The ISR needs to be handled and exited quickly.
Same comment about the delays.
Use the 'code' buttons when posting.
Code: |
int8 bytes[2]; //small buffer for received
int1 have_data=FALSE;
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state <= 0x80) // Master is sending data
{ //Note the = here
incoming = i2c_read();
if (state>0 && state<3)
bytes[state-1]=incoming; //store data
if (state==2)
have_data=TRUE; //flag pair of bytes received
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(1);
}
}
|
Then in your main, test for have_data==TRUE, then set it false and
print the bytes from 'bytes'. |
|
|
luqman82303
Joined: 17 Feb 2020 Posts: 7
|
|
Posted: Mon Feb 17, 2020 11:58 am |
|
|
temtronic wrote: | What Mike says...
Please read sticky above, PIC101, http://www.ccsinfo.com/forum/viewtopic.php?t=47549
It's well known that Proteus is defective, busted, corrupt, damaged, doesn't work reliably. NO Proteus schematic EVER presented here will work in the Real World.......NONE !
OK, with real hardware, what's the VDD of the system ?
These 2 lines of code inside the ISR:
Quote: |
printf(lcd_putc,"recev = %d",incoming);
delay_ms(1000);
|
are a HUGE problem.
|
Thanks for reply!!
I just remove these line but there is a problem about ISR(). They never called even if i just put a simple blink led in interrupt function they not even go there !!
What is reason behind that why ?
Code: | enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL); | there interrupt never enable
i am new in pic so anything false i mention sorry for that. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 17, 2020 12:13 pm |
|
|
When the program falls off the end of main(), the PIC will go into Sleep
mode. CCS puts a SLEEP instruction at the end. (They don't tell you this).
To keep the PIC running, put a while(TRUE) statement at the end of the
program, as shown below in bold:
Quote: |
void main ()
{
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(TRUE);
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Mon Feb 17, 2020 12:51 pm |
|
|
re: sleep....
from the disassembled listing of my current program...
Code: |
182: } //end of main
1096 0003 SLEEP
|
Yes, it's probably not in the manual, I've never checked. I've also never looked for a list of 'keywords' that should never be used as variables. I assume there is, I know MS BASIC had a list !
CCS does tell you, well, kind of, it is there, in the listing. Problem is, I bet not
too many programmers actually look at the listing. |
|
|
luqman82303
Joined: 17 Feb 2020 Posts: 7
|
|
Posted: Mon Feb 17, 2020 4:47 pm |
|
|
Ttelmah wrote: | On state==80, you must read, then write.
If you don't, it causes an issue in the I2C hardware that Proteus doesn't
know about.....
It''s the only state where this has to happen.
The INT_SSP means _one_ transaction is occurring. Not 3. You need to
read/write just one byte.
Don't print in the ISR. The ISR needs to be handled and exited quickly.
Same comment about the delays.
Use the 'code' buttons when posting.
Code: |
int8 bytes[2]; //small buffer for received
int1 have_data=FALSE;
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state <= 0x80) // Master is sending data
{ //Note the = here
incoming = i2c_read();
if (state>0 && state<3)
bytes[state-1]=incoming; //store data
if (state==2)
have_data=TRUE; //flag pair of bytes received
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(1);
}
}
|
Then in your main, test for have_data==TRUE, then set it false and
print the bytes from 'bytes'.
|
Thanks for reply!!
I check those lines in my compiler but nothing is happening in i2c() interrupt!
I don't get the point, why the code is not going into isr function !!
Is there any hardware problem or the oscillator i use is not matched with Arduino crystal? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 17, 2020 6:33 pm |
|
|
luqman82303 wrote: |
I don't get the point, why the code is not going into isr function !!
|
Did you read my post and do what I said ?
Do you have pull-up resistors on the SDA and SCL lines ? (4.7K ohms) |
|
|
luqman82303
Joined: 17 Feb 2020 Posts: 7
|
|
Posted: Mon Feb 17, 2020 9:03 pm |
|
|
PCM programmer wrote: | luqman82303 wrote: |
I don't get the point, why the code is not going into isr function !!
|
Did you read my post and do what I said ?
Do you have pull-up resistors on the SDA and SCL lines ? (4.7K ohms) |
Yes I have 4.7k ohm resistor on scl and sda |
|
|
emaxxenon
Joined: 21 Jan 2020 Posts: 42
|
|
Posted: Mon Feb 17, 2020 11:41 pm |
|
|
Would you share the connection scheme? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Feb 18, 2020 3:49 am |
|
|
You didn't answer the question again !
Did you add the line shown in bold below ?
Quote: | void main ()
{
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(TRUE); // *** ADD THIS LINE ***
}
|
|
|
|
luqman82303
Joined: 17 Feb 2020 Posts: 7
|
|
Posted: Tue Feb 18, 2020 1:01 pm |
|
|
Thanks everyone .. so my I2c hardware finally in working !!
Slave
Code: |
#include <18F452.H>
#fuses HS, NOWDT,PUT,BROWNOUT,NOLVP
#use delay(crystal=16000000)
//#use delay (clock=8000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, ADDRESS=0x18, force_hw)
int8 bytes[2]; //small buffer for received
int1 have_data=FALSE;
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state <= 0x80) // Master is sending data
{ //Note the = here
output_high(PIN_A1);
incoming = i2c_read();
if (state>0 && state<3)
bytes[state-1]=incoming; //store data
if (state==2)
have_data=TRUE; //flag pair of bytes received
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(1);
}
}
void main ()
{
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(TRUE);
} |
Code: |
//////////////////////////////////master//////////////
/*
i2c-master-demo.ino
Demonstrate use of I2C bus
Master sends character and gets reply from Slave
DroneBot Workshop 2019
https://dronebotworkshop.com
*/
// Include Arduino Wire library for I2C
#include <Wire.h>
#include <stream.h>
#include <LiquidCrystal.h>
//#include <twi.h>
// Define Slave I2C Address
//#define SLAVE_ADDR
#define SLAVE_ADDR 0x0c
//#define TWI_FREQ 16000000
// Define Slave answer size
#define ANSWERSIZE 1
// Define LED Pin
int LED = 13;
int b ;
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup()
{
Wire.begin();
Wire.setClock(100000);
Serial.begin(9600);
//Serial.begin(115200);
//////////////////////////lcd
lcd.begin(16, 2); // set up the LCD's number of columns and rows:
// Print a message to the LCD.
// lcd.print("hello, world!");
/////////////////////////////////////////////////master
pinMode(LED, OUTPUT);
//Wire.setClock(400); // Initialize I2C communications as Master
}
void loop()
{
//////////////////////////
lcd.noDisplay();
delay(50);
lcd.display();////////display on
////////////////////////////////////////////////////////////////
// Write a character to the Slave
Wire.beginTransmission(SLAVE_ADDR);
//Wire.beginTransmission((SLAVE_ADDR<<1)|0x00);
//lcd.print("master write");
//delay(500);
// for(int i =0;i <=3 ;i++)
// {
Serial.println("Write data to slave");
lcd.print("master write");
Wire.write(1);
//Wire.write(2);
//delay(500);
//lcd.clear();
// }
delay(500);
lcd.clear();
Wire.endTransmission();
////////////////////////////////////////////////////////////////////////////////////////////////
Wire.requestFrom(SLAVE_ADDR,ANSWERSIZE); // // Read response from Slave
String response = ""; // // Add characters to string
while (Wire.available())
{
Serial.println("READ data FROM slave");
//lcd.print("read from slave");// print the character
//delay(500);
// slave may send less than requested
int c = Wire.read(); // receive a byte as character
lcd.print("read from slave");// print the character
delay(500);
digitalWrite(LED, HIGH);
lcd.clear();
if(c == 1)
{
Serial.println("read done");
lcd.print("read done");
delay (500);
}
// response++;
lcd.clear(); // Turn off the display:
digitalWrite(LED, LOW);
}
delay(500);
} |
|
|
|
|
|
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
|