Vol.904 11.Oct.2024

フォントデータのROM化(1) 合字とは PICミニBB(14)_フォントROMで半角文字表示

F Excel_VBAによるフォントデータのROM化(1)

by fjk

 Excel_VBAを使って、abc899でフォントデータのファイル化、abc901でPICのEPROMへの書込が出来るようになった。そこで、この2つの機能をまとめ、フォントデータのROM化を行いやすくした。

  1. フォントビュアー・ライターのExcelVBA変更・機能追加
    • フォントビットデータを、横方向の1行目データを先に保存し、次に2行目を保存。
    • 通信データ、受信データ、通信ポート番号、通信コマンドセル、次アドレスの計算ボタンを追加
    • 「送信」ボタンを押すと、シリアル通信を実施(SendDataセルの内容を送信)
    • HEXデータファイルは、16進数テキストデータ(CSV)で、C言語データとしてそのまま利用も可
       【 半角Asciiフォントファイル(東雲8x16a.bdfより[一部改])shnm8x16a.csv
      当初、通信機能ボタンは右上のみに設置していたが、文字パターンの近くにも同様のボタンを配置した。
      全フォントを自動でROMに書き込んでも良いが、今回は途中でパターン修正も行えるよう手動にした。
       (注:パターンデータを変更する場合、BDFセル(B5:B20)に16進数を入力すること!)
     
  2. Romライタープログラムの使い方 (注:使用する数値は、port番号を除き、全て16進数です)
    ● 使用する(USBの)シリアル通信ポート番号をCPortセルに入力
    ① BDFファイルを読み込む(必要であれば「カレントフォルダーの変更」も実施)
    ② 文字入力セルに文字を入力(半角/全角の文字とファイルは一致させてください)
    ・コードが一致せず砂時計のまま(サーチ中)の場合、ESCキーを押すと元に戻ります
    ・Excelでアポストロフィ(シングルクォテーション)そのものを入力するには、アポストロフィを2つ続けて入力
    ③「パターン表示」ボタンをクリック(ここで、気に入らなければ、パターンの編集もできる)
    ④「HEXデータ記録」ボタンを押すとFileNameで指定されたファイルに追加モードで保存
    ⑤ 送信するコマンドをCMDセルに、書き込みたいアドレス(20bit)をAddressセルに16進数でセットする
    ・「次番地」ボタンを押すとフォントバイトデータ数をアドレスに加算します
    ⑥「送信データ作成」ボタンを押すと、SendDataセルに送信データを作成し、表示。
    ⑦「送信」ボタンを押すとデータを送信し、受信結果も表示(「送信+」ボタンは送信後addressも加算)。
    ・送受信が正常に終了するとSendDataセルが消去される(2秒以上かかります)
    ・送信内容を手動で行うには、SendDataにデータを手入力後、「送信」ボタンをクリック


全角フォントの例

半角フォントの例(パターンの一部を変更)
【Excel xlsmプログラム】 BDFViewerWriter.xlsm(zip)
 BDFViewerWriter.xlsmは全角用、BDFViewerWriterH.xlsmは半角用(BDFViewerWriter.xlsmに半角ファイルを追加したもの)
 
【Excel VBAプログラム】 BDFViewerWriter.bas(zip)
Option Explicit
Dim filePath As Variant
Dim shtNam As String
Dim RowSize As Long,  CorSize As Long

Sub BDF_Load()
    filePath = Application.GetOpenFilename(filefilter:="BDFファイル(*.bdf),*.bdf")
    If filePath = False Then Exit Sub
    Dim fi As Variant
    fi = Array(Array(1, xlTextFormat))
    Dim maxRow As Long
    Workbooks.OpenText Filename:=filePath, FieldInfo:=fi, Space:=True
    Dim ws As Worksheet
    Set ws = Workbooks.Item(Workbooks.Count).Sheets(1)
    ws.Move After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
    Dim shtNam As String
    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 findKey()
    Dim ws As Worksheet
    Set ws = Worksheets(Worksheets.Count)
    Dim kw As String
    kw = "ENCODING"
    RowSize = 16
    CorSize = 16
    Dim code As Long
    code = Worksheets("16dot").Range("B24").Value
    Dim i As Integer
    Dim r As Range
    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
            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

Sub saveHex()
    Dim fso As Object, tso As Object
    Dim strPath  As String, hData() As String
    Dim i As Integer, j As Integer, rofs As Integer, dsz As Integer, cnt 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 + 2
    ReDim hData(dsz) As String
    Debug.Print CorSize & " " & dsz
    cnt = 0
    For j = 0 To 1
      For i = 0 To CorSize - 1
        hData(cnt) = Cells(21 + j, rofs + i).Value
        Debug.Print cnt; " "; hData(cnt)
        cnt = cnt + 1
        Next i
  Next j
  hData(cnt) = "//"
  hData(cnt+1) = Cells(23, 2)
  hData(cnt+2) = Cells(23, 4)
  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 SerialEC()
  Dim cmd As String, rdc As String
  Dim row As Integer
  Dim S_Time As Date
  ec.COMn = Range("AB2")
  ec.Setting = "115200,n,8,2"
  ec.AsciiLineTimeOut = 1000
  cmd = Range("AB4")
  ec.AsciiLine = cmd
  row = 8
  Range("AB6:AB40").Value = ""
  S_Time = Now
  Do
    If Now > S_Time + TimeSerial(0, 0, 1) Then
      Exit Do     'TimeOut 2sec
    End If
    DoEvents
    Debug.Print "EC: " & ec.InBuffer
    If ec.InBuffer > 0 Then
      DoEvents
      rcv = ec.AsciiLine
      Cells(row, 28) = rcv
      row = row + 1
      S_Time = Now
    End If
  Loop
  ec.InBufferClear          '受信バッファをクリア
  ec.COMn = -1              '終了処理
  Range("AB4").Value = ""
End Sub

