Vol.899 26.Jul.2024

BDFフォントビュアー PICミニBB(9)_I2C接続メモリ

F FONTあれこれ(3)  〜BDFフォントビュアーの強化

by fjk

 Excelで作ったBDFフォントビュアーをabc896で紹介したが、テキストエディッタなどで、別途フォントファイルを開き、手動でデータをコピーする必要があり、使い勝手が良くなかった。
 そこで、@ダイアログで選択したBDFフォントファイルを読み込み、Aキーボードで入力した文字のパターンを表示し、BLCD用データとしてCSVファイルに記録できるようにした。
 なお、今回は縦パターンが1ワードで収まる16×16ドットまでのフォントを対象とした。

【使い方】
@ 表示したいBDFフォントファイルを「読込」ボタンをおして、ファイルを選択し、読み込む
A 文字入力セルに文字を入力(フォントファイルが半角か全角かに合わせること)
B「パターン表示」ボタンを押すを、入力文字に対応したフォントパターンが表示される
C「HEXデータ記録」ボタンを押すと「”フォント名”.CSV」ファイルに追加記録される。

※BDFViewer.xlsmファイルでは、各ボタンにマクロの実行を登録してあります。

【HEXファイル出力例】 (shnmk16.csv)  先頭は文字コード、 続けて縦フォントパターンデータ

Zipファイルには、Excelマクロファイル(xlsm)とVBAマクロファイル(bas)を圧縮保存。
BDFViewer.xlsm & BDFViewer.bas (zip)
 
★BDFViewer(VBAマクロ)

Option Explicit
Dim filePath As Variant, shtNam As String
Dim RowSize As Long, CorSize As Long

Sub BDF_Load()
    Dim fi As Variant,  maxRow As Long, ws As Worksheet
    filePath=Application.GetOpenFilename(filefilter:="BDF file(*.bdf),*.bdf")
    If filePath = False Then Exit Sub
    fi = Array(Array(1, xlTextFormat))
    Workbooks.OpenText Filename:=filePath, FieldInfo:=fi, Space:=True
    Set ws = Workbooks.Item(Workbooks.Count).Sheets(1)
    ws.Move After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
    shtNam = ActiveSheet.Name                    ' 新シート名を取得
    Worksheets("16dot").Range("C1").Value = shtNam
    maxRow = ThisWorkbook.Sheets(shtNam).Cells(1, 1).End(xlDown).Row
    MsgBox shtNam & " をロードしました " & maxRow
    Worksheets("16dot").Select
End Sub

Sub saveHex()
    Dim fso As Object, tso As Object
    Dim strPath As String,  hData() As String
    Dim i As Integer,  rofs As Integer,  dsz As Integer
    Set fso = CreateObject("Scripting.FileSystemObject")
    strPath = Worksheets(Worksheets.Count).Name & ".csv"
    Set tso = fso.OpenTextFile(strPath, 8, True)
    RowSize = Worksheets("16dot").Range("E2")
    CorSize = Worksheets("16dot").Range("C2")
    If CorSize > 8 Then
        rofs = 9
    Else
        rofs = 17
    End If
    dsz = CorSize * 2 + 1
    ReDim hData(dsz) As String
    Debug.Print CorSize & " " & dsz
    hData(0) = Cells(23, 2)
    For i = 1 To CorSize
        hData(i * 2 - 1) = Cells(21, rofs + i).Value
        hData(i * 2) = Cells(22, rofs + i).Value
    Next i
    With tso
        .WriteLine Text:=Join(hData, ",")
        .Close  'ファイルのクローズ
    End With
    Set fso = Nothing
    Set tso = Nothing
    MsgBox CurDir() & "\" & strPath & " にデータを追加しました"
End Sub

Sub ShowFolderPicker()
    Dim fd As FileDialog
    Set fd = Application.FileDialog(msoFileDialogFolderPicker)
    With fd
        If .Show = -1 Then
            MsgBox "選択されたフォルダ: " & .SelectedItems(1)
            ChDir Path:=.SelectedItems(1)
        Else
            MsgBox "フォルダが選択されませんでした。"
        End If
    End With
End Sub

