PDA

View Full Version : PIC16F877 and EEPROM FM24C16A



igeorge
- 10th October 2004, 19:58
Hello everybody,
I do not know if it is a hardware problem or software
I need help on solving an I2C problem
I am new to Pics as i am new to Pic Basic Pro (5 days only)
I got from rentron the flash-lab77 kit with pic basic pro and the rest.
I tryed first the the simple example in the sample and did not work. B1 and B2 returned 0 all the time.

DEFINE LOADER_USED 1 ' Always include this when using the boot-loader
DEFINE OSC 20 ' And this too since your board runs at 20MHz
Include "modedefs.bas" ' Include serial modes


SO VAR PORTB.1 ' Define serial output pin
DPIN var PORTC.0 ' I2C data pin
CPIN var PORTC.1 ' I2C clock pin
BA0 var byte
BA1 var byte
BA2 var byte

For BA0 = 0 To 15 ' Loop 16 times
I2CWRITE DPIN,CPIN,$A0,BA0,[BA0] ' Write each location's address to itself
Pause 10 ' Delay 10ms after each write
Next BA0

loop: For BA0 = 0 To 15 step 2 ' Loop 8 times
I2CREAD DPIN,CPIN,$A0,BA0,[BA1,BA2] ' Read 2 locations in a row
Serout SO,16468 ,[#BA1," ",#BA2," "] ' Print 2 locations
Next BA0

Serout SO,16468,[10] ' Print linefeed

Goto loop

My problems are two , related to the i2c commands, if i can get it first working:
1) First one is that i would like to write on the eeprom some decimal
numbers of 4 digits each. Let say A=1234 and B=5678
I would like with one i2cwrite command to put this data in the eeprom.
The next step is to retrieve this data as decimal numbers too , so i can display it on an serial LCD ( i have figured out the display part and it works).
I wrote this, but does not work

a var word
b var word
a=1234
b=5678
I2CWRITE PORTC.0,PORTC.1,$a0,0,[A,B]
I2Cread PORTC.0,PORTC.1,$a0,0,[A,B]
It will read only one byte from the word.

2) My second problem is to write some ASCII text on the eeprom and be able to read it back . lets say i want to write
"this is text one on eeprom" , then, i would like to be able to read it back so i can display it on the lcd.

I would appreciate if any of you can help me, and a small piece of code as an example it will be a jackpot.
Just keep in mind that i am a complete newbee and what it is obvious for you it might be a mistery for me.
Thank you very much for reading my postl and i hope to hear soon from you
Ion George

mister_e
- 10th October 2004, 21:00
Hi isgeorge,

have a look at this Melanie's thread :

http://www.picbasic.co.uk/forum/showthread.php?s=&threadid=587

hope this help. Case else let us know

regards

igeorge
- 10th October 2004, 21:08
Thanks Mister_e for guidance.
I did read the topic on addressing i2c but i am still in the same dark. Reads, returns only zero. I am suprised that i am not able to make the sample code from mellab working !, not speaking about writing my own code.
Ion

mister_e
- 10th October 2004, 21:18
does only

SEROUT SO,16468,["HELLO",10]

works alone ???

if not try

SEROUT SO,4,["HELLO",10] ;2400 baud inverted

Do you use MicroCode studio to get your data from RS232? If yes, Be sure of the selected BaudRate.

In case of SEROUT SO,4,["HELLO",10] don't work, try
SEROUT SO,0,["HELLO",10] ;2400 true


regards

mister_e
- 10th October 2004, 21:28
"I wrote this, but does not work

a var word
b var word
a=1234
b=5678
I2CWRITE PORTC.0,PORTC.1,$a0,0,[A,B]
I2Cread PORTC.0,PORTC.1,$a0,0,[A,B]
It will read only one byte from the word.

Variable must be define as Byte

try this

cont VAR BYTE
addr VAR WORD
cont = %10100000
addr=1

I2CWRITE PORTC.0,PORTC.1,cont,addr,[A]
I2CWRITE PORTC.0,PORTC.1,cont,addr+1,[B]
PAUSE 10
I2CREAD PORTC.0,PORTC.1,cont,addr,[A,B]

then send A, B serial

one other things. Do you put pull up resistor to the SDA and SCLK pin 5&6 on your EEPROM??? If not use about 4.7K. They must be installed...

let me know

igeorge
- 10th October 2004, 22:18
The answer to the previous post is that serial works .
I did try just to send some strings and i got them on the display.
For the i2c, it does not send it to the lcd as decimal, let say 1234 or 5678, it will just send one byte of each in the hex fromat.
I do not know if the problem is with writing just one byte or reading one byte from the whole word. for 1234 it will display just D2 . it looks it will not read the whole 4D2 , nor converted to decimal on the display
Ion

mister_e
- 10th October 2004, 23:26
O.k. the reason is because 24c16 is a 8bits format. it's mean that you cannot stored an 16bit value in a memory allocatio. the way to acheive to it is to separate your 16 word in 2 8 bit byte

