Skip to content

Instantly share code, notes, and snippets.

@BDeliers
Last active June 15, 2021 11:07
Show Gist options
  • Save BDeliers/f27d02469b90f8718b33ef9049a053ee to your computer and use it in GitHub Desktop.
Save BDeliers/f27d02469b90f8718b33ef9049a053ee to your computer and use it in GitHub Desktop.
Self-measure supply voltage from PIC16F153xx
// DIA addresses
#define TSLR2 0x8113
#define FVRA1X 0x8118
#define FVRA2X 0x8119
// Read from Device Information Area
uint16_t DIARead(uint16_t addr) {
// Access DIA
NVMCON1 = 0b01000000;
// Set address
NVMADRH = (addr >> 8) & 0xFF;
NVMADRL = addr & 0xFF;
// Start reading
NVMCON1bits.RD = 1;
// Wait for reading end
while (NVMCON1bits.RD);
// Return data
return (NVMDATH << 8) | NVMDATL;
}
/* MEASURE VCC */
// FVR enabled, Temperature sensor disabled, low range, comparator FVR disabled, ADC FVR buffer 1024mV
FVRCON = 0b10000001;
// Wait for FVR to be ready
while (!FVRCONbits.FVRRDY);
// ADC source is FVR buffer 1, conversion stopped, ADC enabled
ADCON0 = 0b11111001;
// Result right aligned, clock is ADCRC, ref is VCC
ADCON1 = 0b10110000;
// No auto conversion
ADACT = 0;
// Required for ADC value settling
__delay_us(200);
// Start conversion
ADCON0bits.GO = 1;
// Wait for conversion end
while (ADCON0bits.GO);
// Calculate
uint16_t adc = (ADRESH << 8) | ADRESL;
// FVR real value
uint16_t fvrCalib1 = DIARead(FVRA1X);
// Vcc = Vfvr * ADC dynamic / ADC value
float voltage = (fvrCalib1 * 1024.0) / adc;
//uint16_t voltage = ((8192 / adc) * 1024) / 8;
printf("\nSupply voltage %fmV\r", voltage);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment