On some large projects it is required that some data or variables can be changed on line (configuration or parameter variables) and stored so that after the device is turned off it can keep using the last configuration.
This project describes a way to store data that will be changed some time when the device is running, even when the device is turned off, on each run the last used data can be loaded.
For this we will use the EmEEPROM block.
This PSOC block emulates a EEPROM (electrically Erasable Programmable Read-Only Memory) by using part of the Flash memory available which sometimes could be better than a standalone device in available storage capacity.
Step 1First of all we need the emEEPROM block on the top Design:
There is nothing to configure but the instance name. Now to the main.c.
Step 2For the EEMPROM to work we will need three arrays a temporary RAM array, the EEPROM Array, and a User array. The RAM temporary array helps translate the data form user array to EEPROM array or backwards, the EEPROM array is a static array this means it is visible to every single function this array holds the stored data.
And the user array is the array that will hold the data that was read or will be or was written to the EEPROM:
#include <project.h>
int VariableA, VariableB; // User Variables
//EEPROM related variables and arrays
cystatus status;
uint8 ram_array[4]; // temporary RAM array size in bytes (8bits) each
static const uint8 CYCODE eepromArray[]= { 0,0,0,0 };
// eeprom array size in bytes (8bits) each
uint16 user_array[2];
//User array is half size because it is 16bit array to store larger numbers
Step 3Then we need a function to translate the data between arrays, this function needs to be called with two parameters a destination and a source for transferring the data. (This is important because we have two kinds of variables 8bit and 16bit).
//EEPROM transfer function destination - source
void user_eeprom(uint8 * dest, uint8 * src,uint8 size){// size - size of the src and dest in bytes.
uint8 i=0;
for(i=0;i<size;i++){ *(dest+i) = *(src + i); }
}
Step 4Now the function that actually stores the data to the EEMPROM. The store parameters function reads the variable data and loads it into the user array then using the transfer function user_eeprom() it is then transferred to the ram Array. Then finally with the API from the EEMPROM block we write the data from the RAM array to the EEMPROM.
void Storeparam(){
user_array[0] = VariableA;
user_array[1] = VariableB;
user_eeprom((uint8*)&ram_array,(uint8*)(&user_array), 4);
status = EEPROM_Write(ram_array,eepromArray,4);
}
Now we will add the initialization routine (I will split it for easier explaining)
void Init(){//First run routine
EEPROM_Start();
CyDelay(100);
Not much to explain there start the emEEMPROM.
Step 5Now we have to check if the device was just programmed (First Run) or it has stored values before.
In case it is the First Run we need to write some default values. For this we check one item of the EEPROM array. So if this is part of the array is empty we need to load the default values to the user array, then transfer them to the RAM array and finally write them to the EEPROM array.
Then when the Write process is successful we run the init routine again to load the variables from the EmEEPROM. (This will be the 2nd run.)
if (*(volatile uint8 *) &eepromArray[0] == 0){
user_array[0]= 1; //Variable A Def value
user_array[1]= 1; //Variable B Def value
user_eeprom((uint8*)&ram_array,(uint8*)(&user_array), 4);
status = EEPROM_Write(ram_array,eepromArray,4);
if (CYRET_SUCCESS != status){}Init();
//after writing the values run the init Routine again to load values
}
If the eemprom array has any thing stored then we just read the values from the eemprom array and transfer them to the user array.
else{//If there is anything stored (2nd or later run) just load the values to the variables
user_eeprom((uint8*)(&user_array), (uint8*)&eepromArray, 4);
VariableA=user_array[0];
VariableB=user_array[1];
}
Step 6Then for easy display I will use the I2C LCD commands for further I2C LCD reference check out this project.
I2C_Start();
I2C_LCD_Start();
CyDelay(1200u);
I2C_LCD_Position(0u, 4u);
I2C_LCD_PrintString("emEEPROM DEMO");
I2C_LCD_Position(2u, 2u);I2C_LCD_PrintString("Variable A");
I2C_LCD_Position(3u, 2u);I2C_LCD_PrintString("Variable B");
}
The main routine doesn't have much to it, after running the init routine, I am changing the current variable values and then storing them (this way every time the PSOC is reset, the values are increased again.
int main()
{
CyGlobalIntEnable; /* Enable global interrupts. */
Init();
VariableB=VariableB+2;
Storeparam();
for(;;)
{
/* Place your application code here. */
}
}
Comments