View previous topic :: View next topic |
Author |
Message |
blak3r
Joined: 11 Jan 2004 Posts: 45
|
I2C Read problem. First read = junk. Second is fine! |
Posted: Sun Apr 04, 2004 7:46 pm |
|
|
PIC: 16F876
i2c device: TEA5768HL, a Phillips FM receiver IC
I'm having some trouble getting the proper response from the phillips IC the first time i read from it. After i complete the first read i print out the values i received and then i try it again. The second time it works properly.
I don't seem to have any problems writing to the device.
Also, this behavior only happens on the first read in the program which gets the initial status of the chip. After that first read all subsequent reads work fine.
Circuit details: i also have an i2c eeprom on the i2c bus which works perfectly.
PULLUPS: are only 1k ohm. I found on the forum looking for an answer to my problem that they should be at least 1.6k. (i used 1k because of the following ccs faq )
Code: |
#define RADIO_I2C_WRITE_ADDR 0xC0
#define RADIO_I2C_READ_ADDR 0xC1
main()
{
init_ext_eeprom();
delay_ms(100);
readRadioSettings();
printRadioSettings(); // <-- prints FF for each of the 5 data bytes
readRadioSettings();
printRadioSettings(); // <-- prints valid data
}
#use i2c (Master, sda = PIN_C4, scl = PIN_C5, SLOW)
void init_ext_eeprom(void)
{
output_float(PIN_C4);
output_float(PIN_C5);
}
void readRadioSettings()
{
i2c_start();
radio.readAck = i2c_write(RADIO_I2C_READ_ADDR);
radio.readDataByte1 = i2c_read(1);
radio.readDataByte2 = i2c_read(1);
radio.readDataByte3 = i2c_read(1);
radio.readDataByte4 = i2c_read(1);
radio.readDataByte5 = i2c_read(1);
//i2c_stop(); // no stop bit for the TEA5768hl on reads
return;
}
|
Is this a problem that could really be caused by pullup resistors or possibly a compiler bug?
Thanks,
~blake _________________ "Everything should be made as simple as possible, but not one bit simpler" -- Albert Einstein
http://www.blakerobertson.com |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 04, 2004 9:49 pm |
|
|
This routine is wrong:
void readRadioSettings()
{
i2c_start();
radio.readAck = i2c_write(RADIO_I2C_READ_ADDR);
radio.readDataByte1 = i2c_read(1);
radio.readDataByte2 = i2c_read(1);
radio.readDataByte3 = i2c_read(1);
radio.readDataByte4 = i2c_read(1);
radio.readDataByte5 = i2c_read(1);
//i2c_stop(); // no stop bit for the TEA5768hl on reads
return;
}
It should be like this, I would think. The data sheet is very poor.
It doesn't give bit diagrams for the i2c transactions. What it does
have, is incomplete. Try this:
Code: | void readRadioSettings()
{
i2c_start();
radio.readAck = i2c_write(RADIO_I2C_READ_ADDR);
radio.readDataByte1 = i2c_read();
radio.readDataByte2 = i2c_read();
radio.readDataByte3 = i2c_read();
radio.readDataByte4 = i2c_read();
radio.readDataByte5 = i2c_read(0); // Note the 0 parameter.
i2c_stop(); // Yes, you need a stop.
} |
Also, you should not let your programs fall off the end of main().
They will hit a Sleep instruction that CCS inserts there. Add a while(1)
statement to prevent this. See below.
main()
{
init_ext_eeprom();
delay_ms(100);
readRadioSettings();
printRadioSettings();
readRadioSettings();
printRadioSettings();
while(1); // Add this line.
}
Additional comments:
1. Normally, you would use pins C4 and C3 for i2c. This gives you
the option to use hardware i2c, if you decide to do that later.
2. Make sure you have NOLVP at the end of your #fuses statement.
(Unless you are using low voltage programming -- but most people
don't). |
|
|
blak3r
Joined: 11 Jan 2004 Posts: 45
|
|
Posted: Mon Apr 05, 2004 12:43 am |
|
|
The Philips datasheet is lacking indeed!
I'll have to check my notes that are at the lab but i originally had the code like you listed below.
I think including the stop bit caused it to read the next data byte incorrectly (the first data byte of the second read). I got to the current version of code based on what seemed to work the best.
Quote: |
(PIC1687x Datasheet)
RC3/SCK/SCL bit3 ST RC3 can also be the synchronous serial clock for both SPIand I2C modes.
RC4/SDI/SDA bit4 ST RC4 can also be the SPI Data In (SPI mode) or data I/O (I2C mode).
RC5/SDO bit5 ST Input/output port pin or Synchronous Serial Port data output.
|
grr! I meant to use hardware spi but apparently i misread the datasheet. The "can also" i think through me off and since RC5 pin says Synchronous so i guess i just glanced over the rest of it assuming it was referring to a clock pin not a serial transfer method.
Thanks for pointing that out! _________________ "Everything should be made as simple as possible, but not one bit simpler" -- Albert Einstein
http://www.blakerobertson.com |
|
|
|