Vol.914 14.Mar.2025

4Kモニターは快適 PICでSDカードを使う

K やはり4Kモニターは快適

by fjk

 abc911でwindows11マシンを入手したが、モニターはWQHD(2560x1440)のままだった。
 折角マシンを新調したので、新マシンのモニターも4Kにすることにした。
 新モニターは元のWQHDモニターの場所に置くことにし、以下のスペックで検討した。

で、市内のパソコンショップを回ってみたが、要求仕様にマッチするものが見つからず、最終的にJAPANNEXTのJN-i283U-H(Amazon価格で31,980円)に決めた。詳細スペック
 商品は、注文の翌日の朝に届いた(早!)。
 早速、組み立てて、パソコンにつないでみたところ、

  1. HDMIx2はうまく表示できたが、DPx2はどちらも映らなかった。
  2. そこで、JAPANNEXTのカスタマーサービスにメールを入れた。
  3. しかし、添付のマニュアルを見てみると、「設定を工場出荷時にリセット」というメニューがあり、これを実行してみると、今度は2つのDPポート入力でも画面表示ができるようになった。
  4. ということで、カスタマーサービスには、「自己解決しました」と連絡。

やはり、4K画面は快適ですね。そして、WQHDモニターは女房のパソコンのモニター(フルHD)と交換しました。

JN-i283U-Hの寸法

他の4Kモニターに並べて


P PICでSDカードを使う(1) 〜FatFsライブラリで読み書き

by fjk

 メモリの少ないPICにROMやRAMを使ってメモリを増やしてきたが、画像データなどもっと大きなデータを使いたくなり、SDカードが使えないかトライした。
 今回、使用したSDカードソケットはAdafruit_MicroSD_Card_Breakout+(@1,602、スイッチサイエンス ADA-254)で、3.3Vまたは5Vのどちらでも使えるモジュールである。(SDカードそのものに直接5Vを加えると壊れるので、3.3Vで使用すること!)
 SDカードのPICでの使い方は「C言語&MCCによるPICプログラミング大全」(後閑哲也、技術評論社)を参考にした。16Fシリーズの8ビットPICを利用した場合、FatFsライブラリはPIC16F18857/18877でないとメモリ不足で動作しないとあったので、28pinのPIC16F18857(ROM:32KW[14bit]/RAM:4KB)を用いた(実際にFatFS付でコンパイルしてみると、メモリ使用量はROM:約20KW/RAM:約3KB)。
【PIC16F18857の概要】
・ 最高動作速度: 32 MHz
・ 割り込み機能
・ 16 レベルのハードウェア スタック
・ タイマー:TMR2/4/6(8bit)、 TMR0/1/3/5(16it)
・ メモリ:56 KB(ROM)、4 KB(SRAM)、256B(EEPROM)
・ 4 つの構成可能ロジック セル (CLC)
・ 3 つの相補波形ジェネレーター (CWG)
・ 5 つのCCP モジュール
・ 2つの10 ビット PWM
・ 数値制御発振器 (NCO)
・ データ信号変調器 (DSM)
・ 通信: EUSART、2 つの SPI、2 つの I2C
・ 最大 36 個の I/O ピン
・ 周辺ピン選択 (PPS)
・ 計算機能付きADコンバーター (ADC2)
・ 2 つのコンパレーター (COMP) 
・ 2 つの信号測定タイマー (SMT)
・ 電圧リファレンス:1.024、2,048、4.096V (FVR)
・ 5 ビット DAコンバーター (DAC)
・ 巡回冗長検査 (CRC/SCAN)

PIC16F18857のピン配置
【FatFsの概要と使い方】
1.MMCにFatFsとSD_Cardを追加
FatFsは標準のMMCのDeviceに無いので、FatFsとSD_Cardライブラリを追加する必要がある。 DeviceResourcesのContentManager/Libraryを選ぶと、ライブラリ・リストが表示されるので、 「FatFsFAT_System」を選び、Apply。
同様に「SD/MMC_Card」もapply。
これでDevice_Resorcesに、FatFsとSD_Cardが追加され、MMCで使えるようになる。

ライブラリ・リスト
2.MMCの設定
@System:
Osc=HFINTOSC、Clock=32MHz、SystemDevider=1
AFatFs:
Configurationで「SD_Card]を選択し、insert。SDCardDriverが追加される。
 (さらにオプションも選べるが、デフォルトままでOK。ファイル名は8.3形式)
BMMSPx:
FoudationSeriesの下にあるSPIMASTERで、SPIをMSSP2に、SPIModeをMODE3に、
SPISDFASTのSpeedを4000にする(下のMSSP2は自動でセットされる)。
CSD Card:
「EnableChipSelect」以外のチェックを外す。
DEUSART:
Baud Rateを115200に、Enable EUSART interruptをチェック
ETMR0:
prescaler=1:64、mode=16-bit、Source=FOSC/4、Period=1S、Interruptにチェック。
SoftwareSettingsのCallbackFuctionRate = 1 (1s) に
FPinModule:
以下のように設定(スイッチ入力は未使用)


Pin Module

FatFS
 

MSSP
 

SD_CARD

EUSART

TMR0


回 路 図 (PIC16F18857)

ブレッドボード配線状況
(左上の5Pコネクタはスペーサとして利用)

※プログラムの一部を改良・変更(3/15)
 ・Eコマンドで終了するとリセットが必要なので、X、Cコマンドでカウンタ表示をON/OFFできるようにした。
 ・共通で使える部分はサブルーチン化。
 ・使っていない変数があったので削除。

【実行例】
 プログラムが起動すると、1秒ごとのカウンター値を表示。ターミナルからコマンドを送ると、SDカードへの書き込み/読み込みができる。

 ターミナルから使えるコマンドは、(改良後)
R
SDカードから読み出し、表示
W
SDカードへ現在カウンタ値を書き込む
T
SDカードのマウントテスト
X
カウンタ表示OFF
C
カウンタ表示ON
ファイル名(FilNam)の初期値は LOGDATA.TXT とした。参考とした書籍のファイル名と一緒なので、書籍のプログラムで保存したファイルデータもそのまま読み出すことができる。
 
  

なお、C99でコンパイルすると「型が違うとWarning」がいくつか出ることがあるが、コンパイルは可能
 
ターミナル(テラターム)画面例
(受信はAUTOに設定)


【SDカードの読み書きプログラム】 (ステートを使用しない例)
 改良版:abc914-18857a.c(zip)  旧ファイル:abc914-18857.c (zip)


/*******************(abc914-18857a.c)***
 *  SDカードの読み書き   [改良版]
 *  (EUSART割り込み有り)
 ***************************************/
#include "mcc_generated_files/mcc.h"
#include <stdio.h>

//--- File Systme 変数
FRESULT  result;                    // FatFs処理結果
FATFS    drive;                     // ファイルsysオブジェクト
FIL      file;                      // ファイル構造体
		
//--- アプリ変数
char     FilNam[13] = "LOGDATA.TXT";// ファイル名(8.3)
uint16_t Length[2];                 // 送受信用文字数格納配列
char     Buffer[80];                // データ受信用バッファー
char     Msg[40];                   // コメント等送信用文字列
uint8_t  tFlag;                     // タイマーフラグ
uint16_t Counter;                   // タイマーカウンタ

/***************************************
 *  タイマ0 Callback関数 (1秒周期割り込み)
 ***************************************/
void TMR0_Process(void){
    tFlag = 1;                      // フラグセット
}

/***************************************
 *  文字列バッファ出力関数
 ***************************************/
void StrWrite(char * str){
    while(*str != 0){               // '\0'(文字列終り)まで繰り返し
        EUSART_Write(*str++);       // 1文字バッファに出力(送信)
    }
}
//--- EUSARTへ文字列送信(改行付)
void US_Puts(char * str){
    StrWrite(str);
    EUSART_Write('\n');
}

/***************************************
 *  SDカード用汎用関数
 ***************************************/
//--- SDカードのマウント
FRESULT SD_Mount(void){
    uint8_t i = 0;
    FRESULT res;
    do{
        res = f_mount(&drive,"0:",1);     
        i++;
        EUSART_Write('-');
    }while((res != FR_OK) && (i < 10));    // 10回まで試みる
    
    if(res != FR_OK){                      // マウント失敗なら
        US_Puts("** SD Not Mounted !!");
    }else{
        US_Puts("SD Mount OK!");
        LED_SetHigh();
//        __delay_ms(100);
    }
    return res;	
}
//--- SDカードのクローズとアンマウント
void SD_All_Close(void){
    f_close(&file);                         // ファイルクローズ
    f_mount(0, "0:", 0);                    // アンマウント
    US_Puts("closed & Un_Mounted"); 
    LED_SetLow();	
}

/***************************************
 *  コマンド処理
 ***************************************/
