News:

Let's find out together what makes a PIC Tick!

Main Menu

Reading the PIC18F27Q83 Device Information Area

Started by kcsl, Jul 15, 2025, 12:01 PM

Previous topic - Next topic

kcsl

I want to use the 18F27Q83's internal temperature sensor, but to do the conversion you need to read a couple of values out of the Device Information Area. This area seems to be mapped into address space $2C0000 to $2C003F and Ptr16 says the address is out of range - I knew it wouldn't be that easy.

Does anybody have a bit of code that can read values out of this area please ?

Regards,
Joe
There's no room for optimism in software or hardware engineering.

RGV250

Hi,
Looking at the datasheet you select the ADC channel by ADPCH (page 933) and then read as an analog input. I think you need %xx111100 for the temperature indicator.

Regards,
Bob

kcsl

Quote from: RGV250 on Jul 15, 2025, 01:23 PMHi,
Looking at the datasheet you select the ADC channel by ADPCH (page 933) and then read as an analog input. I think you need %xx111100 for the temperature indicator.

Regards,
Bob

Hi Bob,
Yes, I can read the ADC no problem, but to turn that ADC value into a temperature you need to read some additional factory programmed trim values from the DIA.
Section 42.2 gives the calculation.

Regards,
Joe

There's no room for optimism in software or hardware engineering.

RGV250

Hi Joe,
Google this, "reading DIA registers 18F27Q83"
It goes on to say they are not directly accessible and need to be read as EEPROM. More than my brain cell can cope with at the moment.

Bob

RGV250

Found this.
Quote// Assuming a C-like syntax and a suitable EEPROM library

// Define DIA addresses (refer to datasheet for specific addresses)
#define DIA_TEMP_INDICATOR  0x000 // Example address
#define DIA_UNIQUE_ID       0x010 // Example address

// Function to read from DIA
unsigned char read_DIA(unsigned int address) {
  // Set up EEPROM for read
  EECON1bits.EEPGD = 0; // Access data EEPROM
  EECON1bits.CFGS = 0;  // Access data EEPROM
  EECON1bits.RD = 0;    // Clear the read bit

  FSR0 = address;      // Load the DIA address into FSR0
  EECON1bits.RD = 1;     // Initiate the read operation
  while(EECON1bits.RD == 1); // Wait for read to complete
  return EEDATA;       // Return the read data
}

// Example usage:
unsigned char temperature = read_DIA(DIA_TEMP_INDICATOR);
unsigned char unique_id[8];
for(int i=0; i<8; i++){
    unique_id = read_DIA(DIA_UNIQUE_ID + i);
}

Bob

kcsl

Quote from: RGV250 on Jul 15, 2025, 01:55 PMFound this.
Quote// Assuming a C-like syntax and a suitable EEPROM library

// Define DIA addresses (refer to datasheet for specific addresses)
#define DIA_TEMP_INDICATOR  0x000 // Example address
#define DIA_UNIQUE_ID       0x010 // Example address

// Function to read from DIA
unsigned char read_DIA(unsigned int address) {
  // Set up EEPROM for read
  EECON1bits.EEPGD = 0; // Access data EEPROM
  EECON1bits.CFGS = 0;  // Access data EEPROM
  EECON1bits.RD = 0;    // Clear the read bit

  FSR0 = address;      // Load the DIA address into FSR0
  EECON1bits.RD = 1;     // Initiate the read operation
  while(EECON1bits.RD == 1); // Wait for read to complete
  return EEDATA;       // Return the read data
}

// Example usage:
unsigned char temperature = read_DIA(DIA_TEMP_INDICATOR);
unsigned char unique_id[8];
for(int i=0; i<8; i++){
    unique_id = read_DIA(DIA_UNIQUE_ID + i);
}

Bob

When I searched Google, I got this:

The Device Information Area (DIA) of the PIC18F27Q83 microcontroller stores factory-calibrated data, fixed voltage reference measurements, and a unique identifier. To access this information, you'll need to use the DIA addresses specified in the device's datasheet. The DIA is not directly readable via normal memory access methods; it requires specific instructions or functions provided by the Microchip development tools.

Regards,
Joe
There's no room for optimism in software or hardware engineering.

RGV250

Hi Joe,
Did you use the phrase I put between the quotes for your search, I got different results until I changed it to that.

Bob

top204

#7
If the DIA part of Flash memory, is just a piece of flash at a higher address, then the cPtr24 command should read it, because the address' are 24-bits in size. For example:

