// Program FL_EE.C, Sourceboost C, PIC16F887, ICD2 // // Illustrates how to write to and read from flash EEPROM memory. Note // that this is 14-bits wide. // // The program is simplified to log data by repeatedly calling a stub make_meas // which generates four words and saving these to flash EEPROM beginning at // location 0x1000. Each of these four words is displayed on the serial LCD // using a 'M' (meas) delimiter. // // These four word blocks of data are sequentially written to EEPROM by reading // a 16 word block, inserting the four word block and then programming the 16 // word block. // // The program memory is then displayed by reading four word blocks. Note that // the delimiter 'D' is used to indicate the "dump" code is being executed. // // copyright, Peter H. Anderson, Baltimore, MD, July, '09 #include <system.h> #include <icd2.h> #include <string.h> #include <stdio.h> #pragma DATA 0x2007, 0x28e4 #pragma DATA 0x2008, 0x3eff #pragma CLOCK_FREQ 4000000 #define NEGATIVE 1 #define POSITIVE 0 #define TRUE !0 #define FALSE 0 //#define DEBUG typedef unsigned char byte; void log_data(void); void dump_data(void); void make_meas(int *data, byte num_words); void write_flash_eeprom(int write_address, int *data, byte num_words); void read_flash_eeprom(int read_address, int *data, byte num_words); void print_str(char *s); void print_ch(char ch); void print_ints(int *d, byte num, char ch); void asynch_setup(void); void main(void) { asynch_setup(); while(1) { log_data(); dump_data(); } } void log_data(void) { byte n; int data[16]; int write_address = 0x1000; for (n=0; n<25; n++) // 100 words { make_meas(data, 4); write_flash_eeprom(write_address, data, 4); write_address += 4; } } void dump_data(void) { byte m, n; int data[16], read_address = 0x1000; for (n=0; n<25; n++) { read_flash_eeprom(read_address, data, 4); print_ints(data, 4, 'D'); read_address += 4; } } void write_flash_eeprom(int write_address, int *data, byte num_bytes) { int base_address, save_buffer[16]; byte n, offset; base_address = write_address & 0xfff0; // zero the least signif 4 bits offset = write_address & 0x000f; eecon1.EEPGD = 1; // flash data read_flash_eeprom(base_address, save_buffer, 16); // fetch what is in the 16 byte block // print_ints(save_buffer, 16, 'W'); // now insert the new data for (n=0; n<num_bytes; n++) { save_buffer[n+offset] = data[n]; } eeadrh = (byte) (base_address >> 8); eeadr = (byte) (base_address & 0xff); for (n=0; n<16; n++) { eedath = save_buffer[n] >> 8; eedata = save_buffer[n] & 0xff; eecon1.EEPGD = 1; eecon1.WREN = 1; // disable interrupts eecon2 = 0x55; eecon2 = 0xaa; eecon1.WR = 1; asm { NOP NOP } eecon1.WREN = 0; // okay to enable ints ++eeadr; } } void read_flash_eeprom(int read_address, int *data, byte num_words) { byte n, h, l; for (n=0; n<num_words; n++) { eeadrh = (byte) (read_address >> 8); eeadr = (byte) (read_address & 0xff); eecon1.EEPGD = 1; // flash data eecon1.RD = 1; asm { NOP NOP NOP NOP NOP NOP } h = eedath; l = eedata; data[n] = (((int) h) << 8) | l; ++read_address; } } void make_meas(int *data, byte num_words) { static byte m = 0; byte n; for (n=0; n<num_words; n++) { data[n] = m * 100 + 4 * n; } ++m; m = (m==20) ? 0 : m; print_ints(data, 4, 'M'); delay_s(2); } void asynch_setup(void) { // for UART, see Manual pages beginning at page 151 trisc.7 = 1; trisc.6 = 1; // TX rcsta.SPEN = 1; // enable serial port txsta.TXEN = 1; // enable transmitter txsta.SYNC = 0; // asynchronous txsta.BRGH = 1; spbrg = 25; // 9600 baud at 4.0 MHz } void print_ints(int *d, byte num, char ch) { byte i, j; char s[20]; strcpy(s, "?f"); print_str(s); for (i=0; i<num; i++) { sprintf(s, "%u", d[i]); print_str(s); print_ch(ch); // distictive delimiter if (((i % 4) == 0) && (i!=0)) { strcpy(s, "?n"); print_str(s); } } delay_s(1); } void print_str(char *s) { while(*s != '\0') { txreg = *s; while(txsta.TRMT == 0) { } ++s; } } void print_ch(char ch) { txreg = ch; while(txsta.TRMT == 0) { } }