Sub setSerialData()
  Dim sData()     As String
  Dim i As Integer, j As Integer, rofs As Integer, dsz As Integer, cnt As Integer
  RowSize = Worksheets("16dot").Range("E2")
  CorSize = Worksheets("16dot").Range("C2")
  rofs = 10 + 16 - CorSize
  dsz = CorSize * 2 + 1
  ReDim sData(dsz) As String
  If Range("AC2") = "W" Or Range("AC2") = "S" Then
    sData(0) = Range("AC2") & Range("AD2")
    cnt = 1
  Else
    cnt = 0
  End If
  For j = 0 To 1
    For i = 0 To CorSize - 1
      sData(cnt) = Cells(21 + j, rofs + i).Value
      Debug.Print cnt; " "; sData(cnt)
      cnt = cnt + 1
    Next i
  Next j
  Cells(4, 28) = Join(sData, ",")
End Sub

Sub addAddress()
  Dim adr As Variant,  hdt As Variant
  hdt = WorksheetFunction.Hex2Dec(Range("ad2"))
  adr = Val(hdt) + Range("C2") * 2
  Range("AD2") = WorksheetFunction.Dec2Hex(adr, 5)
End Sub

Sub sendPlus()
  Call SerialEC
  Call addAddress
End Sub


G 合字とは  ~文字コードの確認と入力

by fjk

 合字とは、「㍻」や「㋿」のように2つの文字が一つのフォントになったもので、1文字として扱われます。通常の使用では、「れいわ」と読みを入力後、漢字変換を行うと候補として出てきます。「㍻」は文字コードとしてU+337B(JIS:2D5F、sift-JIS:877E)が割り当てられていますが、「㋿」はJISコードには無くユニコードでU+32FFが割り当てられています。
 これらの文字のコード確認や、コードなどで入力するには、以下を実行

【IME】
 「IMEパッド/Unicode」
【ATOK】
 「文字コード/Unicode表」
※ このファイルは合字を表示するため、s-jis文字コードでは表示できないので、utf-8文字コードで記述しています。


P PICミニBBシリーズ(14)  ~フォントROMで半角文字表示

by fjk

 前項の方法で、「ExcelによるフォントデータのROM化」が可能となったので、とりあえずASCII半角フォントパターン(8x16ドット)をEEPROM(25LC1024)の0x00200から0x007FFに書込み、ASCII半角文字を文字コードでグラフィックLCDに表示できるようにした。


JIS半角フォントコード表(ROMのアドレス0x00200から格納)

【ハードウェア】
abc903のBBセットをそのまま利用。
 
【ソフトウェア】
プログラムの基本は「abc903のおまけ」と同じだが、半角文字/文字列を表示する関数を追加した。
半角フォンパターンデータを前項のExcelでEEPROMに書込後、myProject.hファイルの「#define FONT_ROM」を有効にし、再コンパイルすると、グラフィックLCDに返信データが半角文字で表示されるようになる。
 

半角フォント文字列表示例

 ※ 全てのパターンのテストが完全に終わっていないので、バグがあるかも知れません(謝)。
 ※ 電源投入直後、メモリデータが正しく読めないことがあります。
    ->ROMの準備が間に合わない?->しばらく待つと正常になります。

 これまでのソースをここで纏めておくと・・、


MCC設定(Osc = HFINTOSC、Clock = 32MHz、Divider = 1)

eusart設定

spi設定

【abc904-18325.cファイル】 abc904-18325.c(zip)

/*******************************(abc904-18325)*********
 * SPI接続メモリ(24LC1024/23LCV1024) with AQM1248A  
 ******************************************************/

#include "myProject.h"

char     sBf[BFSIZE];                           // 文字列作業エリア
char     RBuf[BFSIZE];                          // シリアル受信バッファ
uint8_t  SFlg;                                  // シリアル受信フラグ

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

/*-----------------------------------
 *        Main application
 ------------------------------------*/
void main(void){
    uint8_t cmd;

    SYSTEM_Initialize();
    SSP1CON1bits.SSPEN = 1;                     //SPI1を有効に
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();

    gLCD_int();
    gLCD_clr(0);                                // 黒ベタは0xFF
    puts("Ready\r");                            // 動作確認用
    gLCD_strX(0,0,"Ready");
    prtPrompt(spiMem_SqMode());
    while (1){
        if(SFlg){
            gLCD_clr(0);                        // グラフィック画面消去
            gLCD_strX(0,0,RBuf);                // LCDにコマンド表示
            cmd = RBuf[0];                      // コマンドは第1文字
            #ifndef VBA
                printf("\n\r");
            #endif
            switch(cmd) {                       // 各コマンドの実行
                case 'W': spiMem_cmd_W(RBuf);  break;
                case 'R': spiMem_cmd_R(RBuf);  break;
                case 'Q': spiMem_cmd_Q(RBuf);  break;
                case 'U': spiMem_cmd_U(RBuf);  break;
                case 'S': spiMem_cmd_W(RBuf);  break;
                case 'P': spiMem_cmd_P(RBuf);  break;
                case 'K': spiMem_cmd_K(RBuf);  break;
                                                // 有効なコマンドがなく
                default:  if(spiMem_SqMode()){
                            spiMem_cmd_WSQ(RBuf);
                          }                     // 連続書込モード中なら
                          break;                // 書込シーケンスを実行
            }
            SFlg = 0;
            #ifndef VBA
                prtPrompt(spiMem_SqMode());
            #endif
        }
        IO_RA4_Toggle();
        __delay_ms(500);
    }
}

 
【myProject.hファイル】 myProject.h(zip)

/**************************(myProject.h)***
 *   プロジェクト個別条件指定ファイル     *
 *   (main.cと同じフォルダーに作成)     *
 ******************************************/

#include "mcc_generated_files/mcc.h"
#include "AQM1248A_v3.h"
#include "spi_Mem3.h"

#define  ON    1
#define  OFF   0

#define  VBA                                    // Excel VBA 使用?
//#define FONT_ROM                              // フォントROM有り?

/***** PIC電源電圧 ***********************/
//--- VCC宣言無しは5V(VCC=50と同じ)
#define VCC   50                                // 電源電圧は5V
//#define VCC   33                              // 電源電圧は3.3V
/***** EUSARTモジュール *******************/
#define BFSIZE  120                             // 80 から増やした
//--- ECHO宣言無しはエコー有り(ECHO ONと同じ)
#define ECHO  ON                                // エコー有り
//#define ECHO  OFF                             // エコー無し