$define cTSLR1_Address $2C0024           ' Gain
$define cTSLR2_Address $2C0026           ' Temperature indicator ADC reading at 90°C (low range setting)
$define cTSLR3_Address $2C0028           ' Offset (low range setting)
'
' Create global variables
'
    Dim ADC_wGain   As Word
    Dim ADC_w90Deg  As Word
    Dim ADC_wOffset As Word    

'-----------------------------------------------------------------------------------------------------------
' The main program starts here
'
Main:
    ADC_wGain   = cPtr24(cTSLR1_Address) 
    ADC_w90Deg  = cPtr24(cTSLR2_Address)
    ADC_wOffset = cPtr24(cTSLR3_Address)

But is is unknown what orientation they are in, within flash. So the high and low bytes may need to be re-arranged.

JonW

If this is similar to the 16F15376, then here are some flash read/write procs in a library (inc file)

Just adjust the resisters and save as a ***.inc and add the include

Include "P16F15376NVM.INC"              ' NVM READ AND WRITE LIB


' P16F15376NVM.INC
' JON WALKER ELECIUM LTD MAR 2013
'---------------
' CAN READ AND WRITE TO ANY SINGLE REGISTER IN THE DFM
' CAN READ THE DIA FOR CONSTANTS ETC
' EXAMPLE OF USE

' VAR = FLASHREAD(ADDRESS)          ' READS THE DFM AREA
' VAR = FLASHREADCFG(ADDRESS)       ' READS THE DIA AREA
' FLASHWRITE(ADDRESS, DATA)         ' WRITES TO A SINGLE LOCATION IN DFM

'----------------------------------------------------------------------------------------------
'----------------------------------------------------------------------------------------------
'NVMCONTROL

SYMBOL  NVMREGS     = NVMCON1.6             ' 1 = DIA, 0 = PFM
SYMBOL  NVMLWLO     = NVMCON1.5             ' LOAD WRITE LATCHES ONLY
SYMBOL  NVMFREE     = NVMCON1.4             ' PROGRAM FLASH MEMORY ERASE ENABLE
SYMBOL  NVMWRERR    = NVMCON1.3             ' PROGRAM/ERASE ERROR FLAG
SYMBOL  NVMWREN     = NVMCON1.2             ' PROGRAM/ERASE ENABLE BIT
SYMBOL  NVMWR       = NVMCON1.1             ' 1 = INITIATES A WRITE
SYMBOL  NVMRD       = NVMCON1.0             ' 1 = INITIATES A READ ON THE NEXT CYCLE

'NVM PROCS FOR 16F15376

(********************************************************************************************
* Title     :  FLASHREADMEM                                                                 *
* Input     :  FLASH ADDRESS                                                                *
* Output    :  FLASH CONTENT                                                                *
* Notes     :  READS FLASH MEM                                                              *
********************************************************************************************)
Proc FLASHREAD(ADDR As WORD),WORD
      NVMREGS = 0                             ' POINT TO FLASH
      NVMADRL = ADDR.Byte0                    ' LOAD THE POINTERS
      NVMADRH = ADDR.Byte1
      NVMRD = 1                               ' START THE READ
      NOP
      RESULT.HIGHBYTE = NVMDATH               ' RETURN THE DATA
      RESULT.LOWBYTE = NVMDATL
      RESULT = RESULT & %0011111111111111
EndProc

(********************************************************************************************
* Title     :  READFLASHCFG   MMMMMM                                                        *
* Input     :  FLASH ADDRESS                                                                *
* Output    :  FLASH CONTENT                                                                *
* Notes     :  READS DIA (CONFIG) AREA                                                      *
********************************************************************************************)
Proc FLASHREADCFG(ADDR As WORD),WORD
      NVMREGS = 1                             ' POINT TO CONFIG
      NVMADRL = ADDR.Byte0                    ' LOAD THE POINTERS
      NVMADRH = ADDR.Byte1
      NVMRD = 1                               ' START THE READ
      NOP
      RESULT.HIGHBYTE = NVMDATH               ' RETURN THE DATA
      RESULT.LOWBYTE = NVMDATL
EndProc

(********************************************************************************************
* Title     :  UNLOCKDFM (UNLOCK THE DATA FLASH)                                            *
* Input     :  FLASH ADDRESS                                                                *
* Output    :  FLASH CONTENT                                                                *
* Notes     :  26/27K42                                                                     *
********************************************************************************************)
Proc UNLOCKDFM()
        NVMCON2 = $55                         ' Required Writes
        NVMCON2 = $AA                         ' Required Wrtits
        NVMWR = 1                             ' Set WRITE CONTROL BIT
        NOP
        NOP
EndProc