Sub findKey()
    Dim ws As Worksheet, kw As String
    Dim code As Long,  i As Integer,  r As Range
    Set ws = Worksheets(Worksheets.Count)
    kw = "ENCODING"
    RowSize = 16
    CorSize = 16
    code = Worksheets("16dot").Range("B24").Value
    With ws.Range("A:A")
        Worksheets("16dot").Range("C1").Value = ws.Name
        Set r = .Find(what:="FONTBOUNDINGBOX", LookAt:=xlWhole)
        If r Is Nothing Then
            Exit Sub
        Else
            CorSize = r.Offset(0, 1).Value
            Worksheets("16dot").Range("C2") = CorSize
            RowSize = r.Offset(0, 2).Value
            Worksheets("16dot").Range("E2") = RowSize
        End If
        Set r = .Find(what:=kw, LookAt:=xlWhole)
        Do
            If r Is Nothing Then
                MsgBox ("該当無し")
                Exit Do
            Else
                If r.Next.Value = code Then
                    Debug.Print r.Address & "  " & r.Next.Value
                    For i = 1 To 16
                        If i <= RowSize Then
                            Worksheets("16dot").Range("B4").Offset(i) _
                                = r.Offset(4 + i).Value
                        Else
                            Worksheets("16dot").Range("B4").Offset(i) = 0
                        End If
                    Next i
                    Worksheets("16dot").Select
                    Exit Do
                Else
                    Set r = .FindNext(r)
                End If
            End If
        Loop While Not r Is Nothing
    End With
End Sub

【課題】 −>は課題の対策(とりあえず)

  1. 空白区切りが正しく実行されない場合がある
    −>フォントファイルを事前に、秀丸エディッタ等でCSVファイルに変更(「空白」' 'を「コンマ」','に置換)
  2. 最後に読み込んだフォントファイルデータしか利用出来ない
    −>見たいシートを最後(右端)に(複数のファイルを読み込んでもOKで、最後のフォントファイルのみが有効)
  3. Findメソッドは便利だが、処理速度が遅い(フリーズ?と疑うことがある)
  4. 該当するコードがないと無限ループとなる(全角ファイルで半角コードで検索した場合など)
       rangeで検索範囲を指定してもダメ! −>エスケープキーで停止できる・・が
      <注意>全角コードは全角ファイルで、半角コードは半角ファイルと合わせること!
     ※ 無限ループを解消したバージョン(BDFViewer2x.xlsm 、10/17追加)。それでも、検索終了まで時間がかかります(ESCキーで中断可能)

※ バグがありました。 (2024/9/7 訂正)
  16x16、8x16ドットは問題ないが、横ドットが8の倍数でない場合に正しくセーブされない。
  −>saveHexサブで、以下の赤字部分を変更。
 ・併せて、データーの格納順を、グラフィックLCD用のデータ並びに変更。

★BDFViewer(VBAマクロ)
BDFViewer2.xlsm & BDFViewer2.bas (zip)・・修正済み


Sub saveHex()
    Dim fso         As Object
    Dim tso         As Object
    Dim strPath     As String
    Dim hData()   As String
    Dim i As Integer, j As Integer, rofs As Integer, dsz As Integer
    Set fso = CreateObject("Scripting.FileSystemObject")
    strPath = Worksheets(Worksheets.Count).Name & ".csv"
    Set tso = fso.OpenTextFile(strPath, 8, True)
    RowSize = Worksheets("16dot").Range("E2")
    CorSize = Worksheets("16dot").Range("C2")
    rofs = 10 + 16 - CorSize
    dsz = CorSize * 2 + 1
    ReDim hData(dsz) As String
    Debug.Print CorSize & " " & dsz
    hData(0) = Cells(23, 2)
    For j = 0 To 1
        For i = 0 To CorSize
            hData(j * CorSize + i + 1) = Cells(21 + j, rofs + i).Value
        Next i
    Next j
    With tso
        .WriteLine Text:=Join(hData, ",")
        .Close  'ファイルのクローズ
    End With
    Set fso = Nothing
    Set tso = Nothing
    MsgBox CurDir() & "\" & strPath & " にデータを追加しました"
End Sub


P PICミニBBシリーズ(9)  〜外付けI2C接続EEPROM(24FC1025)

