View previous topic :: View next topic |
Author |
Message |
jeferson_ev
Joined: 07 Jan 2009 Posts: 3
|
Problem - i2c_read() always returning 0? |
Posted: Thu Jan 08, 2009 10:14 pm |
|
|
Hi.
I'm starting to use I2C interface to communicate with external periphals. My first test was with an EEPROM (M24256 from ST Microelectronics).
I'm trying to make a "byte write" and a "random address read". Writing is OK, but when I try to read a memory address the value returned by "i2c_read()" instruction is always 0.
I used hyperterminal to show the readed values (image below)
->I'm using CCS v4.084.
Code: |
//----------------------------------------------------------------------------
//--------------------------------I2C BUS-------------------------------------
//----------------------------------------------------------------------------
#INCLUDE <30F4011.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT_PLL16 //XT Crystal Oscillator mode with 16X PLL
#FUSES PR //Primary Oscillator
#FUSES NOCKSFSM //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES PUT64 //Power On Reset Timer value 64ms
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOWRT //Program memory not write protected
#USE DELAY(Clock=64M) //4Mhz Crystal with 16X PLL (Is that right?)
#USE RS232(UART2,Baud=57600,Parity=N,Bits=8)
#USE I2C(Master,Slow,SDA=PIN_F2,SCL=PIN_F3,FORCE_HW)
//----------------------------------------------------------------------------
//--------------------DEFINES,VARIABLES AND FUNCIOTNS-------------------------
//----------------------------------------------------------------------------
#DEFINE LED PIN_D3
#DEFINE EEPROM_WRITE_CMD 0xA0 //= 1010|000|0 in binary
#DEFINE EEPROM_READ_CMD 0xA1 //= 1010|000|1 in binary
void led_flash();
int1 i2c_ack;
long value;
//----------------------------------------------------------------------------
//-------------------------------FIRMWARE-------------------------------------
//----------------------------------------------------------------------------
void main()
{
SET_TRIS_B(0b0000000000000000);
SET_TRIS_C(0b0000000000000000);
SET_TRIS_D(0b0000000000000000);
SET_TRIS_E(0b0000000000000000);
SET_TRIS_F(0b0000000000010000);
SETUP_ADC(ADC_OFF);
SETUP_WDT(WDT_OFF);
DISABLE_INTERRUPTS(INT_RDA2);
DISABLE_INTERRUPTS(INT_TBE2);
DISABLE_INTERRUPTS(INT_TIMER1);
DISABLE_INTERRUPTS(INT_TIMER2);
DISABLE_INTERRUPTS(INT_TIMER3);
DISABLE_INTERRUPTS(INT_TIMER4);
DISABLE_INTERRUPTS(INT_TIMER5);
DISABLE_INTERRUPTS(INTR_GLOBAL);
DISABLE_INTERRUPTS(INTR_NORMAL);
delay_ms(300);
//----------------------------------------------------------------------------
//----------------------Writes 123d on memory adress 5------------------------
//----------------------------------------------------------------------------
printf("EEPROM Write");
i2c_start(); //I2C Start
i2c_ack=i2c_write(EEPROM_WRITE_CMD); //Write CMD = 1010|000|0 in binary
switch(i2c_ack)
{
case 0: {printf("\r\nACK on i2c_write(EPROM_WRITE_CMD)"); break;}
case 1: {printf("\r\nNO_ACK i2c_write(EPROM_WRITE_CMD)"); break;}
}
i2c_ack=i2c_write(0x00); //Memory Adress High
switch(i2c_ack)
{
case 0: {printf("\r\nACK on i2c_write(0x00)"); break;}
case 1: {printf("\r\nNO_ACK on i2c_write(0x00)"); break;}
}
i2c_ack=i2c_write(0x05); //Memory Adress Low
switch(i2c_ack)
{
case 0: {printf("\r\nACK on i2c_write(0x05)"); break;}
case 1: {printf("\r\nNO_ACK on i2c_write(0x05)"); break;}
}
i2c_ack=i2c_write(123); //Writes 123d on memory adress 5
switch(i2c_ack)
{
case 0: {printf("\r\nACK on i2c_write(123)"); break;}
case 1: {printf("\r\nNO_ACK i2c_write(123)"); break;}
}
i2c_stop(); //I2C Stop
delay_ms(300);
//----------------------------------------------------------------------------
//------------------Reads the content of memory adress 5----------------------
//----------------------------------------------------------------------------
printf("\r\nEEPROM Read");
i2c_start(); //I2C Start
i2c_ack=i2c_write(EEPROM_WRITE_CMD); //Write CMD = 1010|000|0 in binary
switch(i2c_ack)
{
case 0: {printf("\r\nACK on i2c_write(EEPROM_WRITE_CMD)"); break;}
case 1: {printf("\r\nNO_ACK on i2c_write(EEPROM_WRITE_CMD)"); break;}
}
i2c_ack=i2c_write(0x00); //Memory Adress High
switch(i2c_ack)
{
case 0: {printf("\r\nACK on i2c_write(0x00)"); break;}
case 1: {printf("\r\nNO_ACK on i2c_write(0x00)"); break;}
}
i2c_ack=i2c_write(0x05); //Memory Adress Low
switch(i2c_ack)
{
case 0: {printf("\r\nACK on i2c_write(0x05)"); break;}
case 1: {printf("\r\nNO_ACK on i2c_write(0x05)"); break;}
}
i2c_start(); // Second I2C Start
i2c_ack=i2c_write(EEPROM_READ_CMD); //Read CMD = 1010|000|1 in binary
switch(i2c_ack)
{
case 0: {printf("\r\nACK on i2c_write(EEPROM_READ_CMD)"); break;}
case 1: {printf("\r\nNO_ACK on i2c_write(EEPROM_READ_CMD)"); break;}
}
while(I2C_POLL()==FALSE) //waits for I2C data reception
{
}
value=i2c_read(); //value = adress 5 content
i2c_stop(); //I2C Stop
printf("\r\n");
printf("VALUE = %lu", value); //prints the content of value
while(TRUE)
{
led_flash();
}
}
void led_flash()
{
output_toggle(LED);
delay_ms(200);
}
|
-------------------------------------------------------------------------
Code showed on Hyperterminal:
http://img151.imageshack.us/my.php?image=eepromuc1.png
The EEPROM acknowledges the writed bytes but value=0 always.
Putting A0 (EEPROM physical address input) to VCC, the EEPROM returns NOACK, this means that the EEPROM is being addressed correctly, but i2c_read() is always returning 0 to the variable value.
-------------------------------------------------------------------------
M24256 EEPROM datasheet shows:
http://img368.imageshack.us/my.php?image=m24256lk5.png
My code does this sequence but I don't know why it isn't working correctly
-------------------------------------------------------------------------
Circuit used:
http://www.speedyshare.com/616555732.html
Pullups resistors on SCL and SDA = 2.2K
PIC used = dsPIC30F4011
M24256 EEPROM Datasheet:
http://www.st.com/stonline/products/literature/ds/6757/m24256-bw.pdf
Somebody knows whats wrong?
Help Plz ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 08, 2009 11:08 pm |
|
|
Your code is overly complicated, which is preventing you from seeing
certain things. Look at the read_ext_eeprom() function in the CCS
driver. What parameter is used in the last i2c_read() operation ?
Quote: | c:\program files\picc\drivers\24256.c |
Look at page 19 in the M24256 data sheet, at this figure:
Quote: | Figure 11. Read mode sequences |
What operation is done on the last i2c read, when it gets "data out" ?
Look in the CCS manual at the i2c_read() function to see what the
parameter is used for in that function.
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf |
|
![](templates/subSilver/images/spacer.gif) |
n-squared
Joined: 03 Oct 2006 Posts: 99
|
|
Posted: Thu Jan 08, 2009 11:46 pm |
|
|
It looks to me like the problem is with the polling loop while reading data from EEPROM.
Try to test the code without:
Code: |
while(I2C_POLL()==FALSE) //waits for I2C data reception
{
}
|
_________________ Every solution has a problem. |
|
![](templates/subSilver/images/spacer.gif) |
jeferson_ev
Joined: 07 Jan 2009 Posts: 3
|
|
Posted: Fri Jan 09, 2009 2:14 pm |
|
|
n-squared wrote: | It looks to me like the problem is with the polling loop while reading data from EEPROM.
Try to test the code without:
Code: |
while(I2C_POLL()==FALSE) //waits for I2C data reception
{
}
|
|
same result :(
hey PCM Programmer:
I've tryed with i2c_read(0) (without data in read ack, the datasheet M24256 shows this), but the value = 0 persists :( |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jan 10, 2009 7:30 pm |
|
|
1. Your schematic doesn't have capacitors on the crystal.
Look at the schematic on page 106 of the dsPICDEM 2 Development
Board User’s Guide:
http://ww1.microchip.com/downloads/en/DeviceDoc/dsPICDEM%202%20Users%20Guide%20DS-51558A.pdf
It shows 22 pf capacitors on either side of the external crystal.
2. Your posted code is too complicated. I would start by using software
i2c instead of hardware i2c. It's possible that CCS doesn't have the
hardware i2c code working. Also, I would get rid of all the printf and ack
stuff and simply try to make it work.
3. The hardware i2c pins on this PIC are also the pins used by the ICD
debugger (PGC and PGD). If you have an ICD debugger connected to
those pins, it may not work. I'd suggest using software i2c on different
pins than F2 and F3.
Here's an example of stripped down code. It doesn't attempt to do ack-
polling. It just does a delay after the write operation. It uses software
i2c.
Code: | #use i2c(Master, SDA=PIN_F2, SCL=PIN_F3 )
#DEFINE LED PIN_D3
void led_flash();
//==================================
void main()
{
int8 value;
printf("Write\n\r");
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_write(0x00);
i2c_write(0x55);
i2c_stop();
delay_ms(5); // Do this for now (instead of ack-polling).
printf("Read\n\r");
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_write(0x00);
i2c_start(); // Re-start
i2c_write(0xA1);
value = i2c_read(0);
i2c_stop();
printf("Value = %X \n\r", value);
while(TRUE)
{
led_flash();
}
}
//====================
void led_flash()
{
output_toggle(LED);
delay_ms(200);
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
jeferson_ev
Joined: 07 Jan 2009 Posts: 3
|
OK |
Posted: Mon Jan 12, 2009 4:55 pm |
|
|
PCM Programmer:
Your code works fine.
I've tried the code in a PIC18F4455 and it worked.
I've also tried on my dsPIC30F4011 and it doesnt work. (I've used my dspic30f4011 on many school projects and I think some I/O pins are damaged, like the pins used by I2C SCL and SDA, maybe)
Big thanks for you PCM programmer and who helped.
![Cool](images/smiles/icon_cool.gif) |
|
![](templates/subSilver/images/spacer.gif) |
|