so if you want to store 1234 you must send


VAR A BYTE
VAR B BYTE

A=12
B=34

I2CWRITE PORTC.0,PORTC.1,cont,addr,[A,B]
PAUSE 10
I2CREAD PORTC.0,PORTC.1,cont,addr,[A,B]
SEROUT SO,16468,[HEX A, HEX B,10]

this is suppose to work. Case not let me know i'll work on it myself and try in real world.

regards

igeorge
- 11th October 2004, 00:47
Thank you Mister_e
This put some light on the project. I will try it.
The only problem with that is that i have to make to many variable, double then normal i do . If it is no other way, i have to leave with that
Ion

mister_e
- 11th October 2004, 03:37
O.k
simply use WORD to get your result and then use 2 byte to convert and send them to eeprom.

By example (MSB, LSB will be value to send/receive from eeprom)



RESULT VAR WORD
MSB VAR BYTE
LSB VAR BYTE
ToConvert VAR WORD
addr VAR BYTE
cont VAR BYTE

addr=0
cont=$a0

;convert WORD size to 2 BYTEs before send to eeprom
RESULT=1234
LSB=RESULT.byte0
MSB=RESULT.byte1
I2CWRITE PORTC.0,PORTC.1,cont,addr,[MSB,LSB]
PAUSE 10