/***** MSSPモジュール *********************/
#define MASTER 1
#define SRAVE  2
//#define I2CMODE MASTER                        // マスターとして使用
//#define I2CMODE SRAVE                         // スレーブとして使用
//--- MSSPが一つしか無い場合は I2C宣言無し
//#define I2C  1                                // I2C1を使用
//#define I2C  2                                // I2C2を使用

#if I2CMODE == MASTER
    #if I2C == 1
       #include "mcc_generated_files/examples/i2c1_master_example.h"
    #elif I2C == 2
       #include "mcc_generated_files/examples/i2c2_master_example.h"
    #else
        #include "mcc_generated_files/examples/i2c_master_example.h"
    #endif
#endif

//--- SPIが一つしか無い場合は宣言しない
#define SPIMODE MASTER                          // マスターとして使用
//#define SPIMODE SRAVE                         // スレーブとして使用

#define SPI  1                                  // SPI1を使用
//#define SPI  2                                // SPI2を使用

 
【spi_Mem3.hファイル】 spi_Mem3.c/h(zip)

/******************************(spi_Mem3.h)***************
 *	SPI接続メモリ(25LC1024/23LCV1024)ヘッダーファイル
 ********************************************************/

#include "ctype.h"                              // isxdigit()
#include "stdio.h"                              // puts(),..
#include "stdlib.h"                             // atoi()...
#include "string.h"                             // strtok()...

#define SPIMEM_WRITEcmd 0x02                    // WRITE
#define SPIMEM_READcmd  0x03                    // READ

#define SPIROM_WR_STATS 0x01                    // WRSR
#define SPIROM_WRITEcmd 0x02                    // WRITE
#define SPIROM_READcmd  0x03                    // READ
#define SPIROM_RD_STATS 0x05                    // RDSR
#define SPIROM_WR_ENABL 0x06                    // WREN
#define SPIROM_PG_ERASE 0x42                    // PE Page Erase
#define SPIROM_CP_ERASE 0xC7                    // CE Chip Erase
#define SPIROM_SC_ERASE 0xD8                    // SE Sector Erase

/***  SPI 汎用サブルーチン *****/
//-----  アドレスadrから、1バイトを読み出す
uint8_t SPI_Mem_Read(uint32_t adr);

//-----  アドレスadrに、1バイトdtを書き込む
uint8_t SPI_Mem_Write(uint32_t adr, uint8_t dat);

//-----  アドレスadrからcntバイトをary[]に読み出す
void SPI_Mem_NRead(uint32_t adr,uint8_t *ary,uint16_t cnt);

//-----  アドレスadrからary[]のcntバイトを書き込む
void SPI_Mem_NWrite(uint32_t adr,uint8_t *ary,uint16_t cnt);

//----  シーケンスモードの確認
uint8_t spiMem_SqMode();

//--- SPI-ROMのステータスの取得
uint8_t SPI_Rom_RdStat();

/****  ターミナルコマンド (*strはコマンドライン文字列) *****/
//----- Wコマンド   W[aaaa][,[d0,・・[,]]]
uint16_t spiMem_cmd_W(char *str);

//---- Rコマンド  R[aaaa][,n]
uint16_t spiMem_cmd_R(char *str);

//---- WSQ (連続書込モード)
uint16_t spiMem_cmd_WSQ(char *str);

//---- Qコマンド(連続書込モードの解除)   Q
void spiMem_cmd_Q(char *str);

//---- U(dump)コマンド    U[aaaa]
//       (128バイトのデータをDBuf[]に読み出す)
int spiMem_cmd_U(char *str);

//---- P(Page)コマンド    P[W/R][aaaa]
//        (DBuf[]の128バイトの表示と、読み書き)
int spiMem_cmd_P(char *str);

//---- Kコマンド(漢字表示コマンド)   K[H}
int spiMem_cmd_K(char *str);
【spi_Mem3.cファイル】

/******************************(spi_Mem3.c)***************
 *	SPI接続メモリ(25LC1024/23LCV1024)読み書きライブラリ
 ***********************************************************/

#include  
#include  
#include  "myProject.h"
#define   MBFSIZE 130                           // メモリ操作用バッファーサイズ

//=== グローバル変数 ============
char     Dlm[] = ",";                           // 文字列区切りデリミタ
char     SBuf[20];                              // 文字列処理用バッファー

//--- SPIメモリー用
static uint32_t CrtAdr = 0;                     // カレントアドレス
static uint8_t  DBuf[MBFSIZE];                  // ページメモリ用バッファー
static uint8_t  SqMode = 0;                     // シーケンスモードフラグ
static char     lstCmd;                         // 最終コマンド
static uint8_t  spiRom = 1;                     // 1:spiEEPRom、0:spiRam

/*************************************
 *  SPIC EEPROM function
 **************************************/
//---- ROMステータスの読み出し
uint8_t SPI_Rom_RdStat(){                       // ROMのみ使用
    uint8_t stat;
    CS0_SetLow();
    SPI1_ExchangeByte(SPIROM_RD_STATS);
    stat = SPI1_ExchangeByte(0xAA);             // 0xAAはダミー
    CS0_SetHigh();
    return stat;
}

//---- コマンドと24ビットアドレスを送信 
void sendAdr(uint8_t cmd, uint32_t adr){
    if(spiRom) CS0_SetLow();                    // spiRom(25LC1024)選択
    else       CS1_SetLow();                    // spiRam(23LCV1024)選択
    SPI1_ExchangeByte(cmd);                     // send Command
    SPI1_ExchangeByte((uint8_t)(adr>>16));
    SPI1_ExchangeByte((uint8_t)(adr>>8));
    SPI1_ExchangeByte((uint8_t)adr);
} 

//-----  アドレスadrから、1バイトを読み出す
uint8_t SPI_Mem_Read(uint32_t adr){
    uint8_t dat;
    if(adr < 0x80000) spiRom = 1;               // spiRom(25LC1024)指定
    else              spiRom = 0;               // spiRam(23LCV1024)指定
    sendAdr(SPIMEM_READcmd,adr);                // send Read_CMD & Address
    dat = SPI1_ExchangeByte(0xAA);
    if(spiRom) CS0_SetHigh();                   // spiRomの場合
    else       CS1_SetHigh();                   // spiRamの場合
    return dat;
}

