|
|
View previous topic :: View next topic |
Author |
Message |
picer
Joined: 25 Jan 2005 Posts: 28 Location: Taxahoma
|
One more I2C |
Posted: Sat Feb 26, 2005 12:47 pm |
|
|
I know not another one...
I tried to make my routines as simple as i can and go from there, I have a master (819) sending 0x44 to the slave (877a) and the slave just gets the data and prints it to the serial port, simple right?
1. Hold reset on both
2. Release reset on slave and it prints Running...
3. Release reset on master and slave starts recieving address and data and prints them both on the screen as so:
Running...
Address: 02
Data: 43
Address: 02
Data: 43
Address: 02
Data: 43
which is correct.
I can reset the master all day long and the slave still puts on the correct data, now if i hit reset on the slave it never works again till I get both reset. It will just print 02 for address and data.
I'll assume first off I'm doing something stupid and go from there.
Master
Code: |
#include <16F819.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#define EEPROM_SDA PIN_B1
#define EEPROM_SCL PIN_B4
#use i2c(MASTER, SDA=EEPROM_SDA, SCL=EEPROM_SCL)
void main()
{
int i2c_command = 0x43;
output_float(EEPROM_SCL);
output_float(EEPROM_SDA);
while (true)
{
delay_ms(1000);
i2c_start();
i2c_write(0x02);
i2c_write(i2c_command);
i2c_stop();
}
}
|
Slave
Code: |
#include <16F877a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,brgh1ok)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x02, FORCE_HW)
#INT_SSP
void ssp_interupt()
{
byte incoming;
if (i2c_poll())
{
incoming = i2c_read();
if (incoming == 0x02)
{
printf("\n\rAddress: %x\n\r", incoming);
incoming = i2c_read();
printf("\n\rData: %x\n\r", incoming);
}
}
}
void main()
{
byte incoming;
delay_ms(1000);
printf("Running...");
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (true)
{
}
}
|
I've about run out of examples to try, this is about the first one that wants to work. Like I said I've made it as bare bones as I could, maybe too bare bones? But like I've said I've tried every example from here, internet search and CCS examples and this is the first so called success. Can anyone help? Thanks.
compiler PCM 3.186 |
|
|
Ttelmah Guest
|
|
Posted: Sun Feb 27, 2005 3:47 am |
|
|
If the I2C interrupt has occured, there _is_ a byte waiting to be read (don't use 'poll'). Get rid of the printing in the slave routine. The problem here is that if the device is out of sync (which may be the case when the slave has reset), this takes time, and degrades the ability to recover. You have nothing to clear the overflow condition (where a second byte arrives, while you are in the first receive), so the slave will effectively become hung.
Code the slave with something like:
Code: |
#include <16F877a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,brgh1ok)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x02, FORCE_HW)
boolean data_available=false;
int8 data_byte;
#byte SSPSTAT=0x94
#bit DATA=SSPSTAT.5
#INT_SSP
void ssp_interupt()
{
static boolean my_address=false;
//You _must_ read the data register in each routine here
if (DATA) {
//Here I have a data byte
if (my_address) {
//Note that you should /ACK the last byte
data_byte = i2c_read(0);
data_available=true;
}
else {
//here data is for somone else
i2c_read();
data_available=false;
}
}
else {
//Here an address
data_byte=i2c_read();
if (data_byte=0x2) my_address=true;
else my_address=false;
}
}
void main()
{
delay_ms(1000);
printf("Running...");
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (true)
{
if (data_available) {
data_available=false;
printf("\n\rData: %x\n\r", data_byte);
}
}
}
|
In the 'master', the command write, can be coded to check that the slave has acknowledged the byte.
Best Wishes |
|
|
picer
Joined: 25 Jan 2005 Posts: 28 Location: Taxahoma
|
|
Posted: Mon Feb 28, 2005 8:41 am |
|
|
Thanks for the above example, it's still doing the same thing unless I missed something you said. |
|
|
Ttelmah Guest
|
|
Posted: Mon Feb 28, 2005 3:40 pm |
|
|
One key thing, I didn't say. I generally set up the I2C myself (rather than using the CCS routines), since for this to work right, the bottom 'nibble' of SSPCON, must be set to 0110, so that the chip only interrupts on data/address bytes, and not on stop/start. Check what is in this register (with a simulator), and if necessary change these bits.
Best Wishes |
|
|
Guest
|
|
Posted: Wed Mar 02, 2005 9:57 pm |
|
|
Ok, made some very good progress but now am completely lost it seems on how to pass more data through I2C.
I got it to do a pwm output and I'm passing the duty cycle through I2C pretty much using the exact code above except data_byte gets assigned the duty and I'm just doing the pwm in the main loop. I added #byte SSPCON=0x36 and then I2C worked but strangely enough I later removed that and it still works great, go figure. But anyways on to the next, I assume doing the following would work, it does not...
snippit from above, just added data_byte2
Code: |
//Here I have a data byte
if (my_address)
{
//Note that you should /ACK the last byte
data_byte = i2c_read();
data_byte2 = i2c_read();
data_available=true;
//data_available2=true;
}
|
This is how the help files shows to do it, the next byte should be data as well? Master is the same too but added another write
Code: |
i2c_start();
i2c_write((0x02|(BYTE)(address>>1))&0xfe);
i2c_write(0x02);
i2c_command--;
i2c_write(i2c_command);
i2c_write(i2c_command2);
i2c_stop();
|
Again from the help file it shows doing 2 writes. It seems to go haywire if I try this, can only assume the next read is NOT data like I think it is. The
#byte SSPCON=0x36 would have fixed this I assume, does not so I'm still missing something. From the amount of I2C questions here I can assume I'm not the only one getting very confused with I2C. I was extreamly happy geting a byte accross today because something finally worked (I can still make that work just fine) but getting more accross was not very successful?? |
|
|
picer
Joined: 25 Jan 2005 Posts: 28 Location: Taxahoma
|
|
Posted: Thu Mar 03, 2005 8:05 am |
|
|
sspcon is being set properly without adding the sspcon line. It posted my responce as guest |
|
|
picer
Joined: 25 Jan 2005 Posts: 28 Location: Taxahoma
|
|
Posted: Thu Mar 03, 2005 11:13 am |
|
|
And I'm now using 877a as master and 819 as slave since the datasheets seem to indicate the 819 is slave I2C only, maybe that was my original problem with I2C comms so I'm now at the point of trying to make multiple byte sends work as sending one byte works fine. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Mar 03, 2005 1:05 pm |
|
|
picer wrote: | And I'm now using 877a as master and 819 as slave since the datasheets seem to indicate the 819 is slave I2C only, maybe that was my original problem with I2C comms so I'm now at the point of trying to make multiple byte sends work as sending one byte works fine. |
Master can always be done in firmware. |
|
|
|
|
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
|