Not a problem with GCB as such, but I'm a little confused by the addressing of a 24C16 Eeprom device.
I've got the LCD discovery program running on my 16F1829 with a serial LCD, and have this connected to my 24C16. When the program is run, it reports:
ID: 0xA0
EEProm_Device
ID: 0xA2
EEProm_Device
ID: 0xA4
EEProm_Device
ID: 0xA6
EEProm_Device
ID: 0xA8
EEProm_Device
ID: 0xAA
EEProm_Device
ID: 0xAC
EEProm_Device
ID: 0xAE
EEProm_Device
If I connect a small RTC module from China with a DS3231 and an on board 24C32, when the program is run it reports:
ID: 0xAE
EEProm_Device
ID: 0xD0
DS1307 RTC
By soldering the links on the RTC module for the EEProm address, I can set the address of the 24C32 for any of the addresses from A0 to AE. I only ever see one address for the 24C32 on this module.
I've tried pulling the address lines high on the 24C16, tried pulling them low, tried all combinations, but it still responds to all the addresses A0 to AE. I've tried a 24C16WP and a U02016B (Atmel device that should be either a 24C16 equivalent or 24C04) which give the same results as the 24C16.
Being new to I2C, is this normal? Which of the addresses should I choose? Have I done something daft in how I've connected it and need to 'activate' the address lines?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It would seem that the top 4-bits of the address are set to A (1010) and the next 3-bits are the MSB of the eeprom memory (so can take any value) the last bit is 0 for write and 1 for read.
Seems a bit dodgy as any I2C device (connected to the same pins) with a top 4-bits of its address = 1010 could be woken up and addressed inadvertently.
So the I2C discovery is working correctly.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If I can advise. Is there an Alternative I2C Discovery for that part?
Why? When I wrote the initial discovery I (stupidly) assumed I would be able to maintain the look up of devices... this update prooved too hard. So, I wrote the Alternative I2C Discovery which simply displays active I2C port addresses. Is there a version for that part?
Always pull i2c high. I used 4k but anything between 2k and 4k should work.
I have not used a 24C16 but the adresses between 0xA0and 0xAE are the write address of the banks of EEPROM.
- So, write and read data A0 and AxA1 should be different to the write and read data to and 0xA2 and 0xA3. Try, reading and writing to the different loctions.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm not sure about the 'Alternative I2C Discovery'. I simply tweaked the file from the demo folder: I2CSoftwareDiscovery to_LCD_ATMega8 so that it worked on a 16F1825, and output the display to a serial LCD display.
I have 4k7 pull up resistors on my I2C bus. I did try 1k but that made no difference.
I had wondered if the memory 'banks' might be on the different device IDs. I modified the Discovery demo so that it wrote a Byte into an address, and then read it back to see if it was actually working, and that did seem to write and read, to each of the device IDs. I'll have to try to write and read a differing value to each location tomorrow. I think the version I've left running overnight is clocking through each memory location, but writing the same value to each.
It does seem odd that it is (not) addressed in that way, but if it is, it is. It might explain why some versions of the parts don't show the A0, A1 or A2 connections on pins 1, 2 and 3.
Thanks for the suggestions. I'll have to order some DIL versions of the 24C32 to try.
I was simply considering getting to grips with some off chip EeProm for storing a few program parameters, run counts and the like. Thinking of the write life of the EeProm on the 16F1825/1829 being limited, I wondered if I could extend the device lifetime by using external memory. I think the lifetime of my devices, even using the on chip EeProm, should be in the region of a few years, after which it isn't unreasonable to be able to sell the customer a new chip anyway, but if I can improve the lifetime by using external memory, I'd quite like to.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The EEPROM lifetime is a bit confusing and as I do store backup variables in the eeprom (in case of a power outage) I researched the problem.
Microchip generally say that each byte will typically stand 100k erase/write cycles - so if you're not storing many bytes - moving the write byte address around would make it difficult to exceed this.
The other consideration is if you have some bytes that have data stored, but are not frequently re-written the data could be lost after 10M read/writes to other bytes in the EEPROM ( If you erase and write 256 bytes this is counted as 256 erase/writes towards your 10M).
I have never found pull-ups critical 4k7 seems good enough, if the device is close to the chip even the internal weak pull-ups will suffice (that is if there is not much capacitance in the clock/data lines)..
Last edit: David Stephenson 2018-12-05
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You just write as if it were RAM and the device takes care of the rest by only writing to the EEPROM if it detects a power fail condition and It automatically restores the RAM on power Up.
So it only uses write cycles in the event of an actual power fail, rather than a scheduled basis.
There is a Library for it in GCBASIC along with examples.
Cheers
Chris
Last edit: Chris Roper 2018-12-05
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Given the low cost of the EERAM devices, I've ordered a few to 'play' with. Thanks for pointing them out.
So far, I've had no failures of EeProm within the PIC devices I use (mostly the 16F1829 or 1825) I generally store a few program parameters, a serial number and a few other things that are mostly static. and don't change more than once or twice a year. I have a few programs which store more items that change around 50 times per day, but 100,000 write cycles / 50 per day = 2000 days = 5 years. So I expect to see some orders for replacement devices in a year or two!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I will look at the Serial EeRAM device, it does sound ideal. Especially so if there is a library for it!
Having looked again at this, it appears as though the 24C16 has it's EePROM split into 8 banks of 255 bytes, each bank is addressed through the addresses A0 - AE, in 'even numbered blocks' so A0, A2, A4, A6, A8, AA, AC and AE.
The code I have used to access this is:
'''A demonstration program for GCGB and GCB.'''--------------------------------------------------------------------------------------------------------------------------------'''This program searches for I2C devices and display their adresses to a serial LCD.'''This program uses the GCB software TWI implementation for the I2C protocol.'''@author TheoL plus works of EvanV'''@licence GPL'''@version 1.0a'''@date 23.02.15''' Modified for a Serial LCD Mark Stevenson 4/12/2018'''********************************************************************************;-----Configuration#chip16F1825,32#optionexplicit;-----DefineHardwaresettings' Define I2C settings - CHANGE PORTS#defineI2C_MODEMaster#defineI2C_DATAPORTC.1'Dat Pin 9#defineI2C_CLOCKPORTC.2'Clk Pin 8#defineI2C_DISABLE_INTERRUPTSON' turn on the RS232 and terminal port.' Define the USART port#defineUSART_BAUD_RATE9600#defineUSART_BLOCKING#defineSerOutPortportC.4'Ser Pin 6'Defines a serial LCD connection. Use the Serial_LCD_16F1825.gcb and LCD.#include<I2CEEPROM.h>DimRead_ValueAsByteDimDeviceIDAsByteDimMem_LocAsByteLetMem_Loc=0Wait500mS;-----Mainbodyofprogramcommenceshere.SerLocate0,0HSerPrint"**Software TWI**"SerLocate1,0HSerPrint"I2C Dev. Search "Wait1000mSSerClsDoFordeviceID=0to255I2CStartI2CSend(deviceID)IfI2CSendState=TruethenSerLocate0,0HSerPrint"ID: 0x"HSerPrinthex(deviceID)SelectCasedeviceIDSerLocate1,0case48HSerPrint"DS2482_1Channel "case64HSerPrint"IC2/Serial_Expan"case68HSerPrint"IC2/Serial_Expan"case72HSerPrint"PCF8574 8bit I/O"case74HSerPrint"PCF8574 8bit I/O"case76HSerPrint"PCF8574 8bit I/O"case78HSerPrint"PCF8574 8bit I/O"case96HSerPrint"GCB Slave Device"case144HSerPrint"PCF8591 AD/DA "case160HSerPrint"EEProm "TestEePromcase162HSerPrint"EEProm "TestEePromcase164HSerPrint"EEProm "TestEePromcase166HSerPrint"EEProm "TestEePromcase168HSerPrint"EEProm "TestEePromcase170HSerPrint"EEProm "TestEePromcase172HSerPrint"EEProm "TestEePromcase174HSerPrint"EEProm "TestEePromcase198HSerPrint"AXE033 I2C LCD "case208HSerPrint"DS1307 RTC "case248HSerPrint"FRAM_Device "caseelseHSerPrint"Unknown_Device "EndselectdeviceID++wait500mSElseSerLocate0,0HSerPrint"ID: 0x "SerLocate0,6HSerPrinthex(deviceID)SerLocate1,0HSerPrint" Searching "EndifI2CStopnextLetMem_Loc=Mem_Loc+2loopSubSerLocate(L_Line,L_PosAsByte)IfL_Line=0ThenLetL_Pos=L_Pos+128ElseLetL_Pos=L_Pos+192EndifHSerSend254'Command followsHSerSendL_PosWait10mSEndSubSubSerCLSHSerSend254'Command followsHSerSend1'CLSWait30mS'Mandatory after a CLS commandEndSubSubTestEePromForMem_Loc=0to255WriteByte(DeviceID,Mem_Loc,Mem_Loc)Wait10mSLetRead_Value=ReadByte(DeviceID,Mem_Loc)SerLocate0,9IfRead_Value=Mem_LocThenHSerPrint"S:"ElseHSerPrint"F:"EndIfHSerPrintRead_ValueSerLocate1,9HSerPrint"L:"HSerPrintMem_LocNextSerLocate0,9HSerPrint" "SerLocate1,9HSerPrint" "EndSubSubWriteByte(InEePDev,InEePAddrAsByte,InWByteAsByte)EeProm_Wr_Byte(EePDev,EePAddr,WByte)'NOTE the original line from the I2CEEPROM header file has an error. eepAddr MUST be a Byte value.'Correct: eeprom_wr_byte (in eepDev as byte, in eepAddr as Byte, in eepromVal as byte)'Wrong: eeprom_wr_byte (in eepDev as byte, in eepAddr as word, in eepromVal as byte)EndSubFunctionReadByte(InEePDevAsByte,InEePAddrAsByte)DimEePromValAsByteLetEePromVal=0EeProm_Rd_Byte(EePDev,EepAddr,EePromVal)LetReadByte=EePromVal'eeprom_rd_byte(in eepDev as byte, in eepAddr as byte, out eepromVal as byte )EndFunction
This is a modified version of the file: I2CSoftwareDiscovery to_LCD_ATMega8 from the demo folder.
To test the correct operation, I'm using a Hi-Lo All100 programmer which after the program has been run at least once, shows the contents of memory as having the values 0-255 sequentially in each of the blocks of memory.
So in conclusion, I was confused by the multiple addresses found by the Discovery program, I then made the mistake of trying to use a word variable for the eepAddr value in 'eeprom_wr_byte' which I'd copied from the I2CEEPROM header file. This added to the confusion as it messed everything up big time and the storage location went haywire.
Last edit: mkstevo 2018-12-05
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
With the program slightly modified to show the I2C device address at the start and end of each of the banks, here is a capture of part of the data read back by the All100 programmer. Byte 0 and byte 255, have the bank address stored within them showing the start and end of each bank.
Not a problem with GCB as such, but I'm a little confused by the addressing of a 24C16 Eeprom device.
I've got the LCD discovery program running on my 16F1829 with a serial LCD, and have this connected to my 24C16. When the program is run, it reports:
ID: 0xA0
EEProm_Device
ID: 0xA2
EEProm_Device
ID: 0xA4
EEProm_Device
ID: 0xA6
EEProm_Device
ID: 0xA8
EEProm_Device
ID: 0xAA
EEProm_Device
ID: 0xAC
EEProm_Device
ID: 0xAE
EEProm_Device
If I connect a small RTC module from China with a DS3231 and an on board 24C32, when the program is run it reports:
ID: 0xAE
EEProm_Device
ID: 0xD0
DS1307 RTC
By soldering the links on the RTC module for the EEProm address, I can set the address of the 24C32 for any of the addresses from A0 to AE. I only ever see one address for the 24C32 on this module.
I've tried pulling the address lines high on the 24C16, tried pulling them low, tried all combinations, but it still responds to all the addresses A0 to AE. I've tried a 24C16WP and a U02016B (Atmel device that should be either a 24C16 equivalent or 24C04) which give the same results as the 24C16.
Being new to I2C, is this normal? Which of the addresses should I choose? Have I done something daft in how I've connected it and need to 'activate' the address lines?
It would seem that the top 4-bits of the address are set to A (1010) and the next 3-bits are the MSB of the eeprom memory (so can take any value) the last bit is 0 for write and 1 for read.
Seems a bit dodgy as any I2C device (connected to the same pins) with a top 4-bits of its address = 1010 could be woken up and addressed inadvertently.
So the I2C discovery is working correctly.
If I can advise. Is there an Alternative I2C Discovery for that part?
Why? When I wrote the initial discovery I (stupidly) assumed I would be able to maintain the look up of devices... this update prooved too hard. So, I wrote the Alternative I2C Discovery which simply displays active I2C port addresses. Is there a version for that part?
Always pull i2c high. I used 4k but anything between 2k and 4k should work.
I have not used a 24C16 but the adresses between 0xA0and 0xAE are the write address of the banks of EEPROM.
- So, write and read data A0 and AxA1 should be different to the write and read data to and 0xA2 and 0xA3. Try, reading and writing to the different loctions.
I'm not sure about the 'Alternative I2C Discovery'. I simply tweaked the file from the demo folder: I2CSoftwareDiscovery to_LCD_ATMega8 so that it worked on a 16F1825, and output the display to a serial LCD display.
I have 4k7 pull up resistors on my I2C bus. I did try 1k but that made no difference.
I had wondered if the memory 'banks' might be on the different device IDs. I modified the Discovery demo so that it wrote a Byte into an address, and then read it back to see if it was actually working, and that did seem to write and read, to each of the device IDs. I'll have to try to write and read a differing value to each location tomorrow. I think the version I've left running overnight is clocking through each memory location, but writing the same value to each.
It does seem odd that it is (not) addressed in that way, but if it is, it is. It might explain why some versions of the parts don't show the A0, A1 or A2 connections on pins 1, 2 and 3.
Thanks for the suggestions. I'll have to order some DIL versions of the 24C32 to try.
I was simply considering getting to grips with some off chip EeProm for storing a few program parameters, run counts and the like. Thinking of the write life of the EeProm on the 16F1825/1829 being limited, I wondered if I could extend the device lifetime by using external memory. I think the lifetime of my devices, even using the on chip EeProm, should be in the region of a few years, after which it isn't unreasonable to be able to sell the customer a new chip anyway, but if I can improve the lifetime by using external memory, I'd quite like to.
The EEPROM lifetime is a bit confusing and as I do store backup variables in the eeprom (in case of a power outage) I researched the problem.
Microchip generally say that each byte will typically stand 100k erase/write cycles - so if you're not storing many bytes - moving the write byte address around would make it difficult to exceed this.
The other consideration is if you have some bytes that have data stored, but are not frequently re-written the data could be lost after 10M read/writes to other bytes in the EEPROM ( If you erase and write 256 bytes this is counted as 256 erase/writes towards your 10M).
I have never found pull-ups critical 4k7 seems good enough, if the device is close to the chip even the internal weak pull-ups will suffice (that is if there is not much capacitance in the clock/data lines)..
Last edit: David Stephenson 2018-12-05
@David and mkstevo
Have you considered using EERAM
https://www.microchip.com/design-centers/memory/serial-eeram
It is Serial RAM with EEPROM backup.
You just write as if it were RAM and the device takes care of the rest by only writing to the EEPROM if it detects a power fail condition and It automatically restores the RAM on power Up.
So it only uses write cycles in the event of an actual power fail, rather than a scheduled basis.
There is a Library for it in GCBASIC along with examples.
Cheers
Chris
Last edit: Chris Roper 2018-12-05
Given the low cost of the EERAM devices, I've ordered a few to 'play' with. Thanks for pointing them out.
So far, I've had no failures of EeProm within the PIC devices I use (mostly the 16F1829 or 1825) I generally store a few program parameters, a serial number and a few other things that are mostly static. and don't change more than once or twice a year. I have a few programs which store more items that change around 50 times per day, but 100,000 write cycles / 50 per day = 2000 days = 5 years. So I expect to see some orders for replacement devices in a year or two!
Thanks again for all the suggestions.
I will look at the Serial EeRAM device, it does sound ideal. Especially so if there is a library for it!
Having looked again at this, it appears as though the 24C16 has it's EePROM split into 8 banks of 255 bytes, each bank is addressed through the addresses A0 - AE, in 'even numbered blocks' so A0, A2, A4, A6, A8, AA, AC and AE.
The code I have used to access this is:
This is a modified version of the file: I2CSoftwareDiscovery to_LCD_ATMega8 from the demo folder.
To test the correct operation, I'm using a Hi-Lo All100 programmer which after the program has been run at least once, shows the contents of memory as having the values 0-255 sequentially in each of the blocks of memory.
So in conclusion, I was confused by the multiple addresses found by the Discovery program, I then made the mistake of trying to use a word variable for the eepAddr value in 'eeprom_wr_byte' which I'd copied from the I2CEEPROM header file. This added to the confusion as it messed everything up big time and the storage location went haywire.
Last edit: mkstevo 2018-12-05
With the program slightly modified to show the I2C device address at the start and end of each of the banks, here is a capture of part of the data read back by the All100 programmer. Byte 0 and byte 255, have the bank address stored within them showing the start and end of each bank.