for one of my future projects (when time allows) i want to give a unique id to each chip, i have been playing around with the sqtp settings on my pickit 3 and have no problems getting this working.
what i would like to clarify is how would i go about reading these locations from within my code when the chip has been assigned a unique i.d after programming.
the user i.d memory locations for the chip used (pic16f1825) are 8000h-80003h, i am familiar with the usual reading/writing to eeprom from within my code for other uses but not really sure how i would go about the user i.d locations assuming it would be done diferently.
tony
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
ProgramRead (8000, uid)
wait 10 ms
HserPrint "UID = "
HserPrint uid
HserPrintCRLF
uid = 0
wait 500 ms
Loop
~~~
again that is just a guess about how to go about this.
for now i am only using user id adress 8000h which i gather is a 2 byte or word sized location,
reading the programmed chip with my pickit 3 shows
address user id
8000 18F9
8001 3FFF
8002 3FFF
8003 3FFF
but the terminal output shows for location 8000 UID = 16128 which in hex is 3F00 so still some things need to be changed or altered but i dont know where to go from here.
tony
edit: upon cycling power it seems the value can change randomly so honestly i dont think it is indeed reading the stored user id at the location.
edit again: even tried setting the EEPGD and CFGS bits in the eecon reg but still i cannot read any location back that matches what i see in the pickit memory view window regardless, im thinking programread is not working
Last edit: tony golding 2016-08-20
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
well im stumped, i can see the user id location change value when i program it and the next sequential uid get loaded from the sqtp file via the pickit 3 memory view window but i just cant get any success with the programread function for ANY locations even in the main program space.
how can i read the user id locations?? answers on a postcard please.
tony
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
#chip 16f1825, 16
#config MCLRE = off
;USART settings
#define USART_BAUD_RATE 9600
#define USART_BL0CKING
TXCKSEL = 1
dir PORTA.0 out
dim uid as Word
wait 500 ms
;Main Program starts here
Do
IDRead (8000, uid)
wait 10 ms
HserPrint "UID = "
HserPrint uid
HserPrintCRLF
uid = 0
wait 500 ms
Loop
sub IDRead(In EEAddress, Out EEDataWord)
Dim EEAddress As Word Alias EEADRH, EEADR
Dim EEDataWord As Word Alias EEDATH, EEDATL_REF
EEADRH = 0
'Select program memory
SET EECON1.CFGS ON
'Disable Interrupt
SET INTCON.GIE OFF
'Start read, wait for it to finish
SET EECON1.RD ON
NOP
NOP
'Enable interrupt
SET INTCON.GIE ON
end sub
I have not tested it on any hardware but it does generate the example code shown in the data sheet:
* This code block will read 1 word of program memory at the memory address:
* PROG_ADDR_LO (must be 00h-08h) data will be returned in the variables;
* PROG_DATA_HI, PROG_DATA_LO
BANKSEL EEADRL ; Select correct Bank
MOVLW PROG_ADDR_LO ;
MOVWF EEADRL ; Store LSB of address
CLRF EEADRH ; Clear MSB of address
BSF EECON1,CFGS ; Select Configuration Space
BCF INTCON,GIE ; Disable interrupts
BSF EECON1,RD ; Initiate read
NOP ; Executed (See Figure 11-1)
NOP ; Ignored (See Figure 11-1)
BSF INTCON,GIE ; Restore interrupts
MOVF EEDATL,W ; Get LSB of word
MOVWF PROG_DATA_LO ; Store in user location
MOVF EEDATH,W ; Get MSB of word
MOVWF PROG_DATA_HI ; Store in user location
GCBasic generates:
IDREAD
;Dim EEAddress As Word Alias EEADRH, EEADR
;Dim EEDataWord As Word Alias EEDATH, EEDATL_REF
;EEADRH = 0
banksel EEADRH
clrf EEADRH
;SET EECON1.CFGS ON
bsf EECON1,CFGS
;SET INTCON.GIE OFF
bcf INTCON,GIE
;SET EECON1.RD ON
bsf EECON1,RD
;NOP
nop
;NOP
nop
;SET INTCON.GIE ON
bsf INTCON,GIE
banksel STATUS
return
My reasoning is that ProgramRead was setting EECON1,CFGS OFF where this code sets it ON.
and this code clears EEADRH whereas the origional code left it as 0x80.
Cheers
Chris
Last edit: Chris Roper 2016-08-20
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
thanks for this but its still not co-operating so something more going on i think.
just flashed the code to the chip with a serial in the idloc0 (8000h) and still getting random results.
the user id im seeing on the memory window view shows user id of A480 hex but on the terminal output its telling me the uid is 7200 (1C20 hex), then if i cycle the power that uid value then changes to 7168 (1C00 hex), somethings definately not right with this but as to what is the confusing part.
thanks anyway,
tony
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
How are you creating and programming the ID's?
I see that there are several threads on the topic and they differ according to the tool used.
I looked at MPLabX IPE and it has severa options there.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have a working program memory write/read if tony wants to verify his setup? It erases/writes a whole row at a time, then reads the first address, which was good enough for me at the time. Code could definitely be improved upon.
I had a go at write and read of the user id, and no luck so far.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
i am using my pickit 3 to add the serial to the device when programmed, i used the options in the advanced mode to generate an sqtp file to pull each serial from when programming a chip.
once i have programmed a chip i can use the read function of the pickit and see in the memory view window the user id written to location 0 in hex, the only issue seems to be reading it back in the chip via code not matching up with what would be expected, even after converting the returned decimal value from the uid to hex with the standrd windows pc calculator it does not seem to be correct
a bit strange to say the least.
edit: also i am using my pickit with mplabx ipe to program my chips.
Last edit: tony golding 2016-08-20
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
i am using my pickit 3 to add the serial to the device when programmed, i used the options in the advanced mode to generate an sqtp file to pull each serial from when programming a chip.
But which software?
I have PICKit3 Version 3.10 but it has no advanced option and the only referance to User ID in the documentation are the read failed and write failed error codes.
I was hoping to recreate your setup so that I could test the code.
cheers
Chris
Last edit: Chris Roper 2016-08-20
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If you are using the SQTP tab in the Advanced options of IPEv3.35 can you let me know the settings, or beter yet a screenshot, so that I can set mine up to match?
Cheers
Chris
I can read back the first byte of the user id now. If someone wants to spend the time to read more bytes etc. feel free. Attached screen shot of the IPE sqtp setup. Kind of a pain to download the hex and sqtp each and every time to see the results.
Adapted program memory read sub per data sheet to GCBasic syntax:
#chip 16f1783,8
#define USART_BAUD_RATE 9600
dir PortC.6 Out 'TX
Prog_Addr_Lo = 0x00
Prog_Addr_Hi = 0x80
Dim PROG_DATA_LO, PROG_DATA_HI As Word
Call ReadWord
HSerPrint "Hello"
HSerSend 10
HSerSend 13
HSerPrint PROG_DATA_LO
HSerSend 10
HSerSend 13
wait 3 s
Main:
Goto Main
sub ReadWord
; This code block will read 1 byte of user id
EEADRH = 0
EEADRL = PROG_Addr_LO
CFGS = 1
'EEPGD = 1
GIE = 0
RD = 1
NOP
NOP
GIE = 1
Prog_Data_Lo = EEDATL
Prog_Data_Hi = EEDATH
end sub
Method two uses the EECON1 Register and applies to the following in my sample:
PIC16F1825/9
Method three uses the NVMCON1 Register and applies to the following in my sample:
PIC16F18326
PIC16F18855
In addition the PIC18 family have a totally different address structure and would need different code again.
The older PIC16 Devices such as the PIC16F886 and the even older 16F690 have no reference to the USER ID in the datasheets.
Whilst there is no common method of accessing all devices it should be possible to use a script to determine which routine to use or throw a compiler error for devices that do not support USER ID.
I have been intending to learn the GCBasic scripting language for a while so this may be a good project to start on, though I can't guarantee support for all devices as I only have a handful that I can test on.
Cheers
Chris
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am busy creating a device independent library function to address this, your screenshots will be a great help in testing.
I see your IPE is out of date, the current version is 3.35 it may help to update it.
Cheers
Chris
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Looks like I am on the right track.
Taking a shotgun approach and dumping the first 16 bytes starting at 0x8000 I get the following from a 16F18855 (Xpress evaluation board).
The mapping from the data sheet is as follows:
; Address Function Read Write
; 8000h-8003h User IDs Yes Yes
; 8006h/8005h Device ID/Revision ID Yes No
; 8007h-800Bh Configuration Words 1 - 5 Yes No
I have not set a User Id as the xpress programer has no support that I can find, but location 8006, the Device ID, returns 306C which is the correct value for the PIC16f18855, and dumping the .hex file shows the config bytes as:
0A 000E 00 8C3F FF3F 9F3F FF1F FD3F A7
The first 3 fields are formating values and the last is the checksum.
the 5 words are the actual config swords stored in Little Endian format, so:
8C3F is the value 3F8C as seen at location 8007 above.
It is the wee hours of the morning here now but I will repeat the tests now with the 28 Pin Demo Board and the PICKit 3 tomorrow, so that I have full control of User ID etc. and can try several different devices.
Watch this space...
Cheers
Chris
Last edit: Chris Roper 2016-08-21
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It is definitely working properly on the PIC16F18855.
I set SQTP for Sequential Increment 2 Byte with the location set to User ID Memory and RAW Data.
The Blank chip read the User ID Fields as:
8000 : 3FFF
8001 : 3FFF
8002 : 3FFF
8003 : 3FFF
After first flash of the test program:
8000 : 0000
8001 : 3FFF
8002 : 3FFF
8003 : 3FFF
After second Flash:
8000 : 0001
8001 : 3FFF
8002 : 3FFF
8003 : 3FFF
Now to try and find Devices that use the other two formats so that I can be sure all 3 methods work and I will then submit the code to Even for possible inclusion in the next release.
Cheers
Chris
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have successfully tested on the 28 PIN PIC16F18855 and the 20 PIN PIC16F1619 Devices.
Trying to test with a 14 PIN PIC16LF1455 causes PICkit3 to complain about the device ID so I cannot complete that test at the moment.
The code has been released to Evan (not even) for further testing and with his approval I will send it to anyone willing to beta test it.
It only supports PIC16F Devices with the Enhanced Core, and no older PIC16F, 12F or 18F devices are supported in this release.
Cheers
Chris
Last edit: Chris Roper 2016-08-22
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It is now also working on all 18F devices, or should be I still need to try a larger sample to be sure, the scripts are in place to fail gracefully on unsupported Devices and return a Warning to the User.
Next stage is to document the use and build some examples.
Unfortunately I missed the 95.009 release but if anyone would like to test it please contact Evan or myself and we will get a copy to you.
Cheers
Chris
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
for one of my future projects (when time allows) i want to give a unique id to each chip, i have been playing around with the sqtp settings on my pickit 3 and have no problems getting this working.
what i would like to clarify is how would i go about reading these locations from within my code when the chip has been assigned a unique i.d after programming.
the user i.d memory locations for the chip used (pic16f1825) are 8000h-80003h, i am familiar with the usual reading/writing to eeprom from within my code for other uses but not really sure how i would go about the user i.d locations assuming it would be done diferently.
tony
so after attempting to read the correct location ( i assume) i dont seem to be getting anywhere so far
code put together from guessing
~~~
#chip 16f1825, 16
#config MCLRE = off
;USART settings
#define USART_BAUD_RATE 9600
#define USART_BL0CKING
TXCKSEL = 1
dir PORTA.0 out
dim uid as Word
wait 500 ms
;Main Program starts here
Do
Loop
~~~
again that is just a guess about how to go about this.
for now i am only using user id adress 8000h which i gather is a 2 byte or word sized location,
reading the programmed chip with my pickit 3 shows
address user id
8000 18F9
8001 3FFF
8002 3FFF
8003 3FFF
but the terminal output shows for location 8000 UID = 16128 which in hex is 3F00 so still some things need to be changed or altered but i dont know where to go from here.
tony
edit: upon cycling power it seems the value can change randomly so honestly i dont think it is indeed reading the stored user id at the location.
edit again: even tried setting the EEPGD and CFGS bits in the eecon reg but still i cannot read any location back that matches what i see in the pickit memory view window regardless, im thinking programread is not working
Last edit: tony golding 2016-08-20
well im stumped, i can see the user id location change value when i program it and the next sequential uid get loaded from the sqtp file via the pickit 3 memory view window but i just cant get any success with the programread function for ANY locations even in the main program space.
how can i read the user id locations?? answers on a postcard please.
tony
Hi Tony,
Try this:
I have not tested it on any hardware but it does generate the example code shown in the data sheet:
GCBasic generates:
My reasoning is that ProgramRead was setting EECON1,CFGS OFF where this code sets it ON.
and this code clears EEADRH whereas the origional code left it as 0x80.
Cheers
Chris
Last edit: Chris Roper 2016-08-20
hi chris,
thanks for this but its still not co-operating so something more going on i think.
just flashed the code to the chip with a serial in the idloc0 (8000h) and still getting random results.
the user id im seeing on the memory window view shows user id of A480 hex but on the terminal output its telling me the uid is 7200 (1C20 hex), then if i cycle the power that uid value then changes to 7168 (1C00 hex), somethings definately not right with this but as to what is the confusing part.
thanks anyway,
tony
Post your code please.
evan just using chris's code above, i just cant seem to get reliable consistent values back for the id location.
I totally trust Chris. He is good. I am sure he will sort.
How are you creating and programming the ID's?
I see that there are several threads on the topic and they differ according to the tool used.
I looked at MPLabX IPE and it has severa options there.
I have a working program memory write/read if tony wants to verify his setup? It erases/writes a whole row at a time, then reads the first address, which was good enough for me at the time. Code could definitely be improved upon.
I had a go at write and read of the user id, and no luck so far.
i am using my pickit 3 to add the serial to the device when programmed, i used the options in the advanced mode to generate an sqtp file to pull each serial from when programming a chip.
once i have programmed a chip i can use the read function of the pickit and see in the memory view window the user id written to location 0 in hex, the only issue seems to be reading it back in the chip via code not matching up with what would be expected, even after converting the returned decimal value from the uid to hex with the standrd windows pc calculator it does not seem to be correct
a bit strange to say the least.
edit: also i am using my pickit with mplabx ipe to program my chips.
Last edit: tony golding 2016-08-20
But which software?
I have PICKit3 Version 3.10 but it has no advanced option and the only referance to User ID in the documentation are the read failed and write failed error codes.
I was hoping to recreate your setup so that I could test the code.
cheers
Chris
Last edit: Chris Roper 2016-08-20
If you are using the SQTP tab in the Advanced options of IPEv3.35 can you let me know the settings, or beter yet a screenshot, so that I can set mine up to match?