(********************************************************************************************
* Title     :  FLASHWRITE                                                                   *
* Input     :  FLASH ADDRESS, BYTE TO WRITE                                                 *
* Output    :  NONE                                                                         *
* Notes     :  UPDATE 1 BYTE IN DFM (CAN WRITE TO ANY LOCATION)                             *
*********************************************************************************************)
Proc FLASHWRITE(ADDR As WORD, B2LOAD As WORD)

     Dim b_ROWs          As word              ' NEED A TEMPORY BYTE TO STORE THE ADDR.BYTE0
     DIM b_BYTE          as byte
     DIM b_LDL1          as byte
     Dim b_FLASH[32]     as word

     B_ROWs = (ADDR/32)                       ' GET THE 32 BYTE BOUNDARY ROW
     b_rows = b_rows * 32                     ' GET START ADDRESS
     b_byte = addr - (b_rows)                 ' GET BYTE INDEX TO REPLACE


     FOR B_LDL1 = 0 to 31                     ' READ FLASH INTO RAM
         B_FLASH[B_LDL1] = FLASHREAD(B_ROWs + B_LDL1)
     Next

     B_FLASH[B_BYTE] = B2LOAD                 ' UPDATE THE BYTE TO CHANGE

     ERASEROW(B_ROWs)                         ' ERASE THE 32 BYTE BLOCK (ROW)

     FOR B_LDL1 = 0 to 30                     ' RELOAD LATCHES
        LOADLATCH(B_ROWS,B_FLASH[B_LDL1],1)
        INC B_ROWS
     Next
        LOADLATCH(B_ROWS,B_FLASH[31],0)       ' FINAL LATCH AND WRITE
     WHILE NVMWR = 1:Wend                     ' WAIT FOR WRITE TO OCCUR IF IN A FAST LOOP
     NVMWREN = 0                              ' DISABLE WRITES
EndProc

(********************************************************************************************
* Title     :  LOADLATCH                                                                    *
* Input     :  FLASH ADDRESS, WORD TO LOAD, LATCH OR WRITE                                  *
* Output    :  NONE                                                                         *
* Notes     :  UPDATE 1 BYTE IN DFM (CAN WRITE TO ANY LOCATION)                             *
*********************************************************************************************)
proc LOADLATCH(ADDR AS WORD,DAT AS WORD, LATCH AS BIT)
        dim  b_GIESTORE AS BIT

        b_GIESTORE = INTCON.7
        NVMDATH = DAT.HIGHBYTE
        NVMDATL = DAT.LOWBYTE
        NVMADRH = ADDR.HIGHBYTE
        NVMADRL = ADDR.LOWBYTE

        NVMREGS = 0
        NVMLWLO = LATCH
        NVMFREE = 0
        NVMWREN = 1
        NOP
        UNLOCKDFM()
        INTCON.7 = b_GIESTORE    ' RETURN INT STATUS
EndProc

(********************************************************************************************
* Title     :  ERASEROW                                                                     *
* Input     :  FLASH ADDRESS                                                                *
* Output    :  NONE                                                                         *
* Notes     :  ERASES 32BYTE ROW AT ADDR                                                    *
*********************************************************************************************)
Proc   ERASEROW(ADDR As word)   ' KEEP THIS PROC SEPERATE SO WE CAN ERASE ANY 64-BYTE BLOCK

       NVMADRL = ADDR.Byte0
       NVMADRH = ADDR.Byte1

       NVMREGS = 0              ' ACCESS FLASH MEMORY
       NVMWREN = 1              ' ENABLE WRITE TO MEM
       NVMFREE = 1              ' ERASE BLOCK
       UNLOCKDFM()              ' UNLOCK DFM
       Nop                      ' REQUIRED
       WHILE NVMFREE = 1:WEND
       NVMWREN = 0              ' DISABLE WRITE TO MEM

EndProc



Example Calls

'TEMP MODULE AND ADC VREF VALUES
Dim VREF1X                           As Word       ; USE FLASHREADCFG TO ETRACT DATA FROM DIA AREA
Dim VREF2X                           As Word
dim VREF4X                           AS WORD
Dim T90H                             As Word




'read DIA
        VREF1X = FLASHREADCFG($8118):VREF2X = FLASHREADCFG($8119)
        VREF4X = FLASHREADCFG($811A):T90H = FLASHREADCFG($8116)

'read FLASH
        DEST_REG = FLASHREAD(FLASH_REG)       ' READ THE FLASH

'WRITE FLASH

        FLASHWRITE(DEST_REG,DATA)                        ; STORE THE DATA IN DEST_REG LOCATION (14 BITS MAX)