|
|
View previous topic :: View next topic |
Author |
Message |
jayanthd
Joined: 06 Dec 2012 Posts: 47 Location: Banned - pirate
|
|
Posted: Sat Mar 23, 2013 3:49 pm |
|
|
@Ttelmah
Quote: | Have you just tried the examples you have been pointed to? |
What examples? Who pointed to them?
Quote: | Have you ever actually written a program that works? |
Yes. You can see in this thread where I posted a link for my project using mikroC. It uses I2C for DS1307.
Quote: |
You _claim_ to have used other languages, but every language _requires_ you to follow it's syntax precisely. You are not even trying. |
What syntax in my code are wrong?
Quote: |
1) You are now trying to read twice in state zero.
2) You are now trying to issue start conditions in the slave - the _master_ is the only chip that can issue starts.
3) Same applies for stops
4) You are now trying to write four bytes in one ISR in the slave - I've already shown how to write multiple bytes.
5) When you actually solve the above, stop and think for a moment. What happens if the slave changes the value half way through an I2C transaction? |
If I don't include the starts and stops in slave, then slave is hanging.
Where have you shown how to write multiple bytes? Please point me to the link.
Is this slave code correct?
Code: |
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
incoming = i2c_read();
}
if((state == 0) || (state == 0x80)) // Master is requesting data from slave
{
i2c_read();
}
if(state > 0x80) // Master is requesting data from slave
{
i2c_write(fvalue.bytes[ctr]);
ctr++;
if(ctr > 3) ctr = 0;
}
}
|
Are you telling me to use this code from EX_SLAVE.C ??
Code: |
{
unsigned int8 incoming, state;
state = i2c_isr_state();
if(state <= 0x80) //Master is sending data
{
if(state == 0x80)
incoming =i2c_read(2); //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
else
incoming = i2c_read();
if(state == 1) //First received byte is address
address = incoming;
else if(state >=2 && state !=0x80) //Received byte is data
buffer[address++] = incoming;
else if(state == 0x80);
address--;
}
if(state >= 0x80) //Master is requesting data
{
i2c_write(buffer[++address]);
}
}
|
Last edited by jayanthd on Sat Mar 23, 2013 4:02 pm; edited 1 time in total |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1345
|
|
Posted: Sat Mar 23, 2013 3:59 pm |
|
|
I'm not an I2C expert, but I am unsure (in reference to the master code) if a NACK can be sent multiple times before a stop condition. I've not seen a device operate where you do
start
read(NACK)
start
read(NACK)
and so on.
Again, it might be fine, but one of the more seasoned veterans might chime in just in case.
Last edited by jeremiah on Sat Mar 23, 2013 4:08 pm; edited 2 times in total |
|
|
jayanthd
Joined: 06 Dec 2012 Posts: 47 Location: Banned - pirate
|
|
Posted: Sat Mar 23, 2013 4:03 pm |
|
|
jeremiah wrote: | I'm not an I2C expert, but I am unsure (in reference to the master code) if a NACK can be sent multiple times before a stop condition. I've not seen a device operate where you do
start
read(NACK)
start
read(NACK)
and so on.
Again, it might be fine, but one of the more seasoned veterans might chime in just in case. |
Ok. See my last post. What is wrong in my Slave ISR code? What modifications should I do in the master code?
Here is my new ISR code for Slave
Code: |
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
BYTE address;
state = i2c_isr_state();
if(state <= 0x80) // Master is sending data
{
if(state == 0x80)
incoming =i2c_read();
//else
//incoming = i2c_read();
if(state == 1) //First received byte is address
address = incoming;
else if(state >=2 && state !=0x80) //Received byte is data
;
else if(state == 0x80);
address--;
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_read();
i2c_write(fvalue.bytes[ctr]);
ctr++;
if(ctr > 3) ctr = 0;
}
}
|
Is this correct? I am reading and writing when state >= 0x80
Last edited by jayanthd on Sat Mar 23, 2013 4:22 pm; edited 2 times in total |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1345
|
|
Posted: Sat Mar 23, 2013 4:13 pm |
|
|
I did see your last post, I am making the comment because it could be bad for the hardware longterm and you may not notice it at this point.
as for the ISR:
The order for your slave ISR is incorrect. Please reference the example I mentioned in a previous post (the example code in the manual entry for i2c_isr_state ). You should use the if/else structure they suggest.
Also, long term you probably don't want to save your data read by the slave in incoming as if you aren't quick enough to save it elsewhere, you'll miss it when the next byte comes through.
I haven't read through ex_slave.c (we actually aren't allowed to post example code here), so I don't know the full context of that blurb. One of the other guys can comment on if that particular example is good or not. I've only ever modeled it out of the manual example. |
|
|
jayanthd
Joined: 06 Dec 2012 Posts: 47 Location: Banned - pirate
|
|
Posted: Sat Mar 23, 2013 4:17 pm |
|
|
@jerimiah
See my last post. I have written a new ISR for Slave.
See this document page no. 13 http://www.eti.pg.gda.pl/katedry/ksg/dydaktyka/dla_studentow//i2c.pdf
It tells if device want to send data more than once it has to issue i2c restart. Then why we are not issuing i2c_start() or i2c_restart() in the slave code? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sat Mar 23, 2013 5:12 pm |
|
|
To add to the mentioned problems there is still the TRIS setting problem: Code: | set_tris_a(0xFF);
set_tris_d(0x00);
output_a(0x00); | Setting port A to be all input is fine, though it is the same as the power up default so not required. Then outputting 0x00 to port A corrupts the whole port A setting. It doesn't make sense to first set the port to input and then outputting data, but, even worse is that the CCS compiler will write the TRIS-A register to make them all outputs. Your analog inputs on these ports will all read 0 after that. |
|
|
jayanthd
Joined: 06 Dec 2012 Posts: 47 Location: Banned - pirate
|
|
Posted: Sat Mar 23, 2013 5:20 pm |
|
|
ckielstra wrote: | To add to the mentioned problems there is still the TRIS setting problem: Code: | set_tris_a(0xFF);
set_tris_d(0x00);
output_a(0x00); | Setting port A to be all input is fine, though it is the same as the power up default so not required. Then outputting 0x00 to port A corrupts the whole port A setting. It doesn't make sense to first set the port to input and then outputting data, but, even worse is that the CCS compiler will write the TRIS-A register to make them all outputs. Your analog inputs on these ports will all read 0 after that. |
If I comment those tris setting used for lcd port and adc port then adc and lcd doesn't work. I tested it already.
Ok. I removed the tris codes from master and slave and lcd is working fine but i2c is not working i.e., data displayed by master is wrong.
No. with output_a(0x00) adc reads fine but I removed it and still adc works fine.
This is my new code. I am getting some value at master but not the right value.
Master Code
Code: |
#include <16F887.h>
#device adc=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000) //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3, FORCE_HW) //FORCE_HW, stream=I2CM
#define SLAVE1_WRT_ADDR 0x12
#define SLAVE1_READ_ADDR 0x13
#define SLAVE2_WRT_ADDR 0x22
#define SLAVE2_READ_ADDR 0x23
float fdata1 = 0, fdata2 = 0;
union float2bytes {
float fval;
int8 bytes[4];
}fvalue;
union float2bytes1 {
float fval1;
int8 bytes1[4];
}fvalue1;
#define LCD_ENABLE_PIN PIN_D2
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
void main()
{
delay_ms(250);
lcd_init();
delay_ms(250);
lcd_putc("\fMaster...\n");
delay_ms(1000);
while(TRUE)
{
i2c_start(1);
i2c_write(SLAVE1_READ_ADDR);
fvalue.bytes[0] = i2c_read();
i2c_start();
fvalue.bytes[1] = i2c_read();
i2c_start();
fvalue.bytes[2] = i2c_read();
i2c_start();
fvalue.bytes[3] = i2c_read(0);
i2c_stop();
delay_ms(100);
i2c_start(1);
i2c_write(SLAVE2_READ_ADDR);
fvalue1.bytes1[0] = i2c_read();
i2c_start();
fvalue1.bytes1[1] = i2c_read();
i2c_start();
fvalue1.bytes1[2] = i2c_read();
i2c_start();
fvalue1.bytes1[3] = i2c_read(0);
i2c_stop();
if((fvalue.fval != fdata1) || (fvalue1.fval1 != fdata2)) {
printf(lcd_putc, "\a%5.2f %5.2f", fvalue.fval, fvalue1.fval1);
printf("%5.2f %5.2f\r\n", fvalue.fval, fvalue1.fval1);
fdata1 = fvalue.fval;
fdata2 = fvalue1.fval1;
}
delay_ms(250);
}
}
|
Slave 1 Code
Code: |
#include <16F887.h>
#device adc=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000) //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x12, FORCE_HW) //FORCE_HW, stream=I2CS
#define LCD_ENABLE_PIN PIN_D2
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
float temp = 0, old_val = 0;
int8 ctr = 0;
union float2bytes {
float fval;
int8 bytes[4];
} fvalue;
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
incoming = i2c_read();
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(fvalue.bytes[ctr]);
ctr++;
if(ctr==4)ctr = 0;
}
}
void main()
{
int16 adc_val = 0;
setup_adc_ports(sAN0|VREF_VREF);
setup_adc(ADC_CLOCK_DIV_2);
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
delay_ms(250);
lcd_init();
delay_ms(250);
lcd_putc("\fSlave 1...\n");
set_adc_channel(0);
delay_us(20);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(TRUE)
{
adc_val = read_adc();
delay_ms(20);
temp = (float)(adc_val * 0.196078431372549);
fvalue.fval = temp;
if(old_val != temp){
printf(lcd_putc, "\a%5.2f", temp);
printf("Temperature is: %5.2f", temp);
printf(" Degree Centigrade\r\n");
printf("%5.2f\r\n", fvalue.fval);
printf("%lu\r\n", adc_val);
}
old_val = temp;
}
}
|
Slave 2 Code
Code: |
#include <16F887.h>
#device adc=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000) //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x22, FORCE_HW) //FORCE_HW, stream=I2CS
#define LCD_ENABLE_PIN PIN_D2
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
float temp = 0, old_val = 0;
int8 ctr = 0;
union float2bytes {
float fval;
int8 bytes[4];
} fvalue;
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
incoming = i2c_read();
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(fvalue.bytes[ctr]);
ctr++;
if(ctr==4)ctr = 0;
}
}
void main()
{
int16 adc_val = 0;
setup_adc_ports(sAN0|VREF_VREF);
setup_adc(ADC_CLOCK_DIV_2);
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
delay_ms(250);
lcd_init();
delay_ms(250);
lcd_putc("\fSlave 1...\n");
set_adc_channel(0);
delay_us(20);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(TRUE)
{
adc_val = read_adc();
delay_ms(20);
temp = (float)(adc_val * 0.196078431372549);
fvalue.fval = temp;
if(old_val != temp){
printf(lcd_putc, "\a%5.2f", temp);
printf("Temperature is: %5.2f", temp);
printf(" Degree Centigrade\r\n");
printf("%5.2f\r\n", fvalue.fval);
printf("%lu\r\n", adc_val);
}
old_val = temp;
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Sun Mar 24, 2013 1:52 am |
|
|
Code: |
//Slave ISR for data transmission
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
static BYTE address; //This needs to hold it's value between calls
state = i2c_isr_state();
if(state <= 0x80) // Master is sending data
{
incoming =i2c_read(); //Simply read in all states where a byte arrives
if(state == 1) //First received byte is address
address = incoming;
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(fvalue.bytes[address++]);
if(address> 3) address = 0;
}
}
//Master code to call this
union {
float value;
byte b[4];
} val;
int count;
i2c_start();
i2c_write(SLAVE_ADDRESS);
i2c_write(0); //byte to read - register address 0
i2c_start(); //restart
i2c_write(SLAVE_ADDRESS+1);
for (count=0;count<4;count++)
{
if (count==3)
val.b[3]=i2c_read(0); //invert ACK on last byte
else
val.b[count]=i2c_read();
}
i2c_stop();
//now val.value is the float received from the slave
|
The problem is you keep putting extra reads/writes in where they are not needed. You were told to add a read to state 0x80, added this, but also added one to states 0x81, 0x82 etc...
Now there is a separate issue still present here that the slave could change the value between calls. This is where a sync flag between the routines is needed, or toggling between two buffers. |
|
|
jayanthd
Joined: 06 Dec 2012 Posts: 47 Location: Banned - pirate
|
|
Posted: Sun Mar 24, 2013 2:12 am |
|
|
I found on this page http://www.ccsinfo.com/forum/viewtopic.php?t=21456
that some registers related to i2c and spi have to be configured. The 16F887.h file doesn't contain these information. I have to add these register configurations in master and slave codes.
Somebody please check and tell whether my setting are right for both master and slave. I have set the values as mentioned in the PIC16F887 datasheet.
Master
Code: |
MASTER
* 16f887 bytes */
/* Change it per chip */
#byte PIC_SSPBUF=0x13
#byte PIC_SSPADD=0x93
#byte PIC_SSPSTAT=0x94
#byte PIC_SSPCON=0x14
#byte PIC_SSPCON2=0x91
/* Bit defines */
#define PIC_SSPSTAT_BIT_SMP 0x00
#define PIC_SSPSTAT_BIT_CKE 0x01
#define PIC_SSPSTAT_BIT_DA 0x00
#define PIC_SSPSTAT_BIT_P 0x00
#define PIC_SSPSTAT_BIT_S 0x00
#define PIC_SSPSTAT_BIT_RW 0x00
#define PIC_SSPSTAT_BIT_UA 0x00
#define PIC_SSPSTAT_BIT_BF 0x00
#define PIC_SSPCON_BIT_WCOL 0x00
#define PIC_SSPCON_BIT_SSPOV 0x00
#define PIC_SSPCON_BIT_SSPEN 0x01
#define PIC_SSPCON_BIT_CKP 0x00
#define PIC_SSPCON_BIT_SSPM3 0x01
#define PIC_SSPCON_BIT_SSPM2 0x00
#define PIC_SSPCON_BIT_SSPM1 0x00
#define PIC_SSPCON_BIT_SSPM0 0x00
#define PIC_SSPCON2_BIT_GCEN 0x00
#define PIC_SSPCON2_BIT_ACKSTAT 0x01
#define PIC_SSPCON2_BIT_ACKDT 0x00
#define PIC_SSPCON2_BIT_ACKEN 0x01
#define PIC_SSPCON2_BIT_RCEN 0x01
#define PIC_SSPCON2_BIT_PEN 0x00
#define PIC_SSPCON2_BIT_RSEN 0x00
#define PIC_SSPCON2_BIT_SEN 0x00
|
Slave
Code: |
* 16f887 bytes */
/* Change it per chip */
#byte PIC_SSPBUF=0x13
#byte PIC_SSPADD=0x93
#byte PIC_SSPSTAT=0x94
#byte PIC_SSPCON=0x14
#byte PIC_SSPCON2=0x91
/* Bit defines */
#define PIC_SSPSTAT_BIT_SMP 0x00
#define PIC_SSPSTAT_BIT_CKE 0x01
#define PIC_SSPSTAT_BIT_DA 0x01
#define PIC_SSPSTAT_BIT_P 0x00
#define PIC_SSPSTAT_BIT_S 0x00
#define PIC_SSPSTAT_BIT_RW 0x01
#define PIC_SSPSTAT_BIT_UA 0x00
#define PIC_SSPSTAT_BIT_BF 0x00
#define PIC_SSPCON_BIT_WCOL 0x00
#define PIC_SSPCON_BIT_SSPOV 0x00
#define PIC_SSPCON_BIT_SSPEN 0x01
#define PIC_SSPCON_BIT_CKP 0x00
#define PIC_SSPCON_BIT_SSPM3 0x00
#define PIC_SSPCON_BIT_SSPM2 0x01
#define PIC_SSPCON_BIT_SSPM1 0x01
#define PIC_SSPCON_BIT_SSPM0 0x00
#define PIC_SSPCON2_BIT_GCEN 0x01
#define PIC_SSPCON2_BIT_ACKSTAT 0x01
#define PIC_SSPCON2_BIT_ACKDT 0x00
#define PIC_SSPCON2_BIT_ACKEN 0x00
#define PIC_SSPCON2_BIT_RCEN 0x00
#define PIC_SSPCON2_BIT_PEN 0x00
#define PIC_SSPCON2_BIT_RSEN 0x00
#define PIC_SSPCON2_BIT_SEN 0x00
|
I tried your new code Ttelmah and it doesn't work. The master doesn't display the read values and the slave hangs and the slave lcd data doesn't update.
I tried with one master and one slave.
Here is the codes I used
MASTER
Code: |
#include <16F887.h>
#device adc=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000) //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3) //FORCE_HW, stream=I2CM
/*
#define SLAVE1_WRT_ADDR 0x12
#define SLAVE1_READ_ADDR 0x13
#define SLAVE2_WRT_ADDR 0x22
#define SLAVE2_READ_ADDR 0x23
*/
#define SLAVE1_ADDRESS 0x12
#define SLAVE2_ADDRESS 0x22
float fdata1 = 0, fdata2 = 0;
/*
union float2bytes {
float fval;
int8 bytes[4];
}fvalue;
union float2bytes1 {
float fval1;
int8 bytes1[4];
}fvalue1;
*/
union {
float value;
byte b[4];
} val;
int count;
#define LCD_ENABLE_PIN PIN_D2
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
void main()
{
delay_ms(250);
lcd_init();
delay_ms(250);
lcd_putc("\fMaster...\n");
delay_ms(500);
while(TRUE)
{
i2c_start();
i2c_write(SLAVE1_ADDRESS);
i2c_write(0); //byte to read - register address 0
i2c_start(); //restart
i2c_write(SLAVE1_ADDRESS+1);
for (count=0;count<4;count++)
{
if (count==3){
val.b[3]=i2c_read(0); //invert ACK on last byte
count = 0;
}
else
val.b[count]=i2c_read();
}
i2c_stop();
//now val.value is the float received from the slave
delay_ms(500);
/*
i2c_start(1);
//i2c_write(SLAVE1_WRT_ADDR);
//i2c_start();
i2c_write(SLAVE1_READ_ADDR);
fvalue.bytes[0] = i2c_read(1);
i2c_start();
//i2c_write(0x13);
fvalue.bytes[1] = i2c_read(1);
i2c_start();
//i2c_write(0x13);
fvalue.bytes[2] = i2c_read(1);
i2c_start();
//i2c_write(0x13);
fvalue.bytes[3] = i2c_read(0);
i2c_stop();
delay_ms(100);
i2c_start(1);
i2c_write(SLAVE2_READ_ADDR);
fvalue1.bytes1[0] = i2c_read();
i2c_start();
fvalue1.bytes1[1] = i2c_read();
i2c_start();
fvalue1.bytes1[2] = i2c_read();
i2c_start();
fvalue1.bytes1[3] = i2c_read(0);
i2c_stop();
*/
if(val.value != fdata1) {
printf(lcd_putc, "\a%5.2f", val.value);
printf("%5.2f\r\n", val.value);
//printf("%d %d %d %d", fvalue.bytes[0], fvalue.bytes[1], fvalue.bytes[2], fvalue.bytes[3]);
fdata1 = val.value;
//fdata2 = val1.value;
}
//delay_ms(250);
}
}
|
SLAVE
Code: |
#include <16F887.h>
#device adc=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000) //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x12) //FORCE_HW, stream=I2CS
#define LCD_ENABLE_PIN PIN_D2
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
float temp = 0, old_val = 0;
int8 ctr = 0;
union float2bytes {
float fval;
int8 bytes[4];
} fvalue;
/*int8 cnt = 0;
int8 buffer[3], c;
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
incoming = i2c_read();
}
else if((state== 0) || (state == 0x80)) {
incoming = i2c_read(1);
//i2c_write(cnt++);
i2c_write(fvalue.bytes[ctr]);
ctr++;
}
else if(state > 0x80) // Master is requesting data from slave
{
i2c_write(fvalue.bytes[ctr]);
ctr++;
if(ctr==4)ctr = 0;
//i2c_read(0);
//i2c_write(cnt++);
}
}
*/
//Slave ISR for data transmission
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
static BYTE address; //This needs to hold it's value between calls
state = i2c_isr_state();
if(state <= 0x80) // Master is sending data
{
incoming =i2c_read(); //Simply read in all states where a byte arrives
if(state == 1) //First received byte is address
address = incoming;
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(fvalue.bytes[address++]);
if(address> 3) address = 0;
}
}
void main()
{
int16 adc_val = 0;
setup_adc_ports(sAN0|VREF_VREF);
setup_adc(ADC_CLOCK_DIV_2);
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
delay_ms(250);
lcd_init();
delay_ms(250);
lcd_putc("\fSlave 1...\n");
set_adc_channel(0);
delay_us(20);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(TRUE)
{
adc_val = read_adc();
delay_ms(20);
temp = (float)(adc_val * 0.196078431372549);
fvalue.fval = temp;
if(old_val != temp){
printf(lcd_putc, "\a%5.2f", temp);
printf("Temperature is: %5.2f", temp);
printf(" Degree Centigrade\r\n");
printf("%5.2f\r\n", fvalue.fval);
printf("%lu\r\n", adc_val);
}
old_val = temp;
}
}
|
If you can fix it please do it. |
|
|
jayanthd
Joined: 06 Dec 2012 Posts: 47 Location: Banned - pirate
|
|
Posted: Sun Mar 24, 2013 3:26 am |
|
|
My Master code works but Ttelmah's master code hangs the slave. I am using Ttelmah's slave ISR.
The problem is my master code gives the value -3.99 which is wrong value and the value never changes.
My master code doesn't hang any PICs and I see I2C communication happening every 1 sec as I have used a 1 sec delay in master code but the value never changes from -3.99
http://www.pixhost.org/show/4608/16407091_i2cp.jpg
MASTER code
Code: |
#include <16F887.h>
#device adc=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000) //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3) //FORCE_HW, stream=I2CM
#define SLAVE1_WRT_ADDR 0x12
#define SLAVE1_READ_ADDR 0x13
#define SLAVE2_WRT_ADDR 0x22
#define SLAVE2_READ_ADDR 0x23
#define SLAVE1_ADDRESS 0x12
#define SLAVE2_ADDRESS 0x22
float fdata1 = 0, fdata2 = 0;
/*
union float2bytes {
float fval;
int8 bytes[4];
}fvalue;
union float2bytes1 {
float fval1;
int8 bytes1[4];
}fvalue1;
*/
union {
float value;
byte b[4];
} val;
int count;
#define LCD_ENABLE_PIN PIN_D2
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
void main()
{
delay_ms(250);
lcd_init();
delay_ms(250);
lcd_putc("\fMaster...\n");
delay_ms(500);
while(TRUE)
{
/*
i2c_start();
i2c_write(SLAVE1_ADDRESS);
i2c_write(0); //byte to read - register address 0
i2c_start(); //restart
i2c_write(SLAVE1_ADDRESS+1);
for (count=0;count<4;count++)
{
if (count==3){
val.b[3]=i2c_read(0); //invert ACK on last byte
count = 0;
}
else
val.b[count]=i2c_read(1);
}
i2c_stop();
//now val.value is the float received from the slave
delay_ms(500);
*/
i2c_start(1);
i2c_write(SLAVE1_WRT_ADDR);
i2c_write(0);
i2c_start();
i2c_write(SLAVE1_READ_ADDR);
val.b[0] = i2c_read(1);
i2c_start();
//i2c_write(0x13);
val.b[1] = i2c_read(1);
i2c_start();
//i2c_write(0x13);
val.b[2] = i2c_read(1);
i2c_start();
//i2c_write(0x13);
val.b[3] = i2c_read(0);
i2c_stop();
/*
delay_ms(100);
i2c_start(1);
i2c_write(SLAVE2_READ_ADDR);
fvalue1.bytes1[0] = i2c_read();
i2c_start();
fvalue1.bytes1[1] = i2c_read();
i2c_start();
fvalue1.bytes1[2] = i2c_read();
i2c_start();
fvalue1.bytes1[3] = i2c_read(0);
i2c_stop();
*/
if(val.value != fdata1) {
printf(lcd_putc, "\a%5.2f", val.value);
printf("%5.2f\r\n", val.value);
//printf("%d %d %d %d", fvalue.bytes[0], fvalue.bytes[1], fvalue.bytes[2], fvalue.bytes[3]);
//fdata2 = val1.value;
}
fdata1 = val.value;
delay_ms(1000);
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Sun Mar 24, 2013 6:05 am |
|
|
PCM_programmer posted a link to multi byte I2C routines right at the start of your thread.
Remove the complexity.
Like most people not used to debugging, you are making the problem too complex. Try sending a packet of known data, with none of the other fiddling around (no temperature reading, and just simple display of the data). Your code should be no more than about 30 lines at each end including headers.
Once you have this working then move on and try adding more.
If the examples don't work, then stop and look at your hardware. You _have_ got suitable pull up resistors on the bus?. You have got the grounds connected between the units?. How long is the bus?.
There are actually two errata for the 16F887 chip affecting I2C, which could explain a lot. First as a slave device, the device will prematurely release the clock line on the last byte of a multi byte transfer. Means the master _must_ pause at this point. You do delay here, but a 'caveat' for the future. Then as a master device, there is a real humdinger on handling clock stretching incorrectly. Try switching to using the software I2C on the master, instead of hardware, and see if things change.... |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Mar 24, 2013 6:37 am |
|
|
I enjoyed the beers last night, and wake up to find this thread about to spill over to page 5.
Here's my take with a few quotes thrown in.
Quote: | I finally got the i2c working somewhat but lcd is not working now. Same problem in hardware and proteus. | You've got the I2C 'working somewhat', then go off on an LCD chase.
To me, 'working somewhat' isn't good enough.
You should be getting the I2C working better than that before going off elsewhere.
Quote: | I believe the problem lays between the screen and the back of your chair.
What does that mean? | Draw a line from screen to head rest.
Then another from left ear to right.
Where do the two lines meet?
I told you back on page 2 that CCS is a different beast.
It takes some effort to get your brain into a totally new way of thinking.
It's a bit like the difference between say 'FORTH' and 'BASIC', 'WINDOWS' and 'DOS'.
At this stage, you're simply not getting it.
As I said before, I've used other 'C' compilers.
I know that Hi-Tek is not very far removed from assembler as far as register operations are concerned.
With CCS you HAVE to get away from the idea of directly operating on the registers.
Assuming that CCS has got it right, the compiler SHOULD do almost ALL register operations for you.
By playing with the registers, you're fighting the compiler.
In your recent post you've introduced a whole new list of registers to play with.
I can only assume you're contemplating screwing those up as well.
I'm not the only one telling you this, there are several of us.
You appear to be totally ignoring most of the advice you're being given on this aspect and many others.
You're even arguing with some of the exquisite responses you're getting.
Quote: | Finally what is the solution to my problem? | I stick by my comment also on page 2, you have to work it out for yourself.
That's me done. I give up.
Mike |
|
|
jayanthd
Joined: 06 Dec 2012 Posts: 47 Location: Banned - pirate
|
|
Posted: Sun Mar 24, 2013 9:38 am |
|
|
Ok. I got it working. Here is a screenshot of my project working.
I will soon post the code after fine tuning my project.
http://www.pixhost.org/show/3166/16411281_i2c_working.jpg
http://www.edaboard.com/attachments/88453d1364142505-i2c_w1.jpg
After reading CCS C manual and microchip i2c document I was able to write the code using CCS C i2c library functions and I have tested it both on hardware and Proteus and it is working fine.
Finally I did it within 24 hours.
There is a problem. I tested the working with one slave at a time and it works fine if with single slaves. Both the slaves are working but If I connect both the slaves it just reads the data once and slave 1 and slave 2 hangs. What might be the problem? Is it that i2c bus is not clearing properly after the first read?
http://www.pixhost.org/show/2236/16412948_i2c_hang.jpg |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Mar 24, 2013 3:49 pm |
|
|
jayanthd wrote: | Ok. I got it working. Here is a screenshot of my project working.
I will soon post the code after fine tuning my project.
After reading CCS C manual and microchip i2c document I was able to write the code using CCS C i2c library functions and I have tested it both on hardware and Proteus and it is working fine.
Finally I did it within 24 hours.
There is a problem. I tested the working with one slave at a time and it works fine if with single slaves. Both the slaves are working but If I connect both the slaves it just reads the data once and slave 1 and slave 2 hangs. What might be the problem? Is it that i2c bus is not clearing properly after the first read?
|
Speaks for itself.
Mike |
|
|
jayanthd
Joined: 06 Dec 2012 Posts: 47 Location: Banned - pirate
|
|
Posted: Mon Mar 25, 2013 1:58 am |
|
|
Mike Walne wrote: |
Speaks for itself.
Mike |
What? I said that if I use only one slave at a time it works without problem but if I use both slaves then master reads data from both the slaves and displays correctly but slaves hangs after that or thats what I think because when the master reads the slaves second time it gives data ad 0.0000 for both the slaves. In master I have written code such that it read data changes from previous data then only print the values. In the second read it is getting 0 for both the slaves. What are the causes for such a problem?
What I see in the i2c debugger is NACK is being performed which should be done only at the end of read operations. Why is it happening? I didn't change the code in anyway. If I use the same code with one slave it works fine but not with two slaves. I have 4 i2c_read operations 2 times that is for 8 read operations in total for 2 slaves to read 8 bytes data. I know that i2c_read() does ACK and i2c_read(0) does a NACK. I have used the read operation like below.
read slave 1
i2c_read()
i2c_read()
i2c_read()
i2c_read(0)
read slave 2
2c_read()
i2c_read()
i2c_read()
i2c_read(0)
What am I doing wrong? |
|
|
|
|
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
|