Cheers
Chris
Last edit: Chris Roper 2016-08-20
I can read back the first byte of the user id now. If someone wants to spend the time to read more bytes etc. feel free. Attached screen shot of the IPE sqtp setup. Kind of a pain to download the hex and sqtp each and every time to see the results.
Adapted program memory read sub per data sheet to GCBasic syntax:
:)
Last edit: kent_twt4 2016-08-20
The 16f1783 only has Byte size user id's when looking at the IPE id window. Adjust accordingly. The sqtp was set in random mode, at 8000h, 2 bytes.
Last edit: kent_twt4 2016-08-21
Just ran through a sample of PIC16 Data Sheets and it appears there are 3 different ways of reading the ID depending on the actual device.
Method one uses the PMCON1 Register and applies to the following in my sample:
PIC16F1454/5/9
PIC16F1615/9
PIC16F1717/8/9
PIC16F1773/6
PIC16F1777/8/9
Method two uses the EECON1 Register and applies to the following in my sample:
PIC16F1825/9
Method three uses the NVMCON1 Register and applies to the following in my sample:
PIC16F18326
PIC16F18855
In addition the PIC18 family have a totally different address structure and would need different code again.
The older PIC16 Devices such as the PIC16F886 and the even older 16F690 have no reference to the USER ID in the datasheets.
Whilst there is no common method of accessing all devices it should be possible to use a script to determine which routine to use or throw a compiler error for devices that do not support USER ID.
I have been intending to learn the GCBasic scripting language for a while so this may be a good project to start on, though I can't guarantee support for all devices as I only have a handful that I can test on.
Cheers
Chris
sorry for the delay chris, just checked and my pickit is running under ipe v3,
added a couple of pics of sqtp page and main window that shows programmed id that wont read back correctly.
tony
Thanks Tony,
I am busy creating a device independent library function to address this, your screenshots will be a great help in testing.
I see your IPE is out of date, the current version is 3.35 it may help to update it.
Cheers
Chris
Looks like I am on the right track.
Taking a shotgun approach and dumping the first 16 bytes starting at 0x8000 I get the following from a 16F18855 (Xpress evaluation board).
The mapping from the data sheet is as follows:
And the result is:
I have not set a User Id as the xpress programer has no support that I can find, but location 8006, the Device ID, returns 306C which is the correct value for the PIC16f18855, and dumping the .hex file shows the config bytes as:
0A 000E 00 8C3F FF3F 9F3F FF1F FD3F A7
The first 3 fields are formating values and the last is the checksum.
the 5 words are the actual config swords stored in Little Endian format, so:
8C3F is the value 3F8C as seen at location 8007 above.
It is the wee hours of the morning here now but I will repeat the tests now with the 28 Pin Demo Board and the PICKit 3 tomorrow, so that I have full control of User ID etc. and can try several different devices.
Watch this space...
Cheers
Chris
Last edit: Chris Roper 2016-08-21
thanks chris, its good to see it starting to work out now and making some progress.
your efforts are much appreciated.
tony
UPDATE:
It is definitely working properly on the PIC16F18855.
I set SQTP for Sequential Increment 2 Byte with the location set to User ID Memory and RAW Data.
The Blank chip read the User ID Fields as:
8000 : 3FFF
8001 : 3FFF
8002 : 3FFF
8003 : 3FFF
After first flash of the test program:
8000 : 0000
8001 : 3FFF
8002 : 3FFF
8003 : 3FFF
After second Flash:
8000 : 0001
8001 : 3FFF
8002 : 3FFF
8003 : 3FFF
Now to try and find Devices that use the other two formats so that I can be sure all 3 methods work and I will then submit the code to Even for possible inclusion in the next release.
Cheers
Chris
I have successfully tested on the 28 PIN PIC16F18855 and the 20 PIN PIC16F1619 Devices.
Trying to test with a 14 PIN PIC16LF1455 causes PICkit3 to complain about the device ID so I cannot complete that test at the moment.
The code has been released to Evan (not even) for further testing and with his approval I will send it to anyone willing to beta test it.
It only supports PIC16F Devices with the Enhanced Core, and no older PIC16F, 12F or 18F devices are supported in this release.
Cheers
Chris
Last edit: Chris Roper 2016-08-22
thats good to hear, i only need to implement this for a few projects using the 16f1825/29.
tony
It is now also working on all 18F devices, or should be I still need to try a larger sample to be sure, the scripts are in place to fail gracefully on unsupported Devices and return a Warning to the User.
Next stage is to document the use and build some examples.
Unfortunately I missed the 95.009 release but if anyone would like to test it please contact Evan or myself and we will get a copy to you.
Cheers
Chris