18F14K50には、電源を切っても保存内容が消えない不揮発性のデータEEPROMが256 バイトあります。 マイコンを使用する環境によりその初期設定値など変更しなければならないときには非常にありがたいメモリです。しかし、その読み書きは多少複雑です。また、書込みには通常のRAMより時間がかかります。データEEPROMに保存されたデータを読み出すには、以下の手順が必要です。
データEEPROMへデータを書込むには、以下の手順が必要です。
書き込みサイクルが完了すると、ハードウェアによって
これらの手順を、以下の関数にまとめました、実際のプログラムは例を参考にしてください。
関数を使用すれば目的を達成することができます。また、PICへのプログラム書き込み時に、EEPROMに初期値をセットするには、XC8のライブラリに設定されているマクロ命令を使用します。
かっこ内に、8ビット値を8個指定します。例のように、初めの1バイトしか使用しない場合にでも、8個全てをパラメータとして指定します。 この値が、EEPROMの先頭アドレスから順にセットされます。この命令を32個並べることで、256アドレス全てに、データをプリセットすることができます。
データEEPROMに関連するに関連するレジスターを一覧で説明します。
| レジスタ | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
|---|---|---|---|---|---|---|---|---|
| RCON | IPEN | SBOREN | — | RI | TO | PD | POR | BOR |
| INTCON | GIE/GIEH | PEIE/GIEL | TMR0IE | INTIE | RABIE | TMR0IF | INT0IF | RABIF |
| PIR2 | OSCFIF | C1IF | C2IF | EEIF | BCLIF | USBIF | TMR3IF | CCP2IF |
| PIE2 | OSCFIE | C1IE | C2IE | EEIE | BCLIE | USBIE | TMR3IE | CCP2IE |
| IPR2 | OSCFIP | C1IP | C2IP | EEIP | BCLIP | USBIP | TMR3IP | CCP2IP |
| EEADR | EEADR7 | EEADR6 | EEADR5 | EEADR4 | EEAD3 | EEADR2 | EEADR1 | EEADR0 |
| EEDATA | EEPROM データレジスタ | |||||||
| EECON1 | EEPGD | CFGS | FREE | WRERR | WREN | WR | RD | |
| EECON2 | EEPROM 制御レジスタ2 ( 物理レジスタではない) | |||||||
| レジスタ | BIT | 名 | 説明 | 1 | 0 |
|---|---|---|---|---|---|
| RCON | 7 | IPEN | 2レベルのインタラプト優先度 | 使用 | 不 |
| INTCON | 7 | GIEH | 高優先度インタラプトを使用許可 | 許可 | 不 |
| 6 | GIEL | 低優先度インタラプトを使用許可 | 許可 | 不 | |
| PIR2 | 4 | EEIF | 送信バッファ フラグ | 空 | 待ち |
| PIE2 | 4 | EEIE | インタラプトを使用許可 | 許可 | 不 |
| IPR2 | 4 | EEIP | インタラプト優先度 | 高 | 低 |
| EEADR | 7-0 | EEPROM アドレスレジスタ | - | - | |
| EECON1 | 7 | EEPGD | データEEPROMにアクセスするには 0 にリセット | Prgm | Data |
| 6 | CFGS | データEEPROMにアクセスするには 0 にリセット | Confg | Data | |
| 5 | - | - | |||
| 4 | FREE | フラッシュ ロウ( ブロック) 消去イネーブルビット | 許可 | 禁止 | |
| 3 | WRERR | エラーフラグ ビット | エラー | 完了 | |
| 2 | WREN | データEEPROM 書き込みイネーブルビット | 許可 | 禁止 | |
| 1 | WR | 書き込みサイクル制御ビット (リセットはできない) | 開始 | 完了 | |
| 0 | RD | 読み出し開始制御ビット (リセットはできない) | 開始 | 待機 |
PushSWを押した回数をLEDでカウントするプログラムです。SWが押されるたびにカウント数をdataEEPROMに書込み、LEDにも反映します。 DataEEPROMに毎回保存しているため、電源を切ってから再び電源を供給したときには、前のカウント数からスタートします。まお、プログラム直後のカウント数は、「3」に設定してあります。
<プログラム>
// File name: EEPROM
// Description: Data EEPROM example
// 4つのLEDがpushSWをカウントする。
// カウント値は毎回data EPROMに保存され、電源OFFでも消えない。
// Notes: 4MHz内部クロック
// LED RC0
// LED RC1
// LED RC2
// LED RC3
// Language: MPLABX XC8
// Target: PIC18F14K50
#include <xc.h>
#define _XTAL_FREQ 4000000 // delay_ms(x) のための定義
#define pushSW PORTBbits.RB7
//-------------- コンフィグレーション --------------------------------
#pragma config MCLRE = OFF
#pragma config PWRTEN = OFF, BOREN = OFF, BORV = 30
#pragma config WDTEN = OFF, WDTPS = 32768
#pragma config STVREN = ON
#pragma config FOSC = IRC // 内部クロック
#pragma config PLLEN = ON, CPUDIV = NOCLKDIV, USBDIV = OFF
#pragma config FCMEN = OFF, IESO = OFF, HFOFST = OFF
#pragma config LVP = OFF, XINST = OFF, BBSIZ = OFF
#pragma config CP0 = OFF, CP1 = OFF, CPB = OFF, CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF
unsigned char eeprom_readbyte(unsigned char);
void eeprom_writebyte(unsigned char, unsigned char);
//------ プログラム直後のEEPROMの初期データ --------------------------
__EEPROM_DATA(3,0,0,0,0,0,0,0);
//--------------------------------------------------------------------
void main(void){
char data;
unsigned char EEadd; // EEPROMアドレス
OSCCON = 0b01010010; // 内部クロック4Mhz
TRISC = 0xF0; // 入出力設定
ANSEL = 0; // すべてデジタル設定
ANSELH= 0;
EEadd=0; // アドレスリセット
data = eeprom_readbyte(EEadd); // EEPROM 0番地 読み込み
while(1){ // 繰り返しループ
LATC = data; // LEDを点灯
while(!pushSW); // SWが押されていないこと
__delay_ms(10); // チャタリング防止10mS遅延
while(pushSW); // SWが押されるのを待つ
__delay_ms(10); // チャタリング防止10mS遅延
data++; // LEDのカウントを1増やす
eeprom_writebyte(EEadd, data); // EEPROM 0番地 書込み
}
}
unsigned char eeprom_readbyte(unsigned char address)
{
EEADR = address; // アドレスをセット
EECON1bits.EEPGD = 0; // EEPROM を選ぶ
EECON1bits.CFGS = 0; // EEPROM を選ぶ
EECON1bits.RD = 1; // 読み出しの開始
while(EECON1bits.RD == 1); // 読み出し終了を待つ
return EEDATA; // データを持って復帰
}
void eeprom_writebyte(unsigned char address, unsigned char data)
{
char GIE_on;
EEADR = address; // アドレスをセット
EEDATA = data; // データをレジスタに書き込む
EECON1bits.EEPGD = 0; // EEPROM を選ぶ
EECON1bits.CFGS = 0; // EEPROM を選ぶ
EECON1bits.WREN = 1; // EEPROM書き込みを有効に
GIE_on = INTCONbits.GIE; // 割込環境を待避
INTCONbits.GIE = 0; // 割込みを禁止
EECON2 = 0x55; // EEPROM書き込み暗号を書く
EECON2 = 0xAA; // EEPROM書き込み暗号を書く
EECON1bits.WR = 1; // 書き込みの開始
if(GIE_on)INTCONbits.GIE = 1; // 割込み環境を復旧
while(PIR2bits.EEIF == 0); // 書き込み終了を待つ
PIR2bits.EEIF = 0; // EEIF bit クリア
EECON1bits.WREN = 0; // 以降は書き込みを禁止する
}