//--- SDカードテストコマンド (兼テンプレート)
void SD_cmd_T(void){
    US_Puts("Start Command T");
    if(SD_Mount() == FR_OK){                // SDマウント
    //  set custom function  ------   ここから
        __delay_ms(2000);
    //  ---------------------------   この間にユーザプログラムを記述
        f_mount(0, "0:", 0);                // アンマウント
        US_Puts("Un_Mounted");
    }
    LED_SetLow();
}
//--- SDカードから読込コマンド
void SD_cmd_R(void){
    FRESULT res;
    US_Puts("Start Command R");
    if(SD_Mount() == FR_OK){
        res = f_open(&file, FilNam, FA_READ);       // ファイルオープン
        if(res == FR_OK){
            sprintf(Msg,"Open %s",FilNam);
            US_Puts(Msg);
            do{
                f_read(&file, Buffer, 64, (UINT *)Length); // SDから読込む
                Buffer[Length[0]] = 0;
                US_Puts(Buffer);
            }while(Length[0]!=0);
        }else{
            sprintf(Msg,"** Can't open %s !!",FilNam);
            US_Puts(Msg);           
        }
        SD_All_Close();             // ファイルクローズ&アンマウント
    }
//    LED_SetLow();
}
//--- SDカードへデータ書込コマンド
void SD_cmd_W(void){
    FRESULT res;
    US_Puts("Start Command W");
    if(SD_Mount() == FR_OK){
        res = f_open(&file, FilNam, FA_WRITE | FA_OPEN_APPEND); // ファイルオープン
        if(res == FR_OK){
            sprintf(Msg,"Open %s",FilNam);
            US_Puts(Msg);
            sprintf(Msg, "%07d,", Counter);
            f_write(&file, Msg, 8, (UINT *)Length);   // SDへ書込
            US_Puts(Msg);
        }else{
            sprintf(Msg,"** Can't open %s !!",FilNam);
            US_Puts(Msg);           
        }
        SD_All_Close();       // ファイルクローズ&アンマウント
    }
//    LED_SetLow();
}

/***************************************
 *  メイン関数
 ***************************************/
void main(void){
    uint8_t tMode = 0;                  // タイマカウンタ表示モードフラグ
    char   cmd;                         // 受信コマンド文字
    
    SYSTEM_Initialize();
  // タイマ0 Callback関数定義
    TMR0_SetInterruptHandler(TMR0_Process);
    
    US_Puts("\n==== SD Test ====");
    
  // 割り込み許可
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();
    
  //======= メインループ =========
    while(1){
      // 1秒周期の処理
        if(tFlag == 1){                                 // フラグオンの場合
            LED_Toggle();
            tFlag = 0;                                  // フラグリセット
            if(tMode == 0){
                sprintf(Msg,"Counter = %05d",Counter++);   // カウント値編集
                US_Puts(Msg);                           // 送信
            }
        }
      // コマンド処理
        if(EUSART_is_rx_ready()){                       // 受信ありの場合
            cmd = EUSART_Read();                        // 1文字受信
            sprintf(Msg,"Input = %c\n",cmd);
            US_Puts(Msg);
            switch(cmd){
                case 'T':   SD_cmd_T();  break;         // SDマウントテスト
                case 'R':   SD_cmd_R();  break;         // SDからデータ読出し
                case 'W':   SD_cmd_W();  break;         // SDにデータを書込む
                case 'X':   tMode = 1;   break;         // カウンタ表示OFF
                case 'C':   tMode = 0;   break;         // カウンタ表示ON
                default:    US_Puts("???"); break; 
            }
        }
    }
}
/******  End of File ******/


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


★おまけ
【PIC16F18857で使えるFatFs関数】
FRESULT f_mount (
/*=== 論理ドライブをマウント/アンマウントする ===*/
  FATFS* fs,
/* ファイルシステム オブジェクトへのポインタ (NULL: アンマウント)*/
  const TCHAR* path,
/* マウント/アンマウントする論理ドライブ番号 */
  BYTE opt
/* モードオプション 0:マウントしない (遅延マウント)、1:すぐにマウント */
);
 
 
FRESULT f_open (
/*=== ファイルを開くか作成する ===*/
  FIL* fp,
/* 空のファイルオブジェクトへのポインタ */
  const TCHAR* path,
/* ファイル名へのポインタ */
  BYTE mode
/* アクセスモードとファイルオープンモードフラグ */
);
 
 
FRESULT f_read (
/*=== ファイルからデータを読み込む ===*/
  FIL* fp,
/* ファイルオブジェクトへのポインタ */
  void* buff,
/* データバッファへのポインタ */
  UINT btr,
/* 読み取るバイト数 */
  UINT* br
/* 読み取ったバイト数へのポインタ */
);
 
 
FRESULT f_write (
/*=== ファイルにデータを書き込みます ===*/
  FIL* fp,
/* ファイルオブジェクトへのポインタ */
  const void* buff,
/* 書き込むデータへのポインタ */
  UINT btw,
/* 書き込むバイト数 */
  UINT* bw
/* 書き込まれたバイト数へのポインタ */
);
 
 
FRESULT f_close (
/*=== 開いているファイル オブジェクトを閉じます ===*/
  FIL* fp
/* 閉じるファイルオブジェクトへのポインタ */
);
 


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


4Kモニターは快適 PICでSDカードを使う