by fjk

 abc897で、消えないメモリにデータを保存することができたが、内蔵メモリは256byteしかなくワードデータを120個しか格納出来なかった。そこで、使えるメモリを増やそうとPIC外部にメモリを追加することにした。外部メモリにはI2C接続のものとSPI接続のものがあり、今回は前者のI2C接続メモリの24FC1025を使ってみる。(類似の24FC1026とはA0-A2の使い方が異なる)
 24FC1025-I/P(秋月#103570、250円)は安価な8ピンDIPサイズメモリで、128kx8ビットの容量がある。最高動作クロックは1MHz、動作電圧は1.8〜5Vで、5V使用のPICが直接接続出来る。

【24FC1025の使い方】

[メモリアクセス]
メモリは64kByte(512kbit)単位のブロックに分かれており、ブロック間で連続アクセスはできない。ブロックはControleByteのB0で指定し、続く16ビットのアドレスワードでアクセスアドレスを指定する。ControleByteのA0,A1は、外部Pin端子でアドレス指定された4つのチップを選択することができる。
なお、同一ピン配置で64kByte容量の24FC512の場合はブロック管理がなく、A0-A2までを使って、8つのチップまで接続出来る。
[データ読み書き]
R/W=0で、アドレスwordデータ(上位、下位バイトの順)、続けてbyteデータ送るとデータが書き込まれる。また、アドレスに続けて、最大128byteのデータを送るとページモードとして、連続で書き込むことができる。
データの読み出しは、アドレスword(上位、下位バイトの順)を指定し、その後R/W=1にすると、指定アドレスのbyteデータが読み出される。続けて読み出しを繰り返すとシーケンスモードとして、最大256バイトまでデータが順に読み出される。
 

24FC1025のピン配置

24FC1025のControleByte

書込みオペレーション
(ページは128バイト単位)

読出しオペレーション
(下:シーケンスモード)

【シリアル通信時のコマンド】(カギ括弧のパラメータは省略可能。コマンド文字は全て大文字)

W[aaaa][,[d0,・・[,]]]
アドレスaaaa(省略時:現在アドレス)からバイトデータを書き込む。
R[aaaa][,n]
アドレスaaaa(省略時:現在アドレス)からn(省略時:1)バイトデータを読み出す。
MBn
メモリブロックを指定する(n=0か1)。現在アドレスは 0 になる。
Q
連続書込みモードの解除(プロンプトが$)。W以外のコマンドでもモード解除。
U[aaaa]
アドレスaaaa(省略時:現在アドレス)が含まれる64バイト単位(ハーフページ)でデータをDBuf[]に読み出し、表示。
PW[aaaa]
64バイト単位(ハーフページ)でDBuf[]データをアドレスaaaa(省略時:現在アドレス)が含まれるメモリに書き込む。
  1. アドレス・データは16進数(nは10進数)。コマンド入力行の文字数は79文字以内(eusart.hのBFSIZEで変更可)。
  2. W、Rコマンド終了後、カレント(現在)アドレスは次アドレスになる。
  3. パラメータの16進数は大文字小文字を問わないが、コマンドと識別しやすくするため小文字を推奨。
  4. 文字はコマンドを含め、全て詰めて入力(空白やタブが無いこと!)
  5. Wコマンドで、Wのみ、または入力行を「コンマ」(,)で終わると、「連続書込みモード」(プロンプトが#)となり、以後「データ」のみの入力で、データが順に書込まれる。このモードは、W以外のコマンドで解除される(Wコマンドでは解除されない)。
  6. Uコマンドでデータを読み出し、PWコマンドで書き込むことで、ページ単位でデータコピーできる(ページアクセス時、アドレスの下位6ビットは全て0から64バイト)。

【ハードウェア】(PIC16F18325使用)


全回路図

I2Cメモリブレッドボード配線図
(ADT・RTCは外している)

読み書きテスト中

テラターム画面例

ページデータコピー例

【ソフトウェア】

※ シリアル通信用バッファーサイズ(BFSIZE)は、Wコマンドで最大16バイトのHex文字データ(6+16×3文字)が受信できるように、余裕を持って80としたが、必要であればeusart.hで変更すること。
※ 液晶表示器用にi2cLCD_ST7032i.c/hが必要です(abc893など参照)。eusart.c/hの設定はabc897を参照。
 
<トラブル?>
何故か?、配列変数要素数を80超にするとコンパイラでエラーが出る。メモリにはまだ余裕があるはずだが・・(18326に交換しても同じ)。
仕方が無いので要素数を78+2(アドレス分)とした。そのため、ページアクセスの要素数は64(ハーフページ分)とした。
−>(s)printf()関数を使用しないように変更すると、メモリ使用量が節約され、配列要素数を増やしてもエラーが出ないので、多分「メモリ不足」が原因。
また、MCCで18326に変更したはずだが、コンパイラにRAM容量の変更が正しく認識されなかったのかも・・。

 
【I2C接続EEPROMテストプログラム】 abc899-18325.c(zip)

/************************(abc899-18325.c)*******************
 *	I2C接続EEPROM(24FC1025)読み書きテスト
 ***********************************************************/

#define DEVICE	0x50                    // Blk0=0x50,Blk1=0x54
#define MBFSIZE	78                      // メモリ操作用バッファーサイズ

#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/examples/i2c1_master_example.h"
#include "i2cLCD_ST7032i.h"
#include "ctype.h"                      // isxdigit()
#include "stdio.h"                      // puts(),..
#include "stdlib.h"                     // atoi()...
#include "string.h"                     // strtok()...
//#include 

//=== グローバル変数 ============
char     Dlm[] = ",";                   // 文字列区切りデリミタ

//--- シリアル通信用
char     RBuf[BFSIZE];                  // シリアル受信用
                                        // BFSIZEはeusart.hで宣言
uint8_t  SFlg;                          // シリアル受信フラグ
char     SBuf[20];                      // 文字列処理用バッファー

//--- I2Cメモリー用
uint8_t  BlkNum = 0;                    // メモリブロック番号
uint16_t CrtAdr = 0;                    // カレントアドレス
uint8_t  DBuf[MBFSIZE];                 // ページメモリ用バッファー
uint8_t  SqMode;                        // シーケンスモードフラグ

/*************************************
 *  I2C EEPROM function
 **************************************/
//-----  アドレスadrから、1バイトを読み出す
uint8_t I2C_Mem_Read(uint16_t adr){
    uint8_t bf[2];

    bf[0] = adr >> 8;
    bf[1] = (uint8_t)adr;
    I2C1_WriteNBytes(DEVICE + BlkNum,bf,2);
    I2C1_ReadNBytes(DEVICE + BlkNum,bf,1);
    return bf[0];
}

//-----  アドレスadrに、1バイトdtを書き込む
void I2C_Mem_Write(uint16_t adr, uint8_t dt){
    uint8_t bf[3];

    bf[0] = adr >> 8;
    bf[1] = (uint8_t)adr;               // アドレスセット
    bf[2] = dt;                         // データセット
    I2C1_WriteNBytes(DEVICE + BlkNum,bf,3);  //書き込む
    __delay_ms(5);
}

//-----  アドレスadrからnバイトをary[]に読み出す
void I2C_Mem_NRead(uint16_t adr, uint8_t *ary, uint8_t n){
    uint8_t bf[2];

    bf[0] = adr >> 8;
    bf[1] = (uint8_t) adr;
    if(n > MBFSIZE) n = MBFSIZE;        // 配列要素数以内
    I2C1_WriteNBytes(DEVICE+BlkNum,bf,2);  // アドレス送信
    I2C1_ReadNBytes(DEVICE+BlkNum,ary,n);  // データ読込
}

//-----  アドレスadrからary[]のnバイトを書き込む
void I2C_Mem_NWrite(uint16_t adr, uint8_t  *ary, uint8_t n){
    uint8_t bf[MBFSIZE + 2];

    bf[0] = adr >> 8;                   // アドレスセット
    bf[1] = (uint8_t) adr;              // ページ境界に注意!
    if(n > MBFSIZE) n = MBFSIZE;
    memcpy(bf+2,ary,n);                 // ary[]をbf[]にコピー
    I2C1_WriteNBytes(DEVICE+BlkNum,bf,n+2);
    __delay_ms(5);
}

//---- ターミナルにプロンプト文字表示
void prtPrompt(uint8_t m){
    if(m)  printf("# ");                // 連続書込モード中
    else   printf("$ ");                // 通常書込モード
}

//---- 16進文字列を10進数に変換
int16_t my_xtoi(char *str){
    uint32_t dec;

    dec = strtoul(str,NULL,16);
    if(errno == ERANGE) return -1;      // 文字列変換エラー
    return (int16_t)dec;
}

/************************************
 * 	コマンドアクション
 ************************************/
//----- Wコマンド   W[aaaa][,[d0,・・[,]]]
uint16_t cmd_W(char *str){
    char     *pt;                       // 文字列操作用ポインタ
    uint8_t  last;                      // 文字列の最後の位置
    int16_t  res = 0;                   // Hex文字数値変換結果
    uint8_t  dt = 0;                    // 書き込むバイトデータ
    uint16_t cnt = 0;                   // 実際に書き込んだバイト数

    if(strlen(str)==1){                 // 'W'のみなら
        SqMode = 1;                     // 連続書込モードにセット
        puts("SqMode ON\n\r");
        return 0;                       // データは書き込まない
    }
    last = (uint8_t)strlen(str)-1;      // 文字列の行末位置を取得
    if(str[last] == ','){               // 行末がコンマなら
        SqMode = 1;                     // 連続書込モードにセット
        puts("SqMode ON\n\r");
        str[last]='\0';                 // 行末のコンマを消す
    }
    if(str[1]!=','){                    // 第2文字がコンマか?
        pt = strtok(str+1,Dlm);         // コマンドの次文字から
        if(pt != NULL){                 // アドレスデータがある
            res = my_xtoi(pt);
            if(res < 0) return cnt;     // 文字変換エラー
            CrtAdr = (uint16_t)res;
        }
        pt = strtok(NULL,Dlm);          // 次文字列取込
    }else{
        pt= strtok(str+1,Dlm);          // 文字列取込
    }
    do{
        if(pt != NULL){                 // データがあるか?
            res = my_xtoi(pt);
            if(res < 0) return cnt;
            dt = (uint8_t)res;
            I2C_Mem_Write(CrtAdr,dt);   // データを書き込む
            sprintf(SBuf,"%d:%04X < %02X",BlkNum,CrtAdr,dt);
            printf("%s\n\r",SBuf);
            LCD_cursor(1,1); LCD_str(SBuf);
            CrtAdr++; cnt++;
            pt = strtok(NULL,Dlm);      // 次文字へ
        }
    }while(pt != NULL);                 // データがあるだけ繰り返す
    return cnt;                         // 書き込んだ文字数を返す
}

//---- Rコマンド  R[aaaa][,n]
uint16_t cmd_R(char *str){
    char *pt;                           // 文字列操作用ポインタ
    uint16_t n = 1;                     // 指定された読込バイト数
    int16_t  res = 0;                   // Hex文字数値変換結果
    uint8_t  dt;                        // 読み込んだバイトデータ
    uint16_t cnt = 0;                   // 実際に読み出されたバイト数
    uint8_t  i;                         // ループ変数

    if(strlen(str) > 1){
        if(str[1]==','){
            pt = strtok(str+2,Dlm);
            if(pt != NULL){             // データ無し?
                res = my_xtoi(pt);
                if(res < 0) return cnt;
                n = (uint16_t)res;
            }
        }else{
            pt = strtok(str+1,Dlm);
            if(pt != NULL){             // addressがある?
                res = my_xtoi(pt);
                if(res < 0) return cnt; // 文字列変換エラー
                CrtAdr = (uint16_t)res;
            }
            pt = strtok(NULL,Dlm);      // 次文字へ
            if(pt != NULL){             // データ無し?
                res = my_xtoi(pt);
                if(res < 0) return cnt;
                n = (uint16_t)res;
            }
        }
    }
    for(i = 0; i < n;i++ ){
        dt = I2C_Mem_Read(CrtAdr);      // データを読み出す
        sprintf(SBuf,"%d:%04X > %02X",BlkNum,CrtAdr,dt);
        printf("%s\n\r",SBuf);
        LCD_cursor(1,1); LCD_str(SBuf);
        CrtAdr++; cnt++;
    }
    SqMode = 0;
//    puts("SqMode OFF");
    return cnt;                         // 読み込んだデータ数を返す
}

//---- WSQ (連続書込モード)
uint16_t cmd_WSQ(char *str){
    char     *pt;                       // 文字列操作用ポインタ
    uint8_t  dt;                        // 書き込むバイトデータ
    int16_t  res;                       // Hex文字数値変換結果
    uint16_t cnt = 0;                   // 実際に読み出されたバイト数

    pt = strtok(str,Dlm);
    while(pt != NULL){                  // データがあるだけ繰り返す
        res = my_xtoi(pt);
        if(res < 0) return cnt;         // 文字列変換エラー
        dt = (uint8_t)res;
        I2C_Mem_Write(CrtAdr,dt);       // データを書き込む
        printf("%d:%04X < %02X\n\r",BlkNum,CrtAdr,dt);
        CrtAdr++; cnt++;
        pt = strtok(NULL,Dlm);          // 次文字列へ
    }
    return cnt;                         // 書き込んだデータ数を返す
}

//---- MBコマンド  MBn
int cmd_M(char *str){
    char     *pt;                       // 文字列操作用ポインタ
    uint8_t  b;                         // メモリバンク番号

    if(str[1] != 'B') return -1;        // 第2文字がBか?
    pt = strtok(str+2,Dlm);
    if(pt==NULL) return -1;             // 文字列変換エラー
    b = atoi(pt) & 0x01;
    printf("Bank %d selected\n\r",b);
    BlkNum = b * 4;                     // Blk = bit2
    CrtAdr = 0;                         // 現在アドレスは0に
    SqMode = 0;
//    puts("SqMode OFF\r");
    return b;
}

//---- Qコマンド(連続書込モードの解除)   Q
void cmd_Q(char *str){
	SqMode = 0;
	puts("SqMode OFF\r");
}

//---- U(dump)コマンド    U[aaaa]
//         (64バイトのデータをDBuf[]に読み出す)
int cmd_U(char *str){
    char    *pt;                        // 文字列操作用ポインタ
    int16_t  res;                       // Hex文字数値変換結果
    uint16_t ad;                        // 指定アドレス
    uint8_t  i;                         // ループ処理用

    pt = strtok(str+1,Dlm);
    if(pt != NULL){                     // アドレス有り?
        res = my_xtoi(pt);
        if(res < 0) return -1;          // 文字列変換エラー
        CrtAdr = (uint16_t)res;
    }
    ad = CrtAdr & 0xFFC0;               // 64バイト単位に 
    I2C_Mem_NRead(ad,DBuf,64);          // 64バイトをDBuf[]に読出し
    printf("%d:%04X - %04X",BlkNum,ad,ad+63);
    for(i = 0; i < 64; i++){            // 16x4文字表示
        if(i % 16 == 0) printf("\n\r");
        printf(" %02X",DBuf[i]);
    }
    puts("\r");
    SqMode = 0;
    return 0;
            
}

//---- P(Page)コマンド    PW[aaaa]
//          (DBuf[]の64バイトをメモリに書き込む)
int cmd_P(char *str){
    char     *pt;                       // 文字列操作用ポインタ
    int16_t  res;                       // Hex文字数値変換結果
    uint16_t ad;                        // 指定アドレス
    uint8_t  i;                         // ループ処理用

    if(str[1] != 'W') return -1;        // 第2文字がW?
    pt = strtok(str+2,Dlm);
    if(pt != NULL){                     // アドレス有り?
        res = my_xtoi(pt);
        if(res < 0) return -1;          // 文字列変換エラー
        CrtAdr = (uint16_t)res;
    }
    ad = CrtAdr & 0xFFC0;               // 64バイト単位に
    I2C_Mem_NWrite(ad,DBuf,64);         // DBuf[]の64バイト書込
    printf("Page Write %d:%04X - %04X\n\r",BlkNum,ad,ad+63);
    SqMode = 0;    
    return 0;
}

/********************************
 *  main apprication 
 ********************************/
void main(){
    char cmd;                           // コマンド文字

    SYSTEM_Initialize();
    LCD_init();                         // LCD初期化

    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();

    puts("ready\r");
    LCD_str("ready");                   // コマンド処理準備完了
    prtPrompt(SqMode);

    while(1){
        if(SFlg){                       // シリアル入力有り?
            LCD_clr(); LCD_str(RBuf);   // LCDにコマンド表示
            cmd = RBuf[0];              // コマンドは第1文字
            printf("\n\r");
            switch(cmd) {               // 各コマンドの実行
                case 'W':  cmd_W(RBuf);  break;
                case 'R':  cmd_R(RBuf);  break;
                case 'Q':  cmd_Q(RBuf);  break;
                case 'M':  cmd_M(RBuf);  break;
                case 'U':  cmd_U(RBuf);  break;
                case 'P':  cmd_P(RBuf);  break;
                                        // 有効なコマンドがなく
                default:   if(SqMode) cmd_WSQ(RBuf);
                                        // 連続書込モード中なら
                           break;       // 書込シーケンスを実行
            }
            SFlg = 0;
            prtPrompt(SqMode);
        }
    }
}


※プログラムのリストをハイライト付きのスタイルで見る場合はここをクリック


※ 本レポートの参考・利用は、あくまでも自己責任でお願いします。


BDFフォントビュアー PICミニBB(9)_I2C接続メモリ