1 Attachment(s)
16F690 and 24LC16B memory - can't WRITE 8 different bytes in a row
Hi there,
I'm having trouble writing 8 bytes to a 24LC16B memory chip.
In fact, I can write 8 consecutive bytes but it seems only the last byte I want to program is written to all 8 positions.
Even after reading the DS many times knowing there is something particular when writing less than 16 bytes (...don't still understand everything for sure :D), I can't see what am I missing.
Attachment 8979
Any clue?
Code:
'======= FUSES ====================================================================================
' PIC 16F690 Fuses (MPASM)
' Internal oscillator
@ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_INTRC_OSC_NOCLKOUT &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
@ ERRORLEVEL -306
'======= REGISTERS =================================================================================
' Registers 76543210
OPTION_REG = %10000000 ' Pull-Ups disabled
OSCCON = %01110000 ' Internal oscillator
ANSEL = %00000000 ' analog inputs Channels 0 to 7
ANSELH = %00000000 ' analog inputs Channels 8 to 11
WPUA = %00000000 ' weak pull-ups
WPUB = %00000000 ' weak pull-ups
ADCON0 = %00000000 ' Select the VP6 channel as ADC input bits5:2 (xx1101xx)
ADCON1 = %00000000 ' Set FRC
VRCON = %00000000 ' VP6 reference
CM1CON0 = %00000000 ' Comparator1 Module
CM2CON0 = %00000000 ' Comparator2 Module
TRISA = %00000000 ' Input/Output (0 to 5)
PORTA = %00000100 ' High/Low (0 to 5)
TRISB = %00000000 ' Input/Output (4 to 7)
PORTB = %00000000 ' High/Low (4 to 7)
TRISC = %00000000 ' Input/Output (0 to 7)
PORTC = %01000000 ' High/Low (0 to 7)
'======= DEFINES ==================================================================================
DEFINE OSC 8
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE NO_CLRWDT 1 ' Don't waste cycles clearing WDT
'======= VARIABLES ================================================================================
Ser_Out VAR PORTA.2 ' Serial Out
EeWP VAR PORTC.3 ' memory Write Protect
SCL VAR PORTC.6 ' i2c Clock pin [6]
SDA VAR PORTC.7 ' i2c Data pin [5]
Cntr VAR BYTE ' just a counter
Ser_Mode VAR word ' serial com baudrate
Mem_Loc var BYTE ' holds the user's code memory place (000..255)
Temp VAR WORD ' for WORD sized calculation
EeVal VAR BYTE(8) ' array that holds the numbers in the Eeprom
EeCtrl var BYTE ' 4 control bits + 3 memory block selector bits
EeAddress var BYTE ' 24LC16B address (0..255)
EeBlock var BYTE ' holds memory block number (0..7)
'======= INITIALIZE ===============================================================================
Cntr = 0
Ser_Mode = 84 ' 9600bps
Mem_loc = 0
Temp = 0
EeCtrl = 0
EeAddress = 0
EeBlock = 0
For Cntr = 0 to 7
EeVal(Cntr) = Cntr ' initialize EeVal
NEXT
HIGH Ser_Out ' avoid serial data garbage @ startup
'======= TEST =====================================================================================
Mem_loc = 45 ' put here an address between 0..255 to write the data to
'======= PROGRAM ==================================================================================
MAIN:
' Calculate control byte
Temp = Mem_loc * 8 ' 24LC16B's starting memory position
EeBlock = Temp / 256 ' 24LC16B's 0..7 memory block number
EeAddress = Temp // 256 ' 24LC16B's 0..255 memory position
' Get the control byte according to block [ 0..2047] [0..255]
IF Eeblock = 0 THEN EeCtrl = $A0 ' 0..255 0..31
IF Eeblock = 1 THEN EeCtrl = $A2 ' 256..511 32..63
IF Eeblock = 2 THEN EeCtrl = $A4 ' 512..767 64..95
IF Eeblock = 3 THEN EeCtrl = $A6 ' 768..1023 96..127
IF Eeblock = 4 THEN EeCtrl = $A8 ' 1024..1279 128..159
IF Eeblock = 5 THEN EeCtrl = $AA ' 1280..1535 160..191
IF Eeblock = 6 THEN EeCtrl = $AC ' 1536..1791 192..223
IF Eeblock = 7 THEN EeCtrl = $AE ' 1792..2047 224..255
' Show the input I'm using for this test
SEROUT2 Ser_Out, Ser_Mode,["Mem_Loc : ",DEC Mem_Loc,10,"EeBlock : ",_
DEC3 EeBlock,10,"EeAddress: ",DEC3 EeAddress,10,"CTRL : ",BIN EeCtrl,13,10]
' VARIANT 1 - WRITE 8 same bytes to memory = works but...
EeWP = 0
PAUSE 10
For Cntr = 0 to 7
i2cwrite SDA,SCL,EeCtrl,EeAddress,[33]
PAUSE 10
NEXT Cntr
EeWP = 1
'' VARIANT 2 - WRITE 8 different bytes to memory = not working
'EeWP = 0 ' Unprotect memory
'PAUSE 10
'For Cntr = 0 to 7
' i2cwrite SDA,SCL,EeCtrl,EeAddress,[Cntr]
' PAUSE 10
'NEXT Cntr
'EeWP = 1
'' VARIANT 3 - WRITE 8 different bytes to memory = not working
'EeWP = 0
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[EeVal(0),EeVal(1),EeVal(2),EeVal(3),_
' EeVal(4),EeVal(5),EeVal(6),EeVal(7)]
'EeWP = 1
'' VARIANT 4 - WRITE 8 different bytes to memory = not working
'EeWP = 0 ' Unprotect memory
'PAUSE 10
'For Cntr = 0 to 7
' i2cwrite SDA,SCL,EeCtrl,EeAddress,[EeVal(Cntr)]
' PAUSE 10
'NEXT Cntr
'EeWP = 1
'' VARIANT 5 - WRITE 8 different bytes to memory = not working
'EeWP = 0
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[1]
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[2]
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[3]
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[4]
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[5]
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[6]
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[7]
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[8]
'PAUSE 10
'EeWP = 1
' READ 8 bytes from memory
For Cntr = 0 to 7
i2cread SDA,SCL,EeCtrl,EeAddress,[EeVal(Cntr)]
NEXT Cntr
' display what's in the memory chip
SEROUT2 Ser_Out, Ser_Mode,[DEC3 EeVal(0)," ",DEC3 EeVal(1)," ",DEC3 EeVal(2)," ",_
DEC3 EeVal(3)," ",DEC3 EeVal(4)," ",DEC3 EeVal(5)," ",DEC3 EeVal(6)," ",DEC3 EeVal(7),13,10,10]
end
Re: 16F690 and 24LC16B memory - can't WRITE 8 different bytes in a row
try
Code:
' VARIANT 5 - WRITE 8 different bytes to memory
EeWP = 0
PAUSE 10
i2cwrite SDA,SCL,EeCtrl,EeAddress,[1]
EeAddress=EeAddress+1
PAUSE 10
i2cwrite SDA,SCL,EeCtrl,EeAddress,[2]
EeAddress=EeAddress+1
PAUSE 10
i2cwrite SDA,SCL,EeCtrl,EeAddress,[3]
EeAddress=EeAddress+1
PAUSE 10
i2cwrite SDA,SCL,EeCtrl,EeAddress,[4]
EeAddress=EeAddress+1
PAUSE 10
i2cwrite SDA,SCL,EeCtrl,EeAddress,[5]
EeAddress=EeAddress+1
PAUSE 10
i2cwrite SDA,SCL,EeCtrl,EeAddress,[6]
EeAddress=EeAddress+1
PAUSE 10
i2cwrite SDA,SCL,EeCtrl,EeAddress,[7]
EeAddress=EeAddress+1
PAUSE 10
i2cwrite SDA,SCL,EeCtrl,EeAddress,[8]
PAUSE 10
EeWP = 1
or just
i2cwrite SDA,SCL,EeCtrl,EeAddress,[1,2,3................] ;within block boundary
4 Attachment(s)
Re: 16F690 and 24LC16B memory - can't WRITE 8 different bytes in a row
Thanks Richard,
I already corrected the address incrementing and also forgot to mention I already tried the ..[1,2,3,..] variant too.
All without any success... :confused:
See the results in two different memory locations (45 and 0)...
>>> Variant 5
Attachment 8981
Attachment 8983
>>> Variant 6
Attachment 8982
Attachment 8984
Code:
'======= FUSES ====================================================================================
' PIC 16F690 Fuses (MPASM)
' Internal oscillator
@ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_INTRC_OSC_NOCLKOUT &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
@ ERRORLEVEL -306
'======= REGISTERS =================================================================================
' Registers 76543210
OPTION_REG = %10000000 ' Pull-Ups disabled
OSCCON = %01110000 ' Internal oscillator
ANSEL = %00000000 ' analog inputs Channels 0 to 7
ANSELH = %00000000 ' analog inputs Channels 8 to 11
WPUA = %00000000 ' weak pull-ups
WPUB = %00000000 ' weak pull-ups
ADCON0 = %00000000 ' Select the VP6 channel as ADC input bits5:2 (xx1101xx)
ADCON1 = %00000000 ' Set FRC
VRCON = %00000000 ' VP6 reference
CM1CON0 = %00000000 ' Comparator1 Module
CM2CON0 = %00000000 ' Comparator2 Module
TRISA = %00000000 ' Input/Output (0 to 5)
PORTA = %00000100 ' High/Low (0 to 5)
TRISB = %00000000 ' Input/Output (4 to 7)
PORTB = %00000000 ' High/Low (4 to 7)
TRISC = %00000000 ' Input/Output (0 to 7)
PORTC = %01000000 ' High/Low (0 to 7)
'======= DEFINES ==================================================================================
DEFINE OSC 8
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE NO_CLRWDT 1 ' Don't waste cycles clearing WDT
'======= VARIABLES ================================================================================
Ser_Out VAR PORTA.2 ' Serial Out
EeWP VAR PORTC.3 ' memory Write Protect
SCL VAR PORTC.6 ' i2c Clock pin [6]
SDA VAR PORTC.7 ' i2c Data pin [5]
Cntr VAR BYTE ' just a counter
Ser_Mode VAR word ' serial com baudrate
Mem_Loc var BYTE ' holds the user's code memory place (000..255)
Temp VAR WORD ' for WORD sized calculation
EeVal VAR BYTE(8) ' array that holds the numbers in the Eeprom
EeCtrl var BYTE ' 4 control bits + 3 memory block selector bits
EeAddress var BYTE ' 24LC16B address (0..255)
EeBlock var BYTE ' holds memory block number (0..7)
'======= INITIALIZE ===============================================================================
Cntr = 0
Ser_Mode = 84 ' 9600bps
Mem_loc = 0
Temp = 0
EeCtrl = 0
EeAddress = 0
EeBlock = 0
For Cntr = 0 to 7
EeVal(Cntr) = Cntr ' initialize EeVal
NEXT
HIGH Ser_Out ' avoid serial data garbage @ startup
'======= TEST =====================================================================================
Mem_loc = 45 ' put here an address between 0..255 to write the data to
'======= PROGRAM ==================================================================================
MAIN:
' Calculate control byte
Temp = Mem_loc * 8 ' 24LC16B's starting memory position
EeBlock = Temp / 256 ' 24LC16B's 0..7 memory block number
EeAddress = Temp // 256 ' 24LC16B's 0..255 memory position
' Get the control byte according to block [ 0..2047] [0..255]
IF Eeblock = 0 THEN EeCtrl = $A0 ' 0..255 0..31
IF Eeblock = 1 THEN EeCtrl = $A2 ' 256..511 32..63
IF Eeblock = 2 THEN EeCtrl = $A4 ' 512..767 64..95
IF Eeblock = 3 THEN EeCtrl = $A6 ' 768..1023 96..127
IF Eeblock = 4 THEN EeCtrl = $A8 ' 1024..1279 128..159
IF Eeblock = 5 THEN EeCtrl = $AA ' 1280..1535 160..191
IF Eeblock = 6 THEN EeCtrl = $AC ' 1536..1791 192..223
IF Eeblock = 7 THEN EeCtrl = $AE ' 1792..2047 224..255
' Show the input I'm using for this test
SEROUT2 Ser_Out, Ser_Mode,["Mem_Loc : ",DEC Mem_Loc,10,"EeBlock : ",_
DEC3 EeBlock,10,"EeAddress: ",DEC3 EeAddress,10,"CTRL : ",BIN EeCtrl,13,10]
' VARIANT 1 - WRITE 8 same bytes to memory = works
'EeWP = 0
'PAUSE 10
'For Cntr = 0 to 7
' i2cwrite SDA,SCL,EeCtrl,EeAddress,[33]
' PAUSE 10
'NEXT Cntr
'EeWP = 1
'' VARIANT 2 - WRITE 8 different bytes to memory = not working
'EeWP = 0 ' Unprotect memory
'PAUSE 10
'For Cntr = 0 to 7
' i2cwrite SDA,SCL,EeCtrl,EeAddress,[Cntr]
' PAUSE 10
'NEXT Cntr
'EeWP = 1
'' VARIANT 3 - WRITE 8 different bytes to memory = not working
'EeWP = 0
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[EeVal(0),EeVal(1),EeVal(2),EeVal(3),_
' EeVal(4),EeVal(5),EeVal(6),EeVal(7)]
'EeWP = 1
'' VARIANT 4 - WRITE 8 different bytes to memory = not working
'EeWP = 0 ' Unprotect memory
'PAUSE 10
'For Cntr = 0 to 7
' i2cwrite SDA,SCL,EeCtrl,EeAddress,[EeVal(Cntr)]
' PAUSE 10
'NEXT Cntr
'EeWP = 1
'' VARIANT 5 - WRITE 8 different bytes to memory = not working
'EeWP = 0
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[1]
'EeAddress=EeAddress+1
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[2]
'EeAddress=EeAddress+1
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[3]
'EeAddress=EeAddress+1
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[4]
'EeAddress=EeAddress+1
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[5]
'EeAddress=EeAddress+1
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[6]
'EeAddress=EeAddress+1
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[7]
'EeAddress=EeAddress+1
'PAUSE 10
'i2cwrite SDA,SCL,EeCtrl,EeAddress,[8]
'EeAddress=EeAddress+1
'PAUSE 10
'EeWP = 1
' VARIANT 6 - WRITE 8 different bytes to memory = not working
EeWP = 0
PAUSE 10
i2cwrite SDA,SCL,EeCtrl,EeAddress,[1,2,3,4,5,6,7,8]
EeWP = 1
' READ 8 bytes from memory
For Cntr = 0 to 7
i2cread SDA,SCL,EeCtrl,EeAddress,[EeVal(Cntr)]
NEXT Cntr
' display what's in the memory chip
SEROUT2 Ser_Out, Ser_Mode,[DEC3 EeVal(0)," ",DEC3 EeVal(1)," ",DEC3 EeVal(2)," ",_
DEC3 EeVal(3)," ",DEC3 EeVal(4)," ",DEC3 EeVal(5)," ",DEC3 EeVal(6)," ",DEC3 EeVal(7),13,10,10]
' List all memory locations (0..255)
' Mem_Loc = Mem_Loc + 1
' IF Mem_Loc = 0 THEN END
' GOTO MAIN
end
Re: 16F690 and 24LC16B memory - can't WRITE 8 different bytes in a row
keep is simple and clear/concise you need to supply 16 bit address $a0 + block <<1 + r/rw [0 for pbp] + eeaddress [0-255]
' VARIANT 6 - WRITE 8 different bytes to memory = not working
EeWP = 0
PAUSE 10
EeCtrl=$a0 + 2 ;using block 1 ie 1<<1=2
i2cwrite SDA,SCL,EeCtrl,EeAddress,[1,2,3,4,5,6,7,8]
EeWP = 1
3 Attachment(s)
16F690 and 24LC16B memory - can't WRITE 8 different bytes in a row
This is what I get with your suggestion:
Code:
EeCtrl=$a0 + 2 ;using block 1 ie 1<<1=2
i2cwrite SDA,SCL,EeCtrl,0,[1,2,3,4,5,6,7,8]
EeWP = 1
Attachment 8986
Something is also even more confusing to me. As you wrote, the address has to be WORD sized - this is also stated in the DS.
In my code, I have it ("EeCtrl") as a BYTE. If I change it to a WORD, it doesn't make any difference.
Your last suggestion with a WORD sized EeCtrl var gives this result:
Attachment 8987
Maybe I'm messing things up in the I2CWRITE command because I understand it this way and both vars (EeCtrl and EeAddress) are looking to be BYTE long:
Attachment 8988
To be honnest, I don't get that thing with the WORD sized address...
Re: 16F690 and 24LC16B memory - can't WRITE 8 different bytes in a row
the closest eprom i have is a xc24c16 which is pretty similar
this works for me
Code:
DEFINE OSC 8
sda var portc.1
sck var portc.2
TMP VAR byte[3]
osccon=$70 '8 mhz
ansel=0 'dig i/o
CMCON0=7 ' compare off
trisa=%001110
trisc=%111111
serout2 porta.0,84, ["ready ",13,10]
i2cwrite sda,sck,$aa,$38,[1,30,52]
main:
i2cread sda,sck,$aa,$38,[str tmp \3 ]
serout2 porta.0,84, ["d " , #tmp[0] ,"," , #tmp[1] ,"," , #tmp[2] ,",",13,10]
pause 4000
goto main
Re: 16F690 and 24LC16B memory - can't WRITE 8 different bytes in a row
Quote:
To be honnest, I don't get that thing with the WORD sized address...
it's constructed as i stated and sent via i2cwrite as to single bytes ,big end first
Re: 16F690 and 24LC16B memory - can't WRITE 8 different bytes in a row
Quote:
Originally Posted by
richard
the closest eprom i have is a xc24c16...
Thank you very much Richard.
Unfortunately, even with your code example, it looks hopeless :frown:
I should be able to grab another identical chip (or maybe a 24LC64...) by tomorrow or the day after.
Re: 16F690 and 24LC16B memory - can't WRITE 8 different bytes in a row
the control word to address an individual memory cell is 16 bits long for that eeprom
made up as ->
$a0 + block <<1 + r/rw [0 for pbp] + eeaddress [0-255]
for example block=5,cell 0x38
0xA0 + 5<<1 + 0 = 0xAA , high byte of word
address=0x38 , low byte of word
this word is transmitted as two bytes, big end first ,
other eeproms have other schemes where cell address is a word and the device control address byte is a constant
based on address pins plus device code.
address =0x538
i2cwrite sda,sck,$a0,address,[1,30,52]
Quote:
Do you mean the I2C command will transform the two BYTE variables in one WORD sized one?
no , the eeprom will interpret the two bytes as a 16 bit value
1 Attachment(s)
Working fine after chip replacement
Thanks a lot for your patience and clear explanation :wink:
BTW, I changed my chip...and all is working fine now.
I've put my last working test program in attachment.