//-----  アドレスadrに、1バイトdatを書き込む
uint8_t PI_Mem_Write(uint32_t adr, uint8_t dat){
    if(adr < 0x80000){
        spiRom = 1;                             // spiRom(25LC1024)指定
        CS0_SetLow();
        SPI1_ExchangeByte(SPIROM_WR_ENABL);     //Set WriteEnableBit
        CS0_SetHigh();
    }else              spiRom = 0;              // spiRam(23LCV1024)
    sendAdr(SPIMEM_WRITEcmd,adr);               // send W_CMD & Address
    SPI1_ExchangeByte(dat);
    if(spiRom){                                 // spiRomの場合
        CS0_SetHigh();
        __delay_ms(6);
    }else{                                      // spiRamの場合
        CS1_SetHigh();
    }
    return dat;
}

//-----  アドレスadrからcntバイトをary[]に読み出す
void SPI_Mem_NRead(uint32_t adr, uint8_t *ary, uint16_t cnt){
    if(adr < 0x80000) spiRom = 1;               // spiRom(25LC1024)指定
    else              spiRom = 0;               // spiRam(23LCV1024)指定
    sendAdr(SPIMEM_READcmd,adr);                // send R_CMD & Address
    SPI1_ReadBlock(ary, cnt);                   // block read
    if(spiRom){
        CS0_SetHigh();
        while(SPI_Rom_RdStat() & 1);
    }else{
        CS1_SetHigh();
    }
}

//-----  アドレスadrからary[]のcntバイトを書き込む
void SPI_Mem_NWrite(uint32_t adr, uint8_t *ary, uint16_t cnt){
    if(adr < 0x80000){
        spiRom = 1;                             // spiRom(25LC1024)指定
        CS0_SetLow();
        SPI1_ExchangeByte(SPIROM_WR_ENABL);     // SetWriteEnableBit
        CS0_SetHigh();
    }else{
        spiRom = 0;                             // spiRam(23LCV1024)指定
    }
    sendAdr(SPIMEM_WRITEcmd,adr);               // send W_CMD & Address
    SPI1_WriteBlock(ary,cnt);                   //  block write
    if(spiRom){
        CS0_SetHigh();
        while(SPI_Rom_RdStat() & 1);
    }else{
        CS1_SetHigh();
    }
}

/****** 汎用サブルーチン ********************/
//---- ページバッファープリント
void prt_PBf(){
    uint8_t i;
    for(i = 0; i < 128; i++){                   // 16文字x8行字表示
        #ifdef VBA
            if(i % 16 == 0) printf("\r");
        #else
            if(i % 16 == 0) printf("\n\r");
        #endif
        printf(" %02X",DBuf[i]);
    }
    puts("\r");
}

//---- 16進文字列を10進数に変換
uint32_t my_xtoi(char *str){
    uint32_t dec;
    dec = strtoul(str,NULL,16);
    return (uint32_t)dec;
}

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

    lstCmd = str[0];
    if(strlen(str)==1){                         // 'W'のみなら
        SqMode = 1;                             // 連続書込モードにセット
        #ifndef VBA
        	puts("SqMode ON\n\r");
        #endif
        return 0;                               // データは書き込まない
    }
    last = (uint8_t)strlen(str)-1;              // 文字列の行末位置を取得
    if(str[last] == ','){                       // 行末がコンマなら
        SqMode = 1;                             // 連続書込モードにセット
        #ifndef VBA
        	puts("SqMode ON\n\r");
        #endif
        str[last]='\0';                         // 行末のコンマを消す
    }
    if(str[1]!=','){                            // 第2文字がコンマか?
        pt = strtok(str+1,Dlm);                 // コマンドの次文字から
        if(pt != NULL){                         // アドレスデータがある
            res = my_xtoi(pt);
            CrtAdr = res;
        }
        pt = strtok(NULL,Dlm);                  // 次文字列取込
    }else{
        pt = strtok(str+1,Dlm);                 // 文字列取込
    } 
    do{
        if(pt != NULL){                         // データがあるか?
            res = my_xtoi(pt);
            dt = (uint8_t)res;
             if(lstCmd=='W'){
                SPI_Mem_Write(CrtAdr,dt);       // データを書き込む
            }else if(lstCmd == 'S'){
                DBuf[CrtAdr & 0x7F]= dt;  
            }
            sprintf(SBuf,"%05lX < %02X",CrtAdr,dt);
            #ifdef VBA
                printf("%s\r",SBuf);
            #else
                printf("%s\n\r",SBuf);
            #endif
            prtHstr_LnClr(0,16,SBuf);
            CrtAdr++; cnt++; 
            pt = strtok(NULL,Dlm);              // 次文字へ
        }
    }while(pt != NULL);                         // データがあるだけ繰返す
    return cnt;                                 // 書き込んだ文字数を返す
}

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

    lstCmd = str[0];
    if(strlen(str) > 1){
        if(str[1]==','){
            pt = strtok(str+2,Dlm);
            if(pt != NULL){                     // データ無し?
                res = my_xtoi(pt);
                n = (uint16_t)res;
            }
        }else{
            pt = strtok(str+1,Dlm);
            if(pt != NULL){                     // addressがある?
                res = my_xtoi(pt);
                CrtAdr = res;
            }
            pt = strtok(NULL,Dlm);             	// 次文字へ
            if(pt != NULL){                     // データ無し?
                res = my_xtoi(pt);
                n = (uint16_t)res;
            }
        }
    }
    for(i = 0; i < n; i++ ){
        dt = SPI_Mem_Read(CrtAdr);              // データを読み出す
        sprintf(SBuf,"%05lX > %02X",CrtAdr,dt);
        #ifdef VBA
        	printf("%s\r",SBuf);
        #else
        	printf("%s\n\r",SBuf);
        #endif
        prtHstr_LnClr(0,16,SBuf);
        CrtAdr++; cnt++;
    }
    SqMode = 0;
    return cnt;                                 // 読込んだデータ数を返す
}

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

    pt = strtok(str,Dlm);
    while(pt != NULL){                          // データがあるだけ繰返す
        res = my_xtoi(pt);
        dt = (uint8_t)res;
        if(lstCmd == 'W'){
            SPI_Mem_Write(CrtAdr,dt);          // データを書き込む
        }else if(lstCmd=='S'){
			DBuf[CrtAdr & 0x7F]= dt;  
        }
        sprintf(SBuf,"%05lX < %02X",CrtAdr,dt);
        #ifdef VBA
        	printf("%s\r",SBuf);
        #else
        	printf("%s\n\r",SBuf);
        #endif
        prtHstr_LnClr(0,16,SBuf);
        CrtAdr++; cnt++;
        pt = strtok(NULL,Dlm);                  // 次文字列へ
    }
    return cnt;                                 // 書込んだデータ数を返す
}

