I2C EEPROMのダンプ表示と書き込みツール (PIC 12F1822)

戻る一つ前のメニューに戻る

I2C接続EEPROMのダンプ表示と書き込みを行うシリアル接続ユニットの製作。

目次

主な機能

  • 動作電圧 3.3V, 5.0V
  • シリアル接続(RS232C接続)によるPCからのコントロール
  • 指定範囲のダンプ表示、指定バイトによる上書き
コマンド書式
機能 コマンド書式 引数の説明
アドレス付き表示(ダンプ) R[addr],[page] addr=開始アドレス, page=表示ページ数(1ページ=32bytes)
表示(ダンプ) H[addr],[page] addr=開始アドレス, page=表示ページ数(1ページ=32bytes)
1バイト書き込み W[addr],[data] addr=開始アドレス, data=書きこみデータ(00〜FF)
指定バイト数書き込み M[addr],[data],[count] addr=開始アドレス, data=書きこみデータ(00〜FF), count=書き込みバイト数

数値は全て16進数として解釈される。数値を省略すると、0が指定されているものと解釈する。

回路図・部品表

eeprom-dump-sch.png

BSch3V用回路図ファイルをダウンロードする

名称 型番・仕様 個数・価格
PICマイコン 12F1822 1個(145円)
I2C EEPROM 24LC64 1個(80円)
炭素皮膜抵抗 10kΩ 1個(5円)

完成写真およびシリアル出力例

eeprom-dump-board.jpg

電源ON直後は0000番地から2page(2*32bytes)表示 EEPROM util [R|H][adr],[pg], W[adr],[dat], M[adr],[dat],[cnt] dmp adr 0000,pg 0002 0000: DD DD 20 80 80 FF FF FF FF FF FF FF FF FF FF FF 0010: A0 A0 A0 A0 A0 00 00 00 00 B0 B0 B0 CC 00 00 00 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

R90,2 ← 0090番地から2page(2*32bytes)表示 EEPROM util [R|H][adr],[pg], W[adr],[dat], M[adr],[dat],[cnt] dmp adr 0090,pg 0002 0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00B0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00C0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

W90,12 ← 0090番地に12を書き込み EEPROM util [R|H][adr],[pg], W[adr],[dat], M[adr],[dat],[cnt] wrt adr 0090,dat 12 done

MA0,34,4 ← 00A0番地から4バイト分に34を書き込み EEPROM util [R|H][adr],[pg], W[adr],[dat], M[adr],[dat],[cnt] wrt adr 00A0,cnt 0004,dat 34 done

R90,2 EEPROM util [R|H][adr],[pg], W[adr],[dat], M[adr],[dat],[cnt] dmp adr 0090,pg 0002 0090: 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00A0: 34 34 34 34 00 00 00 00 00 00 00 00 00 00 00 00 00B0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00C0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

ソースコード

XC8 C言語ソースコード、ビルド済みHEXファイル
動作確認済み開発環境
  • Microchip MPLAB X IDE ver 1.30
  • Microchip MPLAB X IDE ver 1.60
  • Microchip MPLAB XC8 ver 1.01
  • Microchip MPLAB XC8 ver 1.12
メイン関数部分の抜粋

※ライブラリ(i2c-lib, serial-lib)はSubversionブラウザにのみ掲載。

main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include <xc.h>
#include "common-lib.h"
#include "i2c-lib.h"
#include "i2c-eepromlib.h"
#include "serial-lib.h"
 
/* PIC Configuration 1 */
__CONFIG(FOSC_INTOSC &  // INTOSC oscillator: I/O function on CLKIN pin
        WDTE_OFF &      // WDT(Watchdog Timer) disabled
        PWRTE_ON &      // PWRT(Power-up Timer) disabled
        MCLRE_OFF &     // MCLR pin function is digital input
        CP_OFF &        // Program memory code protection is disabled
        CPD_OFF &       // Data memory code protection is disabled
        BOREN_OFF &     // BOR(Brown-out Reset) disabled
        CLKOUTEN_OFF &  // CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
        IESO_OFF &      // Internal/External Switchover mode is disabled
        FCMEN_OFF);     // Fail-Safe Clock Monitor is disabled
 
/* PIC Configuration 2 */
__CONFIG(WRT_OFF &      // Flash Memory Self-Write Protection : OFF
        VCAPEN_OFF &    // VDDCORE pin functionality is disabled
        PLLEN_OFF &     // 4x PLL disabled
        STVREN_ON &     // Stack Overflow or Underflow will not cause a Reset
        BORV_HI &       // Brown-out Reset Voltage Selection : High Voltage
        DEBUG_OFF &     // In-Circuit Debugger disabled, ICSPCLK and ICSPDAT are general purpose I/O pins
        LVP_OFF);       // Low-voltage programming : disable
 
 
#ifndef _XTAL_FREQ
    /* 例:4MHzの場合、4000000 をセットする */
    #define _XTAL_FREQ 4000000
#endif
 
void parse_hex_param(unsigned char *buf, unsigned int *val_1, unsigned int *val_2, unsigned int *val_3)
{
    char *ptr;
    const char *sep = ",";
    unsigned char i = 0;
 
    ptr = strtok(buf, sep);
    while(ptr){
        switch(i++){
            case 0: *val_1 = xtoi(ptr); break;
            case 1: *val_2 = xtoi(ptr); break;
            case 2: *val_3 = xtoi(ptr); break;
        }
        ptr = strtok(NULL, sep);
    }
 
}
 
void print_crlf(void){
    rs232c_puts("\r\n");
}
 