;now convert from eeprom to WORD size and send it
I2CREAD PORTC.0,PORTC.1,cont,addr,[MSB,LSB]
ToConvert.byte0=LSB
ToConvert.byte1=MSB
SEROUT SO,16468,[#ToConvert,10]

i didn't test it but it suppose to work.

let me know

Hockung
- 4th December 2004, 04:27
Hello, i am facing the same problem when i try to store data to the Eeprom. i only get back 0 when i read from the Eeprom. I had done the pull up resistor for Sda and Scl but the result still the same. The data that i try to store is from 0-255.


DEFINE OSC 20 ' 20MHz crystal
DEFINE HSER_RCSTA 90h ' enable serial port and
DEFINE HSER_TXSTA 24h ' enable transmit register
DEFINE HSER_BAUD 19200 ' 19200 baud rate
DEFINE HSER_SPBRG 64 ' 19200 baud rate
DEFINE HSER_CLROERR 1 ' automatically close
DEFINE I2C_SLOW 1

'************************************************* *******************
'Declaration of I/O pins and Variables
'************************************************* *******************

scl VAR PORTC.3 ' I2C clock pin
sda VAR PORTC.4 ' I2C data pin
w VAR WORD
a VAR BYTE
counter VAR BYTE
char VAR BYTE ' Storage for serial character
char2 VAR BYTE ' Storage for serial character
char3 VAR BYTE
add VAR BYTE
value VAR BYTE[80]
value2 VAR BYTE[80]

'************************************************* *******************
a = 0
counter = 0
add = 1block1 CON %10100000
store3: HSerin [STR value\60]
Low PORTA.5
char = value[a]
LCDOut $fe, 1
LCDOut #char
I2CWrite PORTC.4,PORTC.3,$a1,add,[char]
Pause 40
IF a == 60 Then
GoTo baca
Else
a = a + 1
add = add + 1
GoTo store3
EndIF
'Pause 10000

High PORTB.1
add = 1
baca: LCDOut "Read cycle"
Pause 3000
I2CRead PORTC.4,PORTC.3,$a0,add,[char2]
Pause 3000
LCDOut $fe, 1
LCDOut #char
Pause 2000
IF a == 60 Then
GoTo dump
Else
a = a + 1
add = add + 1
GoTo baca
EndIF

Above is part of my program that i had wrote. I can't find out what is the problem. Can some one help me to correct it?

mister_e
- 4th December 2004, 21:00
change i2cread and i2cwrite line. control word must be a variable, not a simple value....

cont=$a0
I2CWrite PORTC.4,PORTC.3,cont,add,[char]

be sure you have around 4.7K pull up, write/protect pin to ground too.

be also sure SCL and SDA are not reverted ...happen sometimes

mister_e
- 4th December 2004, 21:12
also i see you don't use the same control word to read/write to chip...

Hockung
- 13th December 2004, 11:22
This is the program which i wrote to communicate with CMUcam. I faced some prblem regarding storing data to EEprom. The problem that i faced was the Pic took a long time to store the data to the Eeprom. It take about 5s to store about 800 bytes. I suspect delay happened when i store data to the array which is created then only store into the Eeprom. I used this way to ensure no data is lost during transfer using USArt. Did my program got problem or not which cause the Pic to so slow?

DEFINE OSC 20 ' 20MHz crystal
DEFINE HSER_RCSTA 90h ' enable serial port
DEFINE HSER_TXSTA 24h ' enable transmit register
DEFINE HSER_BAUD 115200 ' 19200 baud rate
DEFINE HSER_SPBRG 64 ' 19200 baud rate
DEFINE HSER_CLROERR 1 ' automatically close
DEFINE I2C_SLOW 1 ' standard
DEFINE LOADER_USED 1

'************************************************* *******************
'Declaration of I/O pins and Variables
'************************************************* *******************

w VAR WORD
a VAR WORD
b VAR WORD
c VAR BYTE

counter VAR BYTE
char VAR BYTE ' Storage for serial character
char2 VAR BYTE ' Storage for serial character
add VAR BYTE
value VAR BYTE[96]
'value2 VAR BYTE[80]

SCL VAR PORTC.3 ' Clock pin
SDA VAR PORTC.4 ' Data pin
CONT VAR BYTE
col VAR BYTE
row VAR BYTE

B0 VAR WORD ' Address
B1 VAR BYTE ' Data 1
B2 VAR BYTE ' Data 2
B3 VAR BYTE

'************************************************* *******************

'Clearing all register

'************************************************* *******************

Clear ' clear all register

'************************************************* *******************

a = 0 ' Starting address for Eeprom
col = 30
row = 19 '
CONT = $A0

'************************************************* *******************


High PORTB.0
Pause 1000 ' Wait for LCD to startup
Low PORTB.0


LCDOut $fe, 1 ' Clear LCD screen
High PORTB.0
LCDOut "start" ' Display Hello
Pause 1000 ' Wait 3 second

Low PORTB.0
Pause 1000
High PORTB.0

LCDOut $fe, 1 ' Clear LCD screen
LCDOut "CMU"
Pause 1000 ' Wait 2 second
Low PORTB.0



'************************************************* *******************
loop: HSerin 1, reset, [char] ' Get a char from serial port
Pause 2000
LCDOut $fe, 1 ' Clear LCD screen
LCDOut char ' Send char to display
High PORTB.0
Pause 1000
Low PORTB.0

IF Char = "A" Then pm

reset: HSerout ["rs",13] ' reset CMUcam
High PORTB.1
Pause 1000
Low PORTB.1
GoTo loop

pm: HSerout ["pm 1",13]
Pause 1000
HSerin [char2]
IF char2 ="A" Then
GoTo set
Else
GoTo pm
EndIF

set: Low PORTE.0
High PORTA.5
HSerout ["CR 17 10 18 32 ",13] ' set CMU to YCrCb mode and 4 fps
Pause 1000
Low PORTA.5
GoSub check ' goto check ACK signal

setw: High PORTA.5
HSerout ["SW 11 ", DEC row," 30 ", DEC row,13]
Pause 500
Low PORTB.5
GoTo dump

check: HSerin 1, out, [char2]
LCDOut $fe, 1 ' Clear LCD screen
LCDOut char2 ' Send char to display
Pause 1000

out: IF char2="A" Then
GoTo setw
Else
GoTo set
EndIF

Return

dump: High PORTA.5
HSerout ["DF",13] ' ask camera to dump frame

'************************************************* *******************
'Store image data at external serial EEPROM
'************************************************* *******************


store3: HSerin [SKIP 7,STR value\80] 'Skip the first 7 charactor then store data to value
Low PORTA.5
c = 1
b = a + 20
For B0 = a TO b ' Loop 60 times
B1 = value[c] ' B1 is data for EEPROM
I2CWrite SDA,SCL,CONT,B0,[B1] ' Write each location
Pause 50 ' Delay 10ms after each write
c = c + 4
Next B0



loop2: For B0 = a TO b STEP 3 ' Loop 8 times
I2CRead SDA,SCL,CONT,B0,[B1,B2,B3] ' Read 3 locations in a row
LCDOut $fe,1,#B0,": ",#B1," ",#B2," ",#B3," " ' Display 2 locations
Pause 2000
Next B0

GoTo RSW

RSW: For row = 21 TO 40 ' Reset window
HSerout ["SW 11 ", DEC row," 30 ", DEC row,13]
Pause 20
HSerout ["DF",13]

HSerin [ SKIP 7, STR value\80] 'Skip the first 7 charactor then store data to value
c = 1
a = a + 20
b = a + 20
For B0 = a TO b ' Loop 60 times
B1 = value[c] ' B1 is data for EEPROM
I2CWrite SDA,SCL,CONT, B0,[B1] ' Write each location
Pause 50
c = c + 4 ' Delay 10ms after each write
Next B0

Next row

show: a = 80
b = 160
For B0 = a TO b STEP 3 ' Loop 8 times
I2CRead SDA,SCL,CONT,B0,[B1,B2,B3] ' Read 3 locations in a row
LCDOut $fe,1,#B0,": ",#B1," ",#B2," ",#B3," " ' Display 2 locations
Pause 2000
Next B0

GoTo loop2
'************************************************* *******************

End

mister_e
- 14th December 2004, 01:21
After a fast code reading, two things slow you I2C writing...

DEFINE I2C_SLOW 1

and

PAUSE 50 after I2CWRITE

If your EEPROM support high speed, remove I2C_SLOW define and decrease PAUSE 50 to 10 or 15... should work faster now