//---- Qコマンド(連続書込モードの解除)   Q
void spiMem_cmd_Q(char *str){
    lstCmd = str[0];
	SqMode = 0;
	#ifndef VBA
		puts("SqMode OFF\r");
	#endif
}

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

    lstCmd = str[0];
    pt = strtok(str+1,Dlm);
    if(pt != NULL){                             // アドレス有り?
        res = my_xtoi(pt);
        CrtAdr = res;
    }
    ad = CrtAdr & 0xFFFF80;                     // 128バイト単位に 
    SPI_Mem_NRead(ad, DBuf, 128);               // 128バイトをDBuf[]に読出
    sprintf(SBuf,"%05lX - %05lX", ad, ad+127);
    #ifdef VBA
      	printf("%s",SBuf);
    #else
       	printf("%s\r",SBuf);
    #endif
    prtHstr_LnClr(0,16,SBuf);
    prt_PBf();
    SqMode = 0;
    return 0;
}

//---- P(Page)コマンド    P[R/W][aaaa]
//       DBuf[]の128バイトの表示とメモリに読み書き)
int spiMem_cmd_P(char *str){
    char     *pt;                               // 文字列操作用ポインタ
    uint32_t res;                               // Hex文字数値変換結果
    uint32_t ad;                                // 指定アドレス

    lstCmd = str[0];
    if(strlen(str)==1){
        printf("PageBuffer");
        prt_PBf();
        return 0;
    }
    if(str[1]=='R'){
        spiMem_cmd_U(str+1);
        return 0;
    }
    if(str[1] != 'W') return -1;                // 第2文字がW?
    pt = strtok(str+2,Dlm);
    if(pt != NULL){                             // アドレス有り?
        res = my_xtoi(pt);
        CrtAdr = res;
    }
    ad = CrtAdr & 0xFFFF80;                     // 128バイト単位に
    SPI_Mem_NWrite(ad,DBuf,128);                // DBuf[]の128バイト書込
    sprintf(SBuf,"PW:%05lX - %05lX",ad,ad+127);
    #ifdef VBA
      	printf("%s\r",SBuf);
    #else
       	printf("%s\n\r",SBuf);
    #endif    
    prtHstr_LnClr(0,16,SBuf);
    SqMode = 0;    
    return 0;
}

//----  シーケンスモードの確認
uint8_t spiMem_SqMode(){
	return SqMode;
}

//---- K(漢字)表示コマンド  K[H] 
int spiMem_cmd_K(char *str){
    char     *kp;                               // 文字列操作用ポインタ
    uint8_t i;
    kp = (char *)DBuf;
    if(str[1] == 'H'){                          // 第2文字がHか?
        for(i = 0; i < 8; i++){
            gLCD_nk16X(8*i,32,kp+16*i,8);
        }
    }else{
        for(i = 0;i < 4; i++){
            gLCD_nk16X(16*i,32,kp+32*i,16);
        }      
    }
    SqMode = 0;
    return i;
}

 
【AQM1248A_v3.hファイル】 AQM1248A_v3.c/h + Font_5x7.h(zip)

/******************************(AQM1248A_v3.h)************
 *   Grafic LCD  AQM1248A_m.h 用ライブラリ(FONT別)
 **********************************************************/
/*---  G_LCDを初期化する */
void gLCD_int(void);

/*---  G_LCDのRAMの書込みアドレスを指定する
 *	  表示文字位置(xpos,ypos) */
void gLCD_posyx(uint8_t xpos, uint8_t ypos);

/*---  G_LCDのRAMを全消去(指定データで埋める)
 *	  埋めたい1バイトデータ(dat) */
void gLCD_clr(char dat);

/*---  G_LCDにchrコードの文字パターンを表示
 *    表示位置(ypos,xpos)、表示文字(ch)
 *  ・戻り: 次表示X文字位置  */
uint8_t gLCD_chrX(uint8_t xpos, uint8_t ypos, char ch);

/*---  文字列strをG_LCDに表示する
 *	  表示位置(xpos,ypos)、表示文字列(str)
 * ・戻り: 次表示X文字位置  */
uint8_t gLCD_strX(uint8_t xpos, uint8_t ypos, char *str);

/*---  ビットパターンをG_LCDに表示する
 *	表示位置(xpos, ypos)、パターン(*ptn),バイト数(n)
 *  ・戻り: 次表示X文字位置 */
uint8_t gLCD_ptnX(uint8_t xpos, uint8_t ypos, char *ptn, uint8_t n);

/*---  指定したdatで指定数nだけ表示
 *	表示位置(xpos, ypos)、データ(dat)・・1バイト, 転送数(n) 
 *  ・戻り: 次表示X文字位置 */
uint8_t gLCD_clrX(uint8_t xpos, uint8_t ypos, char dat, uint8_t n);

/*--- バイト単位で16ドットパターン(漢字など)の表示
 *	  表示位置(xpos, ypos)、データ配列(k)
 *    フォントアドレス(*pKj)、 横ドット数(cdt) 
 *  ・戻り: 次表示X文字位置 */
uint8_t gLCD_nk16X(uint8_t xpos, uint8_t ypos, char *pKj, uint8_t cdt);

//---- バイtト単位で半角(8x16)文字表示(次xpos位置を返す)
/*	  表示位置(xpos, ypos)、半角文字コード(chCode)
 *  ・戻り: 次表示X文字位置 */
