PIC12F1501 - Help with writing & reading flash memory (Posting again)
I couldnt find my first post on the same topic in the forum and therefore, I am posting this again.
For my project, using PIC12F1501, I am using NCO peripheral to pulse my circuit and I will be operating it at 2 modes of operation, namely, Calibration mode & Normal operation mode. The underlying circuit operates best at a particular frequency and to find out that particular frequency, I need to have a frequency sweep once in lifetime, store that frequency value in flash and every other time, it operates in normal operation where it fetches the operating frequency from the flash. The switch between calibration and normal operation mode is done by a Digital input. Calibration mode:-
Sweep the NCO frequency from 800kHz to 999kHz at a duty cycle of about 50% using PFM mode
- Find the best operating point (using AN pins)
- Store values in Flash. Normal operation:-
Read the values from flash
- Initialize NCO frequency values with the read variables
- Do other functions.
As mentioned before, the calibraiton is done only once and the value has to be stored in a particular location in flash. Every other time, when the circuit is (re)started, the normal operation mode reads the flash and initializes the NCO accordingly.
I tried using the routines given in memory.c but the FLASH_WriteWord() requires me to declare a variable unit16_t ramBuf which already takes 32 bytes and with other declarations, i am running out of space. I tried to modify this write word as below, but still i wasnt able to get it working.
Could someone help me to write 2 16bit data in the flash only during calibration and can be fetched while normal operation mode.
/* Flash Memory */ memory.c
#define NCOFreq_addr 0x0380
/* Definitions for RAM Memory Allocation */
uint16_t ramBuf[WRITE_FLASH_BLOCKSIZE]; // Needed for writing block
/* Re-using ramBuf */
#define StartFreq ramBuf
#define PWMSweep ramBuf
#define VGain_Freq ramBuf
#define FreqStep ramBuf
#define Calib_DONE ramBuf
/* Constants initialization */
StartFreq = 65529; // start at 999 kHz
FreqStep = 655; // Freq step of 10 kHz
/* Supporting variables */
PWMSweep = StartFreq;
VGain_Freq = 0;
// Find the maximum ADC value in a given frequency sweep and write the value for NCO in Flash
NCO1INCH = PWMSweep >> 8; // Load values to NCO register
NCO1INCL = PWMSweep & 0xFF;
if ( ADC_GetConversion(3) <= VGain_Freq)
PWMValue = PWMSweep;
PWMValue = ADC_GetConversion(0);
VGain_Freq = ADC_GetConversion(3);
PWMSweep = PWMSweep - FreqStep;
FLASH_WriteWord(NCOFreq_addr, ramBuf, PWMValue); // Write Values to Flash
Calib_DONE = 0x01; // Set this so that the calibration is done only once.
PWMValue = FLASH_ReadWord(NCOFreq_addr);
PWMValue = FLASH_ReadWord(NCOFreq_addr+1);
NCO1INCH = PWMValue >> 8;
NCO1INCL = PWMValue & 0xFF;
Freq_read = 0x01; // Set this when the frequency is read once.
// initialize the device
// When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
// Use the following macros to:
// Enable the Global Interrupts
// Enable the Peripheral Interrupts
// Disable the Global Interrupts
// Disable the Peripheral Interrupts
Calib_DONE = 0x00;
Freq_read = 0x00;
if ( EN_CALIB_GetValue() == 0) // Calibration mode
if ( (Calib_DONE & 0x01) != 1) // If calibration is not done, call calibrate function.
else // Normal operation mode
if ((Freq_read & 0x01) != 1) // If frequency is not read, call calibrate function.
// Other operations
// Add your application code
void FLASH_WriteWord(uint16_t flashAddr, uint16_t *ramBuf, uint16_t *word)
uint16_t blockStartAddr = (uint16_t)(flashAddr & ((END_FLASH-1) ^ (ERASE_FLASH_BLOCKSIZE-1)));
uint8_t offset = (uint8_t)(flashAddr & (ERASE_FLASH_BLOCKSIZE-1));
// Entire row will be erased, read and save the existing data
for (i=0; i<ERASE_FLASH_BLOCKSIZE; i++)
ramBuf[i] = FLASH_ReadWord((blockStartAddr+i));
// Write at offset
ramBuf[offset] = word;
ramBuf[offset+1] = word;
// Writes ramBuf to current block