Hello.
I'm attempting to store a "Long" variable value in Eeprom. I only need values upto about 15,000,000 so I'm splitting my "Long" variable across three byte Eeprom locations. My problem is that while checking to see if my maths is correct, my Long variable resets back to zero upon reaching 65536. I have triple checked that I've declared my variables as Long not Word, I have re-written the program a few times to try to eliminate any silly typos, but I just can't see where I'm going wrong.
I'm stumped.
Assuming this is due to a problem with my logic, can anyone suggest how I can store and recall a value of 15,000,000 or thereabouts in Eeprom for displaying on an LCD display?
#OptionExplicit#Chip16F1829,32'LCD connection settings#DefineLCD_IO4#DefineLCD_SPEEDFAST#DefineLCD_NO_RW#DefineLCD_RSPortA.0#DefineLCD_EnablePortA.1#DefineLCD_DB4PortA.2#DefineLCD_DB5PortC.0#DefineLCD_DB6PortC.1#DefineLCD_DB7PortC.2'Eeprom location#DefineE_Save10'Start of Long(ish) Eeprom locations'Occupies 3 bytes for Hi,Mid and LowDimLong_SavedAsLongDimLong_ReturnedAsLongDimS_HiAsLongDimS_MiAsLongDimS_LoAsLongDimTempAsByteLetLong_Saved=GetLEeprom(E_Save)DoLocate0,0Print" "Locate1,0Print" "LetLong_Saved=Long_Saved+135PutLEeprom(E_Save,Long_Saved)Wait5mSLocate0,0PrintLong_SavedPrint" "Long_Returned=GetLEeprom(E_Save)Locate1,0PrintLong_ReturnedPrint" "Wait100mSLoopSubPutLEeprom(HiAddrAsByte,Save_LongAsLong)'Places a Long(ish) into three bytes of'Eeprom, HiAddr is the first Byte'location in Eeprom, the lower Bytes'are placed into the adjacent bytesLetS_Hi=Save_Long/65536LetSave_Long=Save_Long-(S_Hi*65536)LetS_Mi=Save_Long/256LetS_Lo=Save_Long-(S_Mi*256)EpReadHiAddr,TempIfTemp<>S_HiThenEpWriteHiAddr,S_Hi'The high byteEndIfEpReadHiAddr+1,TempIfTemp<>S_MiThenEpWriteHiAddr+1,S_Mi'The Mid byteEndIfEpReadHiAddr+2,TempIfTemp<>S_LoThenEpWriteHiAddr+2,S_Lo'The Low byteEndIfLocate0,7PrintS_HiPrint" "Locate0,10PrintS_MiPrint" "Locate0,13PrintS_LoPrint" "EndSubFunctionGetLEeprom(HiAddrAsByte)AsLong'Takes the address of the High Byte and returns'a Long(ish) made from the HiAddr and the adjacent'bytes in EepromEpReadHiAddr,S_HiEpReadHiAddr+1,S_MiEpReadHiAddr+2,S_LoLocate1,7PrintS_HiPrint" "Locate1,10PrintS_MiPrint" "Locate1,13PrintS_LoPrint" "LetS_Hi=S_Hi*65536'Build the High byteLetS_Mi=S_Mi*256'Build the Mid byteLetGetLEeprom=S_Hi+S_Mi+S_LoEndFunction
Last edit: mkstevo 2017-09-15
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Further experimentation has shown that the problem appears to lie with the SubRoutine declaration (and possibly the Function declaration too) where the "As Long" may be incorrectly interpreted.
This works as I'd expected:
#OptionExplicit#Chip16F1829,32'LCD connection settings#DefineLCD_IO4#DefineLCD_SPEEDFAST#DefineLCD_NO_RW#DefineLCD_RSPortA.0#DefineLCD_EnablePortA.1#DefineLCD_DB4PortA.2#DefineLCD_DB5PortC.0#DefineLCD_DB6PortC.1#DefineLCD_DB7PortC.2'Eeprom location#DefineE_Save10'Start of Long(ish) Eeprom locations'Occupies 3 bytes for Hi,Mid and LowDimLong_SavedAsLongDimLong_ReturnedAsLongDimSave_LongAsLongDimRet_LongAsLongDimS_HiAsLongDimS_MiAsLongDimS_LoAsLongDimTempAsByteGetLEeprom(E_Save)LetLong_Saved=Ret_LongIfLong_Saved>16777000ThenLetLong_Saved=0EndIfDoLocate0,0Print" "Locate1,0Print" "LetLong_Saved=Long_Saved+135LetSave_Long=Long_SavedPutLEeprom(E_Save)Wait5mSLocate0,0PrintLong_SavedPrint" "GetLEeprom(E_Save)LetLong_Returned=Ret_LongLocate1,0PrintLong_ReturnedPrint" "Wait100mSLoopSubPutLEeprom(HiAddrAsByte)'Places a Long(ish) into three bytes of'Eeprom, HiAddr is the first Byte'location in Eeprom, the lower Bytes'are placed into the adjacent bytesLetS_Hi=Save_Long/65536LetSave_Long=Save_Long-(S_Hi*65536)LetS_Mi=Save_Long/256LetS_Lo=Save_Long-(S_Mi*256)EpReadHiAddr,TempIfTemp<>S_HiThenEpWriteHiAddr,S_Hi'The high byteEndIfEpReadHiAddr+1,TempIfTemp<>S_MiThenEpWriteHiAddr+1,S_Mi'The Mid byteEndIfEpReadHiAddr+2,TempIfTemp<>S_LoThenEpWriteHiAddr+2,S_Lo'The Low byteEndIfLocate0,7PrintS_HiPrint" "Locate0,10PrintS_MiPrint" "Locate0,13PrintS_LoPrint" "EndSubSubGetLEeprom(HiAddrAsByte)'Takes the address of the High Byte and returns'a Long(ish) made from the HiAddr and the adjacent'bytes in EepromEpReadHiAddr,S_HiEpReadHiAddr+1,S_MiEpReadHiAddr+2,S_LoLocate1,7PrintS_HiPrint" "Locate1,10PrintS_MiPrint" "Locate1,13PrintS_LoPrint" "LetS_Hi=S_Hi*65536'Build the High byteLetS_Mi=S_Mi*256'Build the Mid byte'Let GetLEeprom = S_Hi + S_Mi + S_LoLetRet_Long=S_Hi+S_Mi+S_LoEndSub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I had previously tried to use the WordVariable_H method when storing a Word variable in Eeprom, but failed to get it to work correctly. Having used my long winded method for extracting the byte values from a Word successfully in that instance, I simply "scaled" it up for the additional byte required to give me the maximum value I needed to store in Eeprom.
When I am next at my computer, I will try again using the LongVariable_H, LongVariable_U, LongVariable_E methods and see if I can spot why I couldn't get it to work.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Something is not correct somewhere. Use a Sub to return the value as this always works.
What is very odd is that the first call to print the long value is correct, the, second is incorrect.
Evan
#Option Explicit
#Chip 16F877a,4
'LCD connection settings
#Define LCD_IO 4
#Define LCD_SPEED FAST
#Define LCD_NO_RW
#Define LCD_RS PortA.0
#Define LCD_Enable PortA.1
#Define LCD_DB4 PortA.2
#Define LCD_DB5 PortC.0
#Define LCD_DB6 PortC.1
#Define LCD_DB7 PortC.2
'Eeprom location
#Define E_Save 10 'Start of Long(ish) Eeprom locations
'Occupies 3 bytes for Hi,Mid and Low
Dim Long_Saved As Long
Dim Long_Returned As Long
Dim Temp As Byte
Long_Saved = 0
Do
Locate 0, 0
Print " "
Locate 1, 0
Print " "
Let Long_Saved = Long_Saved + 135
PutLEeprom( E_Save, Long_Saved )
Wait 5 mS
Locate 0, 0
Print Long_Saved
Print " "
GetLEeprom( E_Save, Long_Returned )
Locate 1, 0
Print Long_Returned
wait 10 ms
Loop
Sub PutLEeprom (HiAddr As Byte, Save_Long As Long) 'Places a Long(ish) into three bytes of
'Eeprom, HiAddr is the first Byte
'location in Eeprom, the lower Bytes
'are placed into the adjacent bytes
EpWrite (HiAddr, Save_Long_E) 'The high byte
EpWrite (HiAddr+1,Save_Long_U) 'The Mid byte
EpWrite (HiAddr+2,Save_Long_H) 'The Low byte
EpWrite (HiAddr+3,Save_Long) 'The Low byte
End Sub
Sub GetLEeprom(HiAddr, out EepromVal as long ) 'Takes the address of the High Byte and returns
'a Long(ish) made from the HiAddr and the adjacent
'bytes in Eeprom
EpRead HiAddr+3, EepromVal
EpRead HiAddr+2, EepromVal_H
EpRead HiAddr+1, EepromVal_U
EpRead HiAddr, EepromVal_E
End Sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Since only 24bits are being used, there is no need to write the "E" byte. The code below demos how to write and read a 24bit value to and from EEPROM.
#chip 18F25K80, 16
#Config OSC = INTIO2
#config MCLRE = ON
#option explicit
;----- Define I2C settings - CHANGE PORTS
#define I2C_MODE Master
#define I2C_DATA PORTC.4
#define I2C_CLOCK PORTC.5
#define I2C_DISABLE_INTERRUPTS ON
;----- Set up LCD
#define LCD_IO 10
#define LCD_I2C_Address_1 0x7E
CLS
Wait 1 s
'// delcare variables
DIM Var1 as Long
DIM Var2 as Long
DIM Var3 as Long
' // set values to test
Var1 = 11476222
Var2 = 14777810
Var3 = 0'clear
'// write 24 bits Vales to EEPRPoM
EPWRITE_24 0, Var1
EPWRITE_24 3, Var2
'// read stored Var1 back into var3
EPREAD_24 0, Var3
Locate 0,0 : Print Var3
'read stored var2 back into Var3
Var3 = 0 '//clear variable
EPREAD_24 3, Var3
Locate 1,0 : Print Var3
End
Sub EPWRITE_24 (IN Mem_Loc as Byte, in TMP_LONG as LONG)
EPWRITE Mem_Loc, TMP_LONG
EPWRITE Mem_Loc + 1, TMP_LONG_H
EPWRITE Mem_Loc + 2, TMP_LONG_U
END SUB
SUB EPREAD_24 (IN Mem_Loc as Byte, OUT NewVal as LONG)
EPREAD Mem_Loc, NewVal
EPREAD Mem_Loc + 1, NewVal_H
EPREAD Mem_Loc + 2, NewVal_U
End SUB
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The root cause of the isue has been found and resolved. We have found a long standing issue (2009) where setting the return value of a function by using it as a subroutine parameter did not work. This is the issue that Steve found. The issue only related to the use of a function not a subroutine.
The fix will be included in v0.98.00. Meanwhile, use the subroutine techniques that Bill and I have recommended.
Hello to you both, and thanks for your suggestions. I won't be able to test any of your suggestions for a few hours, possibly Monday evening at the earliest. Once I've had a chance to test your examples, I'll report back.
I will also look into using the EepromVal_E,EepromVal_U and EepromVal_H type methods of extracting the byte values from the Long. When I last tried using them (on Word values) I possibly misinterpreted the ability to extract the lowest byte value by assigning the Long directly to a Byte, I might have tried to use an alias of something similar to 'EepromVal_L' for the lowest byte.
As I say, thanks for your help so far, I'll report back as soon as I can.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks to all who kindly gave their time in looking at this. It appears as though I found a small bug relating to Long variables being used as parameters in SubRoutines and Functions. I have tested a bug fix version of the compiler which does indeed work as anticipated.
From the release of V0.98 onwards this error regarding Functions should be fixed.
I have to say that using the examples given above, I have been able to tidy my code enourmously, and have been able to increase my storing of a Long value to the full four Byte length allowing me to store values of up to 4+ Billion.
Once again, I'd like to thank everyone's kind contributions.
This code does work as expected on V0.96, and is based on William's and Anobium's suggestions to use a SubRoutine to return the values.
#OptionExplicit#Chip16F1829,32'LCD connection settings#DefineLCD_IO4#DefineLCD_SPEEDFAST#DefineLCD_NO_RW#DefineLCD_RSPortA.0#DefineLCD_EnablePortA.1#DefineLCD_DB4PortA.2#DefineLCD_DB5PortC.0#DefineLCD_DB6PortC.1#DefineLCD_DB7PortC.2'Eeprom location#DefineE_Save10'Start of Long Eeprom locations'Occupies 4 bytes for High, UMid, LMid and LowDimLong_SavedAsLongDimLong_ReturnedAsLongDimTempAsByteDimTempRAsByteGetLEeprom(E_Save,Long_Saved)IfLong_Saved>4000000000ThenLetLong_Saved=0EndIfClsLocate0,11Print":Save"Locate1,11Print": Ret"DoIfLong_Saved<917575ThenClsLocate0,11Print":Save"Locate1,11Print": Ret"EndIfLetLong_Saved=Long_Saved+917575PutLEeprom(E_Save,Long_Saved)Locate0,0PrintLong_SavedGetLEeprom(E_Save,Long_Returned)Locate1,0PrintLong_ReturnedWait1mSLoopSubPutLEeprom(InHiAddrAsByte,InSave_LongAsLong)'Places a Long into four bytes of'Eeprom, HiAddr is the first Byte'location in Eeprom, the lower Bytes'are placed into the adjacent bytesLetTemp=Save_Long_EEpReadHiAddr,TempRIfTemp<>TempRThenEpWrite(HiAddr,Temp)'The High byteEndIfLetTemp=Save_Long_UEpReadHiAddr+1,TempRIfTemp<>TempRThenEpWrite(HiAddr+1,Temp)'The UMid byteEndIfLetTemp=Save_Long_HEpReadHiAddr+2,TempRIfTemp<>TempRThenEpWrite(HiAddr+2,Temp)'The LMid byteEndIfLetTemp=Save_LongEpReadHiAddr+3,TempRIfTemp<>TempRThenEpWrite(HiAddr+3,Temp)'The Low byteEndIfEndSubSubGetLEeprom(InHiAddrAsByte,OutEepromValAsLong)'Takes the address of the High Byte and returns'a Long made from the HiAddr and the adjacent'bytes in Eeprom'The sequence of this 'Rebuild' appears important.'The order of Low byte - High must be maintained.EpReadHiAddr+3,EepromValEpReadHiAddr+2,EepromVal_HEpReadHiAddr+1,EepromVal_UEpReadHiAddr,EepromVal_EEndSub
Last edit: mkstevo 2017-09-17
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello.
I'm attempting to store a "Long" variable value in Eeprom. I only need values upto about 15,000,000 so I'm splitting my "Long" variable across three byte Eeprom locations. My problem is that while checking to see if my maths is correct, my Long variable resets back to zero upon reaching 65536. I have triple checked that I've declared my variables as Long not Word, I have re-written the program a few times to try to eliminate any silly typos, but I just can't see where I'm going wrong.
I'm stumped.
Assuming this is due to a problem with my logic, can anyone suggest how I can store and recall a value of 15,000,000 or thereabouts in Eeprom for displaying on an LCD display?
Last edit: mkstevo 2017-09-15
Further experimentation has shown that the problem appears to lie with the SubRoutine declaration (and possibly the Function declaration too) where the "As Long" may be incorrectly interpreted.
This works as I'd expected:
@Steve. I think you should review https://sourceforge.net/p/gcbasic/discussion/579126/thread/16ce811d/#ef41
I am thinking you should be addressing as follows:
Then, you can remove some complexity by simply address the bytes with the the long variable.
Many thanks for your kind reply.
I had previously tried to use the WordVariable_H method when storing a Word variable in Eeprom, but failed to get it to work correctly. Having used my long winded method for extracting the byte values from a Word successfully in that instance, I simply "scaled" it up for the additional byte required to give me the maximum value I needed to store in Eeprom.
When I am next at my computer, I will try again using the LongVariable_H, LongVariable_U, LongVariable_E methods and see if I can spot why I couldn't get it to work.
Something is not correct somewhere. Use a Sub to return the value as this always works.
What is very odd is that the first call to print the long value is correct, the, second is incorrect.
Evan
Since only 24bits are being used, there is no need to write the "E" byte. The code below demos how to write and read a 24bit value to and from EEPROM.
The root cause of the isue has been found and resolved. We have found a long standing issue (2009) where setting the return value of a function by using it as a subroutine parameter did not work. This is the issue that Steve found. The issue only related to the use of a function not a subroutine.
The fix will be included in v0.98.00. Meanwhile, use the subroutine techniques that Bill and I have recommended.
I also have created a few demos based on this posting. Writing and Reading variables has been asked many times, so, I created two test programs (now deoms) and I have adapted Bill's code. These can be adapted by others in GitHub. See https://github.com/Anobium/Great-Cow-BASIC-Demonstration-Sources/tree/master/EEPROM%20Solutions/Save_and_Read_Variables_to_EEPROM
Last edit: Anobium 2017-09-17
Hello to you both, and thanks for your suggestions. I won't be able to test any of your suggestions for a few hours, possibly Monday evening at the earliest. Once I've had a chance to test your examples, I'll report back.
I will also look into using the EepromVal_E,EepromVal_U and EepromVal_H type methods of extracting the byte values from the Long. When I last tried using them (on Word values) I possibly misinterpreted the ability to extract the lowest byte value by assigning the Long directly to a Byte, I might have tried to use an alias of something similar to 'EepromVal_L' for the lowest byte.
As I say, thanks for your help so far, I'll report back as soon as I can.
Thanks to all who kindly gave their time in looking at this. It appears as though I found a small bug relating to Long variables being used as parameters in SubRoutines and Functions. I have tested a bug fix version of the compiler which does indeed work as anticipated.
From the release of V0.98 onwards this error regarding Functions should be fixed.
I have to say that using the examples given above, I have been able to tidy my code enourmously, and have been able to increase my storing of a Long value to the full four Byte length allowing me to store values of up to 4+ Billion.
Once again, I'd like to thank everyone's kind contributions.
This code does work as expected on V0.96, and is based on William's and Anobium's suggestions to use a SubRoutine to return the values.
Last edit: mkstevo 2017-09-17