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で検索範囲を指定してもダメ! −>エスケープキーで停止できる・・が
      <注意>全角コードは全角ファイルで、半角コードは半角ファイルと合わせること!

※ バグがありました。 (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(ハーフページ分)とした。
 
【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接続メモリ