uint8_t gLCD_HchrX(uint8_t xpos, uint8_t ypos, uint8_t chCode);

//---- バイト単位で半角文字列表示(次xpos位置を返す)-----
/*	  表示位置(xpos, ypos)、半角文字列(*str)
 *  ・戻り: 次表示X文字位置 */
uint8_t gLCD_HstrX(uint8_t xpos, uint8_t ypos, char *str);

//---- バイト単位で行をクリアして半角文字列表示(次xpos位置を返す)
/*	  表示位置(xpos, ypos)、半角文字列(*str)
 *  ・戻り: 次表示X文字位置 */
uint8_t prtHstr_LnClr(uint8_t xpos, uint8_t ypos, char* str);

/*========================================*
 *     ドット単位位置で描画               *
 *========================================*/
/*---  ドット単位で点を描く
 *    表示位置(xpos, ypos)、表示色(col、0:白/1:黒/8:反転)*/
 void gLCD_PSet(uint8_t xpos, uint8_t ypos, uint8_t col);

/*---  ドット単位で文字を描く(次xpos位置を返す)
 *    表示位置(xpos, ypos)、表示文字コード(ch)
 *    表示色(col、0:白/1:黒/8:反転)
 * ・戻り: 次表示X文字位置 */
 uint8_t gLCD_PutChr(uint8_t xpos, uint8_t ypos, char ch, uint8_t col);

/*---  ドット単位で文字列を描く(次xpos位置を返す)
 *    表示位置(xpos, ypos)、表示文字列(*str)
 *    表示色(col、0:白/1:黒/8:反転)
 *  ・戻り: 次表示X文字位置 */
 uint8_t gLCD_PutStr(uint8_t xpos, uint8_t ypos, char *ptn, uint8_t col);

/*-------ドット単位でパターンを描く(次xpos位置を返す)
 *    表示位置(xpos, ypos)、表示パターン(*ptn)・・バイト単位
 *    転送数(n)、表示色(col、0:白/1:黒/8:反転)
 *  ・戻り: 次表示X文字位置 */
 uint8_t gLCD_PutPtn(uint8_t xpos, uint8_t ypos, char *ptn, uint8_t n, uint8_t col);

/*----------ドット単位で直線を描く
 *    開始位置(x0,y0)、終了位置(x1,y1)、
 *    表示色(col、0:白/1:黒/8:反転)*/
 void gLCD_Line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t col);

/*--- バイト単位で16ドットパターン(漢字など)の表示
 *    表示位置(xpos, ypos)、データ配列(k)
 *    データ要素番号(kj)、 横ドット数(cln)
 *    表示色(col、0:白/1:黒/8:反転)
 *  ・戻り: 次表示X文字位置 */
uint8_t Put_nK16(uint8_t xpos, uint8_t ypos, char *k, uint8_t cln, uint8_t col);

//---- ドット単位で半角文字表示(次xpos位置を返す)
/*    表示位置(xpos, ypos)、半角文字コード(chCode)
 *    表示色(col、0:白/1:黒/8:反転)
 *  ・戻り: 次表示X文字位置 */
uint8_t Put_HchrX(uint8_t xpos, uint8_t ypos, uint8_t chCode,uint8_t col);

//---- ドット単位で半角文字列を表示(次xpos位置を返す)
/*    表示位置(xpos, ypos)、半角文字列(*str)
 *    表示色(col、0:白/1:黒/8:反転)
 *  ・戻り: 次表示X文字位置 */
uint8_t Put_HstrX(uint8_t xpos, uint8_t ypos, char *str, uint8_t col);

 
【AQM1248A_v3.cファイル】

/***********************************(AQM1248A_v3.c)*******
 *     AQM1248A グラフィックライブラリ(spi-vRam付き)
 **********************************************************/

#include "myProject.h"
#include "Font_5x7.h"

#define VRAM_ADR    0x80000
#define LCG_C_SIZE  128
#define HASC_OFS    0x00200
#define H_BLANK     0x007F0

static uint8_t vBf[32];                         // フォントパターン用バッファー

//--- SPI-vRam アクセス関数
uint8_t vRam_read(uint8_t xpos, uint8_t ypos){
	uint32_t adr;
	adr = VRAM_ADR + (uint32_t)ypos * LCG_C_SIZE + xpos;
	return SPI_Mem_Read(adr);
}

void vRam_write(uint8_t xpos, uint8_t ypos, uint8_t dat){
	uint32_t adr;
	adr = VRAM_ADR + (uint32_t)ypos * LCG_C_SIZE + xpos;
	SPI_Mem_Write(adr, dat);
}

void vRam_Nread(uint8_t xpos,uint8_t ypos,char *ptn,uint8_t n){
	uint32_t adr;
	adr = VRAM_ADR + (uint32_t)ypos * LCG_C_SIZE + xpos;
	SPI_Mem_NRead(adr,(uint8_t *)ptn,n);
}

void vRam_Nwrite(uint8_t xpos,uint8_t ypos,char *ptn,uint8_t n){
	uint32_t adr;
	adr = VRAM_ADR + (uint32_t)ypos * LCG_C_SIZE + xpos;
	SPI_Mem_NWrite(adr,(uint8_t *)ptn,n);
}

//-------- G-LCDを初期化 ------------------------------------
void gLCD_int (void){
    gCS_SetLow();                               // gLCDセレクト有効
    gRS_SetLow();                               // コマンドデータ指定
    SPI1_ExchangeByte(0xAE);                    // Display = OFF
    SPI1_ExchangeByte(0xA0);                    // ADC = normal
    SPI1_ExchangeByte(0xC8);                    // C.output = revers
    SPI1_ExchangeByte(0xA3);                    // bias = 1/7
    SPI1_ExchangeByte(0x2C);                    // power control 1
    __delay_ms(2);                              // 2mS遅延
    SPI1_ExchangeByte(0x2E);                    // power control 2
    __delay_ms(2);                              // 2mS遅延v
    SPI1_ExchangeByte(0x2F);                    // power control 3
    SPI1_ExchangeByte(0x23);                    // Vo ratio set
    SPI1_ExchangeByte(0x81);                    // E-volume mode
    SPI1_ExchangeByte(0x1C);                    // E-volume value
    SPI1_ExchangeByte(0xA4);                    // 全点灯しない
    SPI1_ExchangeByte(0x40);                    // start line = 0
    SPI1_ExchangeByte(0xA6);                    // 白黒反転しない
    SPI1_ExchangeByte(0xAF);                    // Display = ON
    gCS_SetHigh();                              // gLCDセレクト無効
}