int main(int argc, char** argv) {
    // 基本機能の設定
    OSCCON = 0b01101010;        // 内部オシレーター 4MHz
    TRISA = 0b00101111;         // IOポートRA0(AN0),RA1(SCL),RA2(SDA),RA5(RX)を入力モード(RA3は入力専用)、RA4(TX)を出力モード
    APFCONbits.RXDTSEL = 1;     // シリアルポート RXをRA5ピンに割付
    APFCONbits.TXCKSEL = 1;     // シリアルポート TXをRA4ピンに割付
    ANSELA = 0b00000001;        // A/D変換をAN0を有効、AN1,AN2,AN4を無効
    PORTA = 0;
    INTCONbits.PEIE = 1;        // 割り込み機能をON (RX受信割り込みを使う場合)
    INTCONbits.GIE = 1;         // 割り込み機能をON (RX受信割り込みを使う場合)
 
    i2c_enable();
    OPTION_REGbits.nWPUEN = 0;  // I2C プルアップ抵抗 有効
    WPUA = 0b00000110;          // pull-up (RA1=SCL, RA2=SDA pull-up enable)
 
    ADCON0 = 0;                 // AN0選択, A/D機能停止
 
    // 0.5秒待つ
    __delay_ms(500);
 
    rs232c_init(9);     // init 9600bps
 
    unsigned int start_addr = 0;
    unsigned int page_count = 2;
    unsigned int temp_num = 0;
    unsigned char write_data = (char)0;
    unsigned char buf_strfmt[5];   // 数値の文字列変換用
 
    // 動作モード
    // R: dump with addr, H: dump without addr, P: write page, B: write byte
    unsigned char mode_sw = 'R';
 
    while(1)
    {
 
        print_crlf();
        rs232c_puts("EEPROM util");
        print_crlf();
        rs232c_puts("[R|H][adr],[pg], W[adr],[dat], M[adr],[dat],[cnt]");
        print_crlf();
 
        switch(mode_sw)
        {
            case 'R':
            case 'H':
                rs232c_puts("dmp"); break;
            case 'W':
            case 'M':
                rs232c_puts("wrt"); break;
        }
        print_crlf();
 
        INTCONbits.PEIE = 0;        // 割り込み機能を一旦OFF
        INTCONbits.GIE = 0;         // 割り込み機能を一旦OFF
 
        unsigned char i;
 
        if(mode_sw == 'R' || mode_sw == 'H')
        {
            rs232c_puts("adr ");
            rs232c_puts(uint_to_hex4(start_addr, buf_strfmt));
            rs232c_puts(",pg ");
            rs232c_puts(uint_to_hex4(page_count, buf_strfmt));
            print_crlf();
            for(int j=0; j<page_count; j++)
            {
                i2c_eeprom_read_32byte(start_addr + (j<<5), rs232c_buffer);
                if(mode_sw == 'R')
                {
                    rs232c_puts(uint_to_hex4(start_addr + (j<<5), buf_strfmt));
                    rs232c_puts(": ");
                }
                for(i=0; i<32; i++)
                {
                    rs232c_puts(uchar_to_hex2(rs232c_buffer[i], buf_strfmt));
                    rs232c_puts(" ");
                    if(i==15)
                    {
                        print_crlf();
                        if(mode_sw == 'R')
                        {
                            rs232c_puts(uint_to_hex4(start_addr + (j<<5) + 16, buf_strfmt));
                            rs232c_puts(": ");
                        }
                    }
                }
                print_crlf();
            }
        }
        else if(mode_sw == 'W' || mode_sw == 'M')
        {
            rs232c_puts("adr ");
            rs232c_puts(uint_to_hex4(start_addr, buf_strfmt));
            if(mode_sw == 'M'){
                rs232c_puts(",cnt ");
                rs232c_puts(uint_to_hex4(page_count, buf_strfmt));
            }
            rs232c_puts(",dat ");
            rs232c_puts(uchar_to_hex2(write_data, buf_strfmt));
            print_crlf();
            if(mode_sw == 'W'){
                i2c_eeprom_write_byte(start_addr, write_data);
            }
            else{
                for(i=0; i<page_count; i++){
                    i2c_eeprom_write_byte(start_addr + i, write_data);
                }
            }
            rs232c_puts("done");
            print_crlf();
        }
 
        // RS232Cでの受信待機モードに切り替える
        rs232c_buffer[0] = (char)0;
        flag_rs232c_received = 0;
        INTCONbits.PEIE = 1;        // 割り込み機能を再度ON
        INTCONbits.GIE = 1;         // 割り込み機能を再度ON
 
        start_addr = 0;
        page_count = 0;
        temp_num = 0;
        mode_sw = 'R';
 
        // RS232C入力またはRA3ボタンが押されるまで待つ
        while(1)
        {
            // 0.5秒待つ
            __delay_ms(500);
 
            // RS232Cで改行を伴う文字列入力を検知した場合
            if(flag_rs232c_received)
            {
                if(rs232c_buffer[0] == 'R' || rs232c_buffer[0] == 'H')
                {
                    parse_hex_param(rs232c_buffer+1, &start_addr, &page_count, &temp_num);
                    mode_sw = rs232c_buffer[0];
                }
                else if(rs232c_buffer[0] == 'W' || rs232c_buffer[0] == 'M')
                {
                    parse_hex_param(rs232c_buffer+1, &start_addr, &temp_num, &page_count);
                    write_data = (char)(temp_num & 0xff);
                    mode_sw = rs232c_buffer[0];
                }
 
                rs232c_buffer[0] = (char)0;
                flag_rs232c_received = 0;
                break;
            }
 
            // RA3ボタンが押された場合
            if(!PORTAbits.RA3)
            {
                break;
            }
        }
    }
    return (EXIT_SUCCESS);
}

関連記事

 

戻る一つ前のメニューに戻る