PIC16F18346には、電源を切っても保存内容が消えない不揮発性のデータEEPROMが256 バイトあります。 マイコンを使用する環境によりその初期設定値など変更しなければならないときには非常にありがたいメモリです。しかし、その読み書きは多少複雑です。また、書込みには通常のRAMより時間がかかります。データEEPROMに保存されたデータを読み出すには、以下の手順が必要です。
データEEPROMへデータを書込むには、以下の手順が必要です。
書き込みサイクルが完了すると、ハードウェアによって
これらの手順は、XC8のライブラリにすでに設定されているため、実際のプログラムでは、
関数を使用すれば目的を達成することができます。また、PICへのプログラム書き込み時に、EEPROMに初期値をセットするには、XC8のライブラリに設定されているマクロ命令を使用します。
かっこ内に、8ビット値を8個指定します。例のように、初めの1バイトしか使用しない場合にでも、8個全てをパラメータとして指定します。 この値が、EEPROMの先頭アドレスから順にセットされます。この命令を32個並べることで、256アドレス全てに、データをプリセットすることができます。
データEEPROMに関連するに関連するレジスターを一覧で説明します。
| レジスタ | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
|---|---|---|---|---|---|---|---|---|
| INTCON | GIE | PEIE | - | - | - | - | - | INTEDG |
| PIE2 | TMR6IE | C2IE | C1IE | NVMIE | SSP2IE | BLC2IE | TMR4IE | NCO1IE |
| PIR2 | TMR6IF | C2IF | C1IF | NVMIF | SSP2IF | BLC2IF | TMR4IF | NCO1IF |
| NVMADRH | - | NVM アドレス< 14 - 8 > | ||||||
| NVMADRL | NVM アドレス< 7 - 0 > | |||||||
| NVMDATH | - | - | NVM データ< 13 - 8 > | |||||
| NVMDATL | NVM データ< 7 - 0 > | |||||||
| NVMCON1 | - | NVMREGS | LWLO | FREE | WRERR | WREN | WR | RD |
| NVMCON2 | EEPROM 制御レジスタ2 ( 物理レジスタではない) | |||||||
| レジスタ | BIT | 名 | 説明 | 1 | 0 |
|---|---|---|---|---|---|
| INTCON | 7 | GIE | インタラプトを使用許可 | 許可 | 不 |
| 6 | PEIE | ペリフェラルインタラプトを使用許可 | 許可 | 不 | |
| PIR2 | 4 | NVMIF | EE書き込み完了フラグ | 完了 | 待ち |
| PIE2 | 4 | EEIE | インタラプトを使用許可 | 許可 | 不 |
| NVMADRL | 7-0 | EEPROM アドレスレジスタ | - | - | |
| NVMADRH | 14-8 | EEPROM アドレスは、0x70 | - | - | |
| NVMCON1 | 7 | - | - | ||
| 6 | NVMREGS | データEEPROMにアクセスするには 1 にセット | Data | Prgm | |
| 5 | LWLO | Progrm PROMにアクセスするに使用 | ー | ー | |
| 4 | FREE | Progrm PROMにアクセスするに使用 | 許可 | 禁止 | |
| 3 | WRERR | エラーフラグ ビット | エラー | 完了 | |
| 2 | WREN | データEEPROM 書き込みイネーブルビット | 許可 | 禁止 | |
| 1 | WR | 書き込みサイクル制御ビット (リセットはできない) | 開始 | 完了 | |
| 0 | RD | 読み出し開始制御ビット (リセットはできない) | 開始 | 待機 |
PushSWを押した回数をLEDでカウントするプログラムです。SWが押されるたびにカウント数をdataEEPROMに書込み、LEDにも反映します。 DataEEPROMに毎回保存しているため、電源を切ってから再び電源を供給したときには、前のカウント数からスタートします。まお、プログラム直後のカウント数は、「3」に設定してあります。
<プログラム>
/*************************************
* File: EE DataPROM sample
* System ClockはConfigで内部1MHzに設定
* RA3 のSWが押されたらEEPROMデータを+1する
* RC0-RC3 にEE_POMデータを表示
* PIC16F18346
* Created on July 22, 2020, 2:37 PM
**************************************/
#include <xc.h>
#define _XTAL_FREQ 1000000 // delay_ms(x) のための定義
#pragma config FEXTOSC = OFF,RSTOSC = HFINT1 // HFINTOSC (1MHz)
#pragma config CLKOUTEN = OFF,CSWEN = OFF,FCMEN = OFF
#pragma config MCLRE = OFF,PWRTE = OFF,WDTE = OFF,LPBOREN = OFF
#pragma config BOREN = OFF,BORV = LOW,PPS1WAY = OFF,STVREN = ON
#pragma config DEBUG = OFF
#pragma config WRT = OFF,LVP = OFF,CP = OFF,CPD = OFF
#define LEDs LATC
#define pushSW PORTAbits.RA3
//------ プログラム直後のEEPROMの初期データ --------
__EEPROM_DATA(3,0,0,0,0,0,0,0);
//---------------------------------------------
void main(void) {
char data;
LATC = 0;
TRISC = 0b110000; // RC0-RC3を出力に設定
TRISA = 0b111111; // PortAを入力に設定
ANSELA = 0; // 全てのpinをデジタルに設定
ANSELC = 0;
__delay_ms(100); // 安定を待つ
while(1){
data = eeprom_read(0); // EEPROM 0番地 読み込み
LEDs = data; // LEDを点灯
while(!pushSW); // SW ON/OFF を待つ
__delay_ms(5);
while(pushSW);
__delay_ms(5);
data++; // LEDのカウントを1増やす
eeprom_write(0, data); // EEPROM 0番地 書込み
}
}
//*************************************************
// コンパイラがEEPROM読み書きをサポートしていないときは
// 以下の関数を使用する
//*************************************************
//unsigned char eeprom_readbyte(unsigned char address)
//{
// NVMADRH = 0x70; // アドレスをセット
// NVMADRL = address; // アドレスをセット
// NVMCON1bits.NVMREGS = 1; // EEPROM を選ぶ
// NVMCON1bits.RD = 1; // 読み出しの開始
// while(NVMCON1bits.RD == 1); // 読み出し終了を待つ
// return NVMDATL; // データを持って復帰
//}
//void eeprom_writebyte(unsigned char address, unsigned char data)
//{
// char GIE_on;
// NVMADRH = 0x70; // アドレスをセット
// NVMADRL = address; // アドレスをセット
// NVMDATL = data; // データをレジスタに書き込む
// NVMCON1bits.NVMREGS = 1; // EEPROM を選ぶ
// NVMCON1bits.WREN = 1; // EEPROM書き込みを有効に
// GIE_on = INTCONbits.GIE; // 割込環境を待避
// INTCONbits.GIE = 0; // 割込みを禁止
// NVMCON2 = 0x55; // EEPROM書き込み暗号を書く
// NVMCON2 = 0xAA; // EEPROM書き込み暗号を書く
// NVMCON1bits.WR = 1; // 書き込みの開始
// if(GIE_on)INTCONbits.GIE = 1; // 割込み環境を復旧
// while(PIR2bits.NVMIF == 0); // 書き込み終了を待つ
// PIR2bits.NVMIF = 0; // NVMIF bit クリア
// NVMCON1bits.WREN = 0; // 以降は書き込みを禁止する
//}