« 50MHz AMトランシーバー(組み立て2) | メイン | 10m E級アンプの実験 »

2019年5月 6日 (月)

PIC24FJ64GA004 フラッシュメモリーへの書き込み(EEPROM代用)

<カテゴリー:PICマイコン

16bitのPICマイコンの中で、24FシリーズにはEEPROMを個別に持っているものと、プログラムを格納するフラッシュROMエリアにデータも書きこんで、これを読み出す事により、EEPROMを代用できるものとに分かれます。 今回、PIC24FJ64GA004 において、EEPROM機能を必要としましたので、そのソフトをXC16のプログラムで紹介します。

Microchipやインターネットに情報公開している大先輩方による解説は沢山あるのですが、あまり考えずにコピペして使えるプログラム例がありませんでしたので、コピペだけで、済まそうという方に参考になればと思い公開します。

条件: フラッシュメモリーのアドレス0x9600から600バイトをEEPROM代用に宣言し、その中で64ワード分を読み書きできるようにします。 もし、64ワード以上必要な場合、ご自分で検討して下さい。

このデータメモリーは起動時にフラッシュROMエリアのデータを必要分のみ読み取り、プログラム実行中に変更されるあるいは変更されないデータいずれも、全てまた同じアドレスに書きこむことを基本動作としています。 例では lastmemory[] という変数の中にメモリー必要なデータが保持されるようにしています。 また、書き込み動作は結構時間がかかりますので、64ワード全てが必要でない場合、必要なワードのみを書き込み、影響を最小限にしています。 例では0から6までの引数(7種類)のデータだけを読み書きし、時間短縮を行っています。

コピペする範囲を青色、各自でアレンジする必要あるところを緑で示します。

最初にインクルードファイルです。

#include <libpic30.h>

次にグローバル変数を定義します。

section(".Data_Memory")の記述は、MPLAB Xにてコンパイルした時、メモリーマップが表示されるようにしたもので、リストの中に.Data_memory という情報を見つける事ができます。

//////////////グローバル変数として以下定義

unsigned int lastmemory[64];//EEPROM

const __attribute__((section(".Data_Memory"), space (prog), address (0x9600) )) unsigned int _flash_datas[96*8];

以下、読み書きENDまでが読み込み、書き込み関数です。 ここは何も考えずにコピペすればOKです。

/////////////////////////////////////////////フラッシュメモリー読み書き
void Flash_Read(unsigned char LN) {
 unsigned int i=0;

    unsigned int page = __builtin_tblpage(&_flash_datas);
    unsigned int offset = __builtin_tbloffset(&_flash_datas);
      // フラッシュメモリー読み込み
    TBLPAG = page;
    for (i=0; i<=LN; i++) {
        lastmemory[i] = __builtin_tblrdl(offset + i*2);
    }
}

void Flash_Write(unsigned char LN) {
    unsigned int i=0;
    unsigned int page = __builtin_tblpage(&_flash_datas);
    unsigned int offset = __builtin_tbloffset(&_flash_datas);

    
    // ページ消去
    TBLPAG = page;
    __builtin_tblwtl(offset, 0x0000); // 
    NVMCON = 0x4042;
    asm volatile ("disi #5");
    __builtin_write_NVM();          //erase 8line = 64*8
    while(NVMCONbits.WR);
 
    // ラストメモリー書き込み
    NVMCON = 0x4003;
    TBLPAG = page;
    for (i=0; i<=LN; i++) {
        __builtin_tblwtl(offset + i*2, lastmemory[i]);  // *2 偶数
        __builtin_tblwth(offset + i*2, 0xFF);
   
    asm volatile ("disi #5");
    __builtin_write_NVM();
    while(NVMCONbits.WR);
    }
}
/////////////////////////////////////////////フラッシュメモリー読み書きEND

以下、読み出したデータ lastmemory[] の中を、プログラムで使用している変数に分解します。 フラッシュメモリーはワード単位で読み出されますので、32bitのデータや8bitのデータはそれなりに加工が必要になります。 この例では、lastmemory[0],[1] は合成して32bitのデータに変換しています。 また、例えcharの変数でも16bit全体を使い余計な処理は省いています。

void readlastmemory(){
 unsigned long int bf;
 Flash_Read(6);//引数6は最後の[6]を指定する事
    bf = lastmemory[1];
 bf = bf << 16;
 BASEFREQ = lastmemory[0] | bf;
 V_level = lastmemory[2];
 MODE = lastmemory[3];
 IWB = lastmemory[4];
 RIT = lastmemory[5];
 Ritfreq = lastmemory[6];
}

以下は、プログラムで使用中の変数を lastmemory[] に格納した上フラッシュROMへ書きこみます。

void writelastmemory() {
 lastmemory[0] = BASEFREQ & 0x0000FFFF;//BASEFREQは32bitデータなので、[0],[1]に分割する。
 lastmemory[1] = BASEFREQ >> 16;
 lastmemory[2] = V_level;
 lastmemory[3] = MODE;
 lastmemory[4] = IWB;
 lastmemory[5] = RIT;
 lastmemory[6] = Ritfreq;
 Flash_Write(6);//引数6は最後の[6]を指定する事

}

MPLAB XにてコンパイルするときMPLAB Xの設定を少し変更が必要です。

Mplabx190506

Project Propertiesの中のXC16_gccを選び、上のoption categories の中のMemory Modelを開き、添付のようにチェックマークを入れます。(通常はマークなし) ただし、この状態は私の環境によるもので、使用状態では異なる可能性があります。 エラーが出る場合、この辺のチェックを付けたり外したりしてみて下さい。

このプログラムの実施例はこちらに有ります。

PIC24FV32KAシリーズのEEPROMアクセスコード例はこちらにあります。

INDEXに戻る