PIC三昧(17) EEPROM、データ書き込み&読み出し、PIC16F18855

Joseph Halfmoon

前回まで4回を費やしてMSSPを一通りなでました。今回は「軽く」NVM(NONVOLATILE MEMORY)に入りたいと思います。PIC16FマイコンはプログラムメモリとしてFlashを搭載しているだけでなく、不揮発なデータ格納用にEEPROMを搭載しています。これがあれば電源切っても消えない設定など自由自在だっ。

※『PIC三昧』PIC関係の記事総目次はこちら

※作業はMicroChip社の統合開発環境 MPLAB X IDEと、その上で走るコンフィギュレーションツールMCC Classic を使用して行っています。ターゲット・マイコンはPIC16F18855です。

オンチップNONVOLATILE MEMORY
PIC16FのFは多分FlashのFです。MicroChip社はマイコン業界では後発ながらもFlashマイコンを武器にして市場を開拓してマイコン大手にのし上がったと思ってます。PIC16FもプログラムメモリはFlashですが、それ以外に小容量ですがEEPROMも搭載してます。EEPROMはデータ用です。今ではFlashやEEPROMを混載しているマイコンは多いですが、会社によってはプロセスが弱くて電気特性のエンデュランスやリテンションをみるとがっかりなこともあります(個人の感想デス。)その点、MicroChip社製品は業界標準というかの性能じゃないかと思います。
PIC16F18855の場合の不揮発メモリの仕様は以下のようです。
    1. PFM Program Flash Memory 、1ワード14-bit、14Kワード、32ワードを1ブロックとした消去書き込みに対応。エンデュランスは1万回。データ保持期間40年、書き込みサイクルタイムは 2.5ms MAX.
    2. Data EEPROM、1ワード8-bit、256ワード、バイト単位の書き変え可能。エンデュランスは10万回、データ保持期間40年、書き込みサイクルタイムは1バイトにつき5ms MAX.
MCC Classicでの設定

NVMをプログラムからアクセスするための関数を使うためにはその名も「MEMORY」というリソースをプロジェクトに追加する必要があります。EEPROM_Resources

といっても設定項目などはなく、イネーブルにして関数がプロジェクトに取り込まれるようにするだけのようです。こんな感じ。EEPROMsetup

なお、今回もSTDIOをUSBシリアルに向けて出力を見れるようにしておくので、EUSARTも追加します。UARTsetting

手元のMCC Classicの場合、STDIOとして使うにあたっては前回同様の対処が必要です。

ピンマネージャの設定は以下の通りです。EUSARTのピンはUSBシリアルへのボード配線、PortAのビット0はLチカ用のLEDへの配線です。また、PortAのビット5を外部スイッチに接続し、EEPROMへの書き込みモードと読み出しモードの切り替えに使っています。pinMGR

 

EEPROM Read&Write、手抜きなテストプログラム

PortAのビット5が0(GND)なら書き込みモードに入りEEPROMの全バイトに0から255を書き込みます。ビット1が1(3.3V)なら読みだしモードに入りアドレス0xF000から0xF0FFまでのEEPROMの全バイトを標準出力に送ります。その際、書き込み時にはアドレスの下8ビット=データとしてあるので、書き込めているか否かが分かるようになっています。

void main(void)
{
    uint16_t adr;
    uint8_t  dat;

    SYSTEM_Initialize();
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();
    if (RA5 == 0) {
        printf("WRITE EEPROM\n");
        adr = 0xF000;
        dat = 0;
        while (adr < 0xF100)
        {
            DATAEE_WriteByte(adr++, dat++);
        }              
        printf("WRITE Complete.\n");
    } else {
        printf("READ EEPROM\n");
        adr = 0xF100;
        while (1)
        {
            RA0 = 1;
            __delay_ms(1000);
            adr = adr >= 0xF100 ? 0xF000 : adr + 1;
            printf("ADR=0x%04x RD=0x%02x\n", adr, DATAEE_ReadByte(adr));
            RA0 = 0;
            __delay_ms(1000);
        }       
    }
}

なお、書き込み関数 DATAEE_WriteByte()は、書き込み完了確認待ちループを含むので戻ってくれば書き込みプロセスは完了しているとみなせます。ただし、書き込み中は割り込み禁止になるので、割り込み使っていると取りこぼしが発生する可能性があります。実際、書き込みモードで標準出力にPrintfすると取りこぼしが起きている気がします。EEPROM書き込み時は他の仕事は止めてこれに専念するのが良いように思います。

また、読み出し関数 DATAEE_ReadByte()は割り込みを操作したりしないようなのでお楽。ただし、内部の読み出しタイミングはNOPの個数でとってます。高速なシステムクロックの場合NOPの数が足らなくなる可能性があるようです。以下コメントは引用。

// NOPs may be required for latency at high frequencies

しかし、今回のシステムクロックは1MHz設定なので問題なしと思います。

実機動作確認

実験ボードにスイッチを接続したものが以下に。PIC_EEPROM_DUT

まず書き込み前の状態をREADモードで確認しておきます。BeforeWrite

EEPROMの全バイト0xFFが読み取れるようです。

つづいてスイッチを書き込みモードにして走らせます。その後、再び読み出しモードにして読み出してみます。AfterWrite

アドレスの下8ビットと同じ値がデータとして書き込まれていることが確認できました。予定通りね。

PIC三昧(16) MSSP、I2C Slaveモードでデータを送受、PIC16F18855 へ戻る

PIC三昧(18) CRC、データ配列のCRC8をハードで計算、PIC16F18855 へ進む