//-------- G-LCDのデータを全消去(指定データで埋める)---
void gLCD_clr (char dat){
    uint8_t x, y;
    gCS_SetLow();                               // gLCDセレクト有効
    for(y = 0; y < 6; y++){
        gRS_SetLow();                           // コマンド指定
        SPI1_ExchangeByte(0xB0 + y);
        SPI1_ExchangeByte(0x10);
        SPI1_ExchangeByte(0x00);
        gRS_SetHigh();                          // 表示データ指定
        for(x = 0; x < 128; x++){
            SPI1_ExchangeByte(dat);
        }
    }
    gCS_SetHigh();                              // gLCDセレクト無効
    for(y = 0; y < 6; y++){
        for(x = 0; x < 128; x++){
            vRam_write(x,y,dat);                // vRamクリア
        }
    }
}

//-------- カーソル位置指定 -----------------------------------
void gLCD_posXY(uint8_t xpos, uint8_t ypos){
    gCS_SetLow();                               // チップセレクト有効
    gRS_SetLow();                               // コマンド指定
    SPI1_ExchangeByte(0xB0 | (ypos >> 3));
    SPI1_ExchangeByte(0x10 | (xpos >> 4));
    SPI1_ExchangeByte(xpos & 0x0F);
    gCS_SetHigh();                              // チップセレクト無効
}

//-------- バイト単位で文字表示(次xpos位置を返す) ---------
uint8_t gLCD_chrX(uint8_t xpos, uint8_t ypos, char chr){
    uint8_t i, sx, yAdr, ptn;
    chr -= 0x20;                                //配列アドレスを計算
    gLCD_posXY(xpos, ypos);                     //表示位置を指定
    sx = xpos;                                  // posxを保存
    yAdr = ypos >> 3;
    gCS_SetLow();                               // チップセレクト有効
    gRS_SetHigh();                              // 表示データ指定
    for(i = 0; i < 5; i++) {                    //データを順に取得
        ptn = Font[chr][i];
        if(ptn == 0xFF)  break;                 //幅狭文字なら抜ける
        vBf[i] = ptn;
        SPI1_ExchangeByte(ptn);
        xpos++;
    }
    vBf[i] = 0;
    SPI1_ExchangeByte(0);                       //文字間隔を空ける
    xpos++;
    gCS_SetHigh();                              // チップセレクト無効
    vRam_Nwrite(sx,ypos,(char *)vBf, i);        // vRamに書き込む 
    return xpos;                                //次表示位置を返す
}

//-------- バイト単位で文字列表示(次xpos位置を返す)-----
uint8_t gLCD_strX(uint8_t xpos, uint8_t ypos, char *str){
    while(*str)  xpos = gLCD_chrX(xpos, ypos, *str++);
    return xpos;                                //次表示位置を返す
}

//-------- バイト単位でパターンを表示(次xpos位置を返す)
uint8_t gLCD_ptnX(uint8_t xpos, uint8_t ypos, char *ptn, uint8_t n){
    uint8_t i, yAdr;
    gLCD_posXY(xpos, ypos);                     // 表示位置を指定
    gCS_SetLow();                               // チップセレクト有効
    gRS_SetHigh();                              // 表示データ指定
    yAdr = ypos >> 3;
    for(i = 0; i < n; i++){
         SPI1_ExchangeByte(*(ptn + i));
    }
    gCS_SetHigh();                              // チップセレクト無効
    vRam_Nwrite(xpos,ypos,ptn,n);
    return xpos + n;                            // 次表示位置を返す
}

//---- バイト単位でn個の指定データで埋める(次xpos位置を返す)
uint8_t gLCD_clrX(uint8_t xpos, uint8_t ypos, char dat, uint8_t n){
    uint8_t i, yAdr;
    gLCD_posXY(xpos,ypos);                      // 表示位置を指定
    gCS_SetLow();                               // チップセレクト有効
    gRS_SetHigh();                              // 表示データ指定
    yAdr = ypos >> 3;
    for(i = 0; i < n; i++) {
        SPI1_ExchangeByte(dat);
    }
    gCS_SetHigh();                              // チップセレクト無効
    for(i=0;i<// 次開始位置を返す
}

//---- バイト単位で(縦)16ドットパターン(漢字など)の表示
/*	xpos: X位置、	ypos: Y位置
 *	*pKj: 漢字パターンデータポインタ、 cdt: 漢字横ドット数
 *---------------------------------------------------- */
uint8_t gLCD_nk16X(uint8_t xpos, uint8_t ypos, char *pKj, uint8_t cdt){
 	gLCD_ptnX(xpos, ypos,(char *)pKj, cdt); 
	xpos = gLCD_ptnX(xpos, ypos+8, (char *)(pKj + cdt),cdt);
	return xpos;
}

//---- 半角(8x16)文字表示(次xpos位置を返す)-----
uint8_t gLCD_HchrX(uint8_t xpos, uint8_t ypos, uint8_t chCode){
    uint32_t adr;
    if((chCode >= 0x20) & (chCode < 0x7F)){
        adr = (chCode - 0x20) * 16 + HASC_OFS;
    }else{
        adr = H_BLANK;                          // 半角ブランク表示
    }
    SPI_Mem_NRead(adr,(uint8_t *)vBf,16);
    xpos = gLCD_nk16X(xpos, ypos, (char *)vBf, 8); 
    return xpos;
}

//-------- バイト単位で半角文字列表示(次xpos位置を返す)-----
uint8_t LCD_HstrX(uint8_t xpos, uint8_t ypos, char *str){
    while(*str)  xpos = gLCD_HchrX(xpos, ypos, *str++);
    return xpos;                                //次表示位置を返す
}

//--- 行をクリアして半角文字列表示(次xpos位置を返す)
uint8_t prtHstr_LnClr(uint8_t xpos, uint8_t ypos,char* str){
    gLCD_clrX(0,ypos  ,0,LCG_C_SIZE);
    #ifdef FONT_ROM
        gLCD_clrX(0,ypos+8,0,LCG_C_SIZE);
        return  gLCD_HstrX(xpos,ypos,str);
    #else
        return  gLCD_strX(xpos,ypos,str);
    #endif
}

/****** ドット単位位置で描画 ******/
//----------ドット単位で点を描く----------------------
void gLCD_PSet(uint8_t xpos, uint8_t ypos, uint8_t col){
    uint8_t yAdr, yBit;                         // yアドレス、ビット位置
    uint8_t ptn = 0x01;                         // ビットパターン
    uint8_t dat;
    if((xpos > 127) || (ypos > 47))  return;
    dat = vRam_read(xpos, ypos);
    yAdr = ypos >> 3; yBit = ypos & 0x07;
    ptn <<= yBit;
    switch(col){
        case 0:	dat &= (~ptn);	break;
        case 1: dat |= ptn;		break;
        case 8: dat ^= ptn;		break;
    }
    gLCD_posXY(xpos,ypos);  
    gCS_SetLow();                               // チップセレクト有効
    gRS_SetHigh();                              // 表示データ指定
    SPI1_ExchangeByte(dat);
    gCS_SetHigh();                              // チップセレクト無効
    vRam_write(xpos, ypos, dat);
}

//-------ドット単位で文字を描く(次xpos位置を返す)-------
uint8_t gLCD_PutChr(uint8_t xpos, uint8_t ypos, char ch, uint8_t col){
    uint8_t i, j, ptn, msk;                     //ビットマスクデータ
            //有効フォントデータでないなら何もしない
    if((ch < 0x20)||(ch > 0x7f)) return xpos;
    ch -= 0x20;                                 //配列アドレスを計算
    for(i = 0; i < 5; i++){
        msk = 0x01;
        ptn = (uint8_t)Font[ch][i];
        if(ptn == 0xFF) break;                  //幅狭文字なら抜ける
        for(j = 0; j < 8; j++){
            if(ptn & msk)    gLCD_PSet(xpos + i,ypos + j,col);
            msk <<= 1;
        }
    } 
    return xpos + i + 1;
}

//-------ドット単位で文字列を描く(次xpos位置を返す)---
uint8_t gLCD_PutStr(uint8_t xpos, uint8_t ypos, char * str, uint8_t col){
    while(*str)                                 //文字列終端まで継続
        xpos = gLCD_PutChr(xpos,ypos,*str++,col);
    return xpos;                                //次表示位置を返す
}

//-------ドット単位でパターンを描く(次xpos位置を返す)-------
uint8_t gLCD_PutPtn(uint8_t xpos, uint8_t ypos, char * ptn, uint8_t n, uint8_t col){
    uint8_t i, j, msk;                          //ビットマスクデータ
    for(i = 0; i < n; i++){
        msk = 0x01;
        for(j = 0; j < 8; j++){
            if(*ptn & msk)    gLCD_PSet(xpos+i,ypos+j,col);
            msk <<= 1;
        }
        ptn++;
    }
    return xpos + i;
}

// --- ABS、SWAP関数定義

void swap_uint8_t(uint8_t *a, uint8_t *b){
	uint8_t tmp; tmp = *a; *a = *b; *b = tmp;
}
#define ABS(a)    (((a)>0) ? (a) : -(a))

//----------ドット単位で直線を描く-------------------
void gLCD_Line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t col){
    uint8_t steep, x, y, tmp;
    int   ystep, deltax, deltay, error;
    steep = (ABS(y1 - y0) > ABS(x1 - x0));
    if(steep){    swap_uint8_t(&x0,&y0); swap_uint8_t(&x1,&y1); }
    if(x0 > x1){  swap_uint8_t(&x0,&x1); swap_uint8_t(&y0,&y1); }
    deltax = x1 - x0;                           //  傾き計算
    deltay = abs(y1 - y0);
    error = 0;
    y = y0;
    if(y0 < y1) ystep = 1; else ystep = -1;
    for(x = x0; x < x1 + 1; x++){
        if(steep) gLCD_PSet(y,x,col); 
        else      gLCD_PSet(x,y,col);
        error += deltay;
        if((error << 1) >= deltax){
            y += ystep;
            error -= deltax;
        }
    }
}

//---- ドット単位で(縦)16ドットパターンの表示(次xpos位置を返す)
/*	xpos: X位置、	ypos: Y位置,		col: 表示モード
 *	*pKj: 漢字パターンデータポインタ、	cdt: 漢字横ドット数
 *---------------------------------------------------- */
uint8_t Put_nK16(uint8_t xpos, uint8_t ypos, char *pKj, uint8_t cdt, uint8_t col){
 	gLCD_PutPtn(xpos, ypos, (char *)pKj, cdt, col); 
	xpos = gLCD_PutPtn(xpos, ypos+8, (char *)(pKj + cdt),cdt, col);
	return xpos;
}

//---- ドット単位で半角文字表示(次xpos位置を返す)
uint8_t Put_HchrX(uint8_t xpos, uint8_t ypos, uint8_t chCode,uint8_t col){
    uint32_t adr;
    if((chCode >= 0x20) & (chCode < 0x7F)){
        adr = (chCode - 0x20) * 16 + HASC_OFS;
    }else{
        adr = H_BLANK;                          // 半角ブランク
    }
    SPI_Mem_NRead(adr,(uint8_t *)vBf,16);
    xpos = Put_nK16(xpos, ypos, (char *)vBf, 8, col);       
    return xpos;
}

//---- ドット単位で半角文字列を表示(次xpos位置を返す)
uint8_t Put_HstrX(uint8_t xpos, uint8_t ypos, char *str, uint8_t col){
    while(*str)  xpos = Put_HchrX(xpos, ypos, *str++, col);
    return xpos;                                //次表示位置を返す
}

【EUSART】   EUSARTの設定 (abc900)
USBシリアル通信の設定
【PICライブラリ】 ライブラリの使い方 (abc840)
使用するライブラリの追加など


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


フォントデータのROM化(1) 合字とは PICミニBB(14)_フォントROMで半角文字表示