PICマイコン Feed

2019年5月 6日 (月)

PIC24FJ64GA004 フラッシュメモリーへの書き込み(EEPROM代用)

<カテゴリー:PICマイコン

16bitのPICマイコンの中で、24FシリーズにはEEPROMを個別に持っているものと、プログラムを格納するフラッシュROMエリアにデータも書きこんで、これを読み出す事により、EEPROMを代用できるものとに分かれます。 今回、PIC24FJ64GA004 において、EEPROM機能を必要としましたので、そのソフトをXC16のプログラムで紹介します。

Microchipやインターネットに情報公開している大先輩方による解説は沢山あるのですが、あまり考えずにコピペして使えるプログラム例がありませんでしたので、コピペだけで、済まそうという方に参考になればと思い公開します。

条件: フラッシュメモリーのアドレス0x9600から600バイトをEEPROM代用に宣言し、その中で64ワード分を読み書きできるようにします。 もし、64ワード以上必要な場合、ご自分で検討して下さい。

このデータメモリーは起動時にフラッシュROMエリアのデータを必要分のみ読み取り、プログラム実行中に変更されるあるいは変更されないデータいずれも、全てまた同じアドレスに書きこむことを基本動作としています。 例では lastmemory[] という変数の中にメモリー必要なデータが保持されるようにしています。 また、書き込み動作は結構時間がかかりますので、64ワード全てが必要でない場合、必要なワードのみを書き込み、影響を最小限にしています。 例では0から6までの引数(7種類)のデータだけを読み書きし、時間短縮を行っています。

コピペする範囲を青色、各自でアレンジする必要あるところを緑で示します。

最初にインクルードファイルです。

#include <libpic30.h>

次にグローバル変数を定義します。

section(".Data_Memory")の記述は、MPLAB Xにてコンパイルした時、メモリーマップが表示されるようにしたもので、リストの中に.Data_memory という情報を見つける事ができます。

//////////////グローバル変数として以下定義

unsigned int lastmemory[64];//EEPROM

const __attribute__((section(".Data_Memory"), space (prog), address (0x9600) )) unsigned int _flash_datas[96*8];

以下、読み書きENDまでが読み込み、書き込み関数です。 ここは何も考えずにコピペすればOKです。

/////////////////////////////////////////////フラッシュメモリー読み書き
void Flash_Read(unsigned char LN) {
 unsigned int i=0;

    unsigned int page = __builtin_tblpage(&_flash_datas);
    unsigned int offset = __builtin_tbloffset(&_flash_datas);
      // フラッシュメモリー読み込み
    TBLPAG = page;
    for (i=0; i<=LN; i++) {
        lastmemory[i] = __builtin_tblrdl(offset + i*2);
    }
}

void Flash_Write(unsigned char LN) {
    unsigned int i=0;
    unsigned int page = __builtin_tblpage(&_flash_datas);
    unsigned int offset = __builtin_tbloffset(&_flash_datas);

    
    // ページ消去
    TBLPAG = page;
    __builtin_tblwtl(offset, 0x0000); // 
    NVMCON = 0x4042;
    asm volatile ("disi #5");
    __builtin_write_NVM();          //erase 8line = 64*8
    while(NVMCONbits.WR);
 
    // ラストメモリー書き込み
    NVMCON = 0x4003;
    TBLPAG = page;
    for (i=0; i<=LN; i++) {
        __builtin_tblwtl(offset + i*2, lastmemory[i]);  // *2 偶数
        __builtin_tblwth(offset + i*2, 0xFF);
   
    asm volatile ("disi #5");
    __builtin_write_NVM();
    while(NVMCONbits.WR);
    }
}
/////////////////////////////////////////////フラッシュメモリー読み書きEND

以下、読み出したデータ lastmemory[] の中を、プログラムで使用している変数に分解します。 フラッシュメモリーはワード単位で読み出されますので、32bitのデータや8bitのデータはそれなりに加工が必要になります。 この例では、lastmemory[0],[1] は合成して32bitのデータに変換しています。 また、例えcharの変数でも16bit全体を使い余計な処理は省いています。

void readlastmemory(){
 unsigned long int bf;
 Flash_Read(6);//引数6は最後の[6]を指定する事
    bf = lastmemory[1];
 bf = bf << 16;
 BASEFREQ = lastmemory[0] | bf;
 V_level = lastmemory[2];
 MODE = lastmemory[3];
 IWB = lastmemory[4];
 RIT = lastmemory[5];
 Ritfreq = lastmemory[6];
}

以下は、プログラムで使用中の変数を lastmemory[] に格納した上フラッシュROMへ書きこみます。

void writelastmemory() {
 lastmemory[0] = BASEFREQ & 0x0000FFFF;//BASEFREQは32bitデータなので、[0],[1]に分割する。
 lastmemory[1] = BASEFREQ >> 16;
 lastmemory[2] = V_level;
 lastmemory[3] = MODE;
 lastmemory[4] = IWB;
 lastmemory[5] = RIT;
 lastmemory[6] = Ritfreq;
 Flash_Write(6);//引数6は最後の[6]を指定する事

}

MPLAB XにてコンパイルするときMPLAB Xの設定を少し変更が必要です。

Mplabx190506

Project Propertiesの中のXC16_gccを選び、上のoption categories の中のMemory Modelを開き、添付のようにチェックマークを入れます。(通常はマークなし) ただし、この状態は私の環境によるもので、使用状態では異なる可能性があります。 エラーが出る場合、この辺のチェックを付けたり外したりしてみて下さい。

このプログラムの実施例はこちらに有ります。

PIC24FV32KAシリーズのEEPROMアクセスコード例はこちらにあります。

INDEXに戻る

2018年8月13日 (月)

PICkit3 の修理

<カテゴリー:PICマイコン

DDS VFOの検討中に5Vの三端子レギュレーターが壊れてしまい、+5Vラインに+12Vが現れ、接続してあったPICkit3が煙を出して壊れてしまいました。

壊れたのは、バストランシーバーと呼ばれるPICkit3と外部回路のインターフェースに使われるICでした。

これを修理すべく、まずPICkit3の回路図を探すと、結構多くの情報がありました。 インターネットで調べていくと、MicrochipはPICkit3のクローンを容認しているというか、推奨しているようで、Microchip自身が回路図を公開していました。

pickit3sch.pdfをダウンロード  

この配線図そのものはMicrochip 製なのかクローンを作った会社のものか判りませんが、現物照合すると抵抗値が一部異なる所はありますが、IC名や結線は合っていました。

壊れたICはSN74LVC1T45DBVRという品番のバストランシーバーである事が判りました。 このバストランシーバーのパッケージは何種類もありますが、PICkit3に使われているのは、最後の文字がDBVRという一番大きいサイズのものです。

東京出張の帰りに、このICを秋葉原で探しましたが、結局見つからず。 帰ってからRSで見つけましたので注文し、現物も入手していましたが、その間にクローンのPICkit3を入手していましたので、修理は手づかずの状態でした。

最近、このバストランシーバーを実験する機会があり、PICkit3の修理の事を思い出しましたので、修理にトライする事にしました。

壊れたICは完全に黒焦げで、下の基板も炭化し、一部銅箔も無くなっていました。 本来6個の半田ランドが必要なICですが、6番ピンのランドとストリップラインは消失し、4番ピンに接続するストリップラインも消失していました。 拡大鏡を駆使してなんとかハンダ付けし、出来上がった基板は以下です。

Picki3up

Pickitopen

左上が黒焦げの基板上に新しいICをマウントし、消失したストリップラインの代わりに0.18mmの銅線で配線した状態です。 この作業の後、テスターを使い導通テストを繰り返し、接続漏れや逆に端子間ショートが無い事を確認した後、通電し、PICのターゲットを接続すると、ターゲットのIDが返ってきて、プログラムも無事書き込む事が出来ました。

これから、電源電圧には最新の注意を払う事にします。

INDEXに戻る

2016年1月 1日 (金)

LCD-TS174をPICによりドライブ

<カテゴリー:PICマイコン

「aitendo」という通販ショップで99円のLCDが売られていました。 その他の部品を含めてこのLCDを2個購入したのですが、仕様書はなし、有るのは、使用されているICの品名と、ATMELのチップ用デモソフトのみという物でした。 

今、PICマイコンで正弦波発生器を作っていますが、この周波数表示にちょうど良さそうですので、このデモソフトをPIC用に書き換え、WEB上からダウンロードしたICの仕様書を基に周波数を表示させてみる事にしました。

使用するマイコンはPIC16F1827という8bitのマイコンです。 周波数表示ですので、マイコンのクロックは7.2MHzの水晶発振で、これをPLLで4倍とした28.8MHzのメインクロックとしてあります。

回路図 LCD_demo_schema.pdfをダウンロード

オリジナルのデモソフトをこの配線図に合わせてi/o変更をした上で、XC8でコンパイルできるように書き換えました。 オリジナルの仕様では、一旦LCD全画面をクリアーした後、左側から順番に各セグメントが点灯していきます。 これをヒントに7セグの数値を表示させるコードを調査し、下記のように解析しました。

Ts174_segmap

このコード表をベースに7ケタの整数を表示するプログラムを作りました。数値以外に文字やドットがありますが、今回は使っていません。

Lcd1250disp

このLCD用のICのクロックは3.3uS以上を要求していますので、余裕を見て約6uSくらいのクロックになるようディレーを入れてあります。 また、メイン関数の170行目にwhileで無限ループを作り、以下のプログラムは実行されないようにしてあります。 この170行目のwhile文をコメントアウトすると、オリジナルデモソフトが動作します。  

また、プログラム上にはLEDが出てきますが、デバッグ用です。 さらに、RB0からの外部割込みの記述もありますが、このLCD表示については不要です。

PICkit3からHEXファイルを書き込もうとするとき、このICもVDDを5Vを指定するとエラーになります。4.875Vに設定すると問題無しです。

99円のLCDでも十分実用になります。 周波数のLCD表示が可能になりましたので、正弦波発生器のコントローラーを作る事にします。

ソースコード LCD_TS174BNLdemo.cをダウンロード

このオリジナルソースをベースにXC16でコンパイルしたところ、LCDのデータラインに信号が出ません。 色々調べた結果、下のLCD_Wr_Data()の関数の中で、

 B=B>>7; の処理を追加しないと、現状のままでは、データをi/oポートへ送る事が出来ない事が判りました。 判ってしまえば当たり前の事で、いままで動いていたのが不思議なくらいです。

void LCD_Wr_Data(unsigned char Data,unsigned char cnt) {
   unsigned char i,d,B;
    d = Data;             //Dataを一度ローカル変数に置き換える
    for (i=0;i<cnt;i++) { 
         LCD_WR=0;
         delayNop();
         B=d & 0x80;         //Dataと0x80とアンドを取った値を一度ローカル変数に置く
        B=B>>7;
         LCD_DA =B;          //LCD_DA=Data & 0x80 ではうまくいかない
         delayNop();

         LCD_WR=1;
         delayNop();
         d = d<<1;
       }
  }

INDEXに戻る

2015年12月 9日 (水)

正弦波発生器(PIC18F14K50)

<カテゴリー:PICマイコン

CQ誌のPWM変調AM送信機の記事に魅せられて、微力ながら、このアナログの塊のオールソリッドステートの送信機を作りたくなりました。  WEB上の情報から、この送信機の構成は理解できましたので、部品集めを進める傍らで、AM変調用の低周波発振器の必要性を認識しました。 実は、45年前に購入した20Hzから200KHzまでカバーするKENWOOD製の低周波発振器を6年前に完動品のまま粗大ごみに出してしまった事を悔やんでいます。 

CWのサイドトーン用にウィーンブリッジ式の正弦波発振器の製作例はこのブログでも紹介していますが、せっかくPICマイコンを曲がりなりにもいじれるようになりましたので、マイコンからDA変換を利用した正弦波発生器ができないか検討する事にしました。 WEBで検索すると、PICマイコンで正弦波を発生させる方法が沢山見つかりました。 その中で、マイコンのシステムクロックをフリーランの外部クロックで駆動し、任意の低周波周波数を得る方法と、固定クロックでADの出力周期を変えながら複数のスポット周波数として発生させるアイデアがあるようですが、その中で、比較的ひずみ率が良好で、簡単なCRフィルターで構成出来る8bitのラダー抵抗式DAコンバーターが良さそうです。

AM送信機で必要な周波数は1KHz、及び300Hzから3KHzの変調周波数特性と、これより広い範囲でどれだけ減衰しているかをチェックできる周波数帯となる100Hzから6KHzくらいをスポットでカバーできる周波数があれば良く、周波数も大体でOKですが、ひずみ率は1%以下とし、全周波数帯域に渡り出力レベルは+/-0.5dBくらいに抑えたいという条件があります。

マイコンは、使い道が無く、ジャンク箱に転がっていたPIC18F14K50というチップを拾い上げ、これにアセンブラでソフトを仕込む事にしました。 アセンブラによるソフトの開発は30年以上前にMC68000で少しかじっただけでしたが、データシートやWEBでの情報を頼りに再挑戦する事にしました。

まずは、ちゃんと正弦波が発生できるかどうかですが、約1週間かかり、なんとかそれらしき信号が得られました。 

40hz_nolpf_2

9khz_nolpf_3

左は最低周波数、1サイクルを256分割した40Hzの波形。右は最高周波数、1サイクルを64分割した12.5KHzの波形です。いずれもまだLPFは入っていないDAC出力直後の波形です。

波形の様子から、簡単なCRによるLPFでクロックによる高調波は取り除く事ができそうです。OP-AMPによりカットオフ周波数約30KHzのLPFを作り、DACとこのLPFが持っている周波数特性をもう1段のOP-AMPで補正し、40Hzから12.5KHzまでほぼフラットな正弦波発生器ができました。

40hz_lpf

1khz_lpf

9khz_lpf

左から40Hz,1KHz,12.5KHzのLPF後の波形で、周波数特性の補正を行い、振幅を一定にしたものです。ひずみ率計がありませんので、はっきりした数値は判りませんが、経験的にいずれもひずみ率は1%以下になっているようです。

配線図をダウンロード

A_osc2

A_osc1_2

上がPICによるDAコンバーターとLPFのOP-AMPを実装した基板です。 基板裏側の左側の空き地は後日、この正弦波発生器をコントロールするマイコンを実装するスペースです。

PICのプログラムは周波数を初期設定した後、無限ループに入って、正弦波を出力し続けますので、周波数を変更したい場合、周波数設定用のSW1からSW5をセットした後、RESETスイッチSW9を押すことで実現します。 これをロータリーSWかロータリーエンコーダーの操作のみで実現する為に、周波数表示が可能な簡単なマイコンを実装する予定にしていますが、今回の目的が、AM送信機を作る事なので、コントロールマイコンやケース入れは後回しにします。

 ソースコード sin_wave_osc.ASMをダウンロード

SW1-SW4に対応した周期カウント値は適当な値ですので、周波数カウンターを使い、トリミング必要です。

INDEXに戻る

2015年10月18日 (日)

PICマイコンでSDカードのファイルを読み込む

<カテゴリー:PICマイコン

マイクロチップのMLAの中にあるデモソフトは簡易データロガーともいえるもので、何らかの手段で定期的に入手したデータをデモファイルにAPPENDしながら書き込んでいくものです。 従い、MS-DOSのDIRコマンドに相当したファイル検索や、特定のファイル名をオープンして、中身を読みだすという動作は行いません。 ただし、これらの機能の、コマンドの使い方は例で示してあります。 

今回、SDカードにセーブしたCSVファイルを検索して、LCD上にファイル名を表示させる機能、及び、表示したファイル名を指定して、そのCSVファイルを読み込み、LCD上にSWRカーブを再表示させる事にトライしました。 FILEIOのHELPドキュメントを読んだだけでは理解できず、構造体の勉強を3週間くらいやって、やっと、思ったようにソフトが動くようになりました。

Aa50_find

Aa_50_40m

ソースコードを下記しますが、そのままコピペしても動作しません。 これをデモ用として提供されているソースコードの中に埋め込んでやると期待したような動作が得られます。

MS-DOSのDIRに相当する関数は「FILEIO_Find」という関数を使います。

searchnameは16bitの文字で "*.CSV" と初期設定し、FILEIO_Findの関数を実行させるとsearchRecordの中にファイル名がひとつだけストアされます。 これをset_dir_fname()の関数に送り、そこで2次元の文字列にストアします。この動作を20回繰り返します。 ファイルの数が20以下の場合、i=20で強制的にループを抜けます。

unsigned int  find_SD_card(void) {

     DEMO_STATE demoState = DEMO_STATE_NO_MEDIA;

   FILEIO_OBJECT file;

    FILEIO_SEARCH_RECORD searchRecord;

    init_SDcard();

    unsigned char i;

   uint16_t SD_ER = 0;

      while(SD_ER == 0) {

        switch (demoState) {

            case DEMO_STATE_NO_MEDIA:

                 if (FILEIO_MediaDetect(&gSdDrive, &sdCardMediaParameters) == true) {

                    demoState = DEMO_STATE_MEDIA_DETECTED;  

                    }

                 break;

            case DEMO_STATE_MEDIA_DETECTED:

                  SD_ER=(FILEIO_DriveMount(drive_A, &gSdDrive, &sdCardMediaParameters));

                if (SD_ER ==0){

                    demoState = DEMO_STATE_DRIVE_MOUNTED;

                     } else {

                    demoState = DEMO_STATE_NO_MEDIA;

                    }

                     break;

            case DEMO_STATE_DRIVE_MOUNTED:

                if (FILEIO_Find (searchname, FILEIO_ATTRIBUTE_MASK, &searchRecord, true) == FILEIO_RESULT_SUCCESS) {

                    i=0;

                    set_dir_fname(&searchRecord,i);

                    i++;

                    } //サーチの最初はこのようにtrueを指定して検索

                    while (i < 20) {

                        if (FILEIO_Find (searchname, FILEIO_ATTRIBUTE_MASK, &searchRecord, false) == FILEIO_RESULT_SUCCESS) {

                           set_dir_fname(&searchRecord,i);

                            i++;

                            } else {i=20;} //whileループから抜ける為

                        }  //2回目以降はfalseを指定して検索

・・・・・・

・・・・・・

このfind_SD_cardの関数は、ファイル名を検索して最大で20個表示したら一旦ドライブをアンマウントさせます。

.

.

ファイルの読み出しは「FILEIO_GetChar」という関数を使います。

void get_SDdata(unsigned int *sptr) { //テキストデータを1行(LFまで)読み込む
     uint8_t C=0;
     uint8_t i=0;
     while (C != 0x0A) {
        C=FILEIO_GetChar(sptr);
        if (C == 0x1A) {break;} //EOFでもループを抜ける
        SWR_SDdata[i]=C;
        i++;

     if (i>40) {break;} //1行の文字数が40を超えたら抜ける
        }
     SWR_SDdata[i-2]=0;
  }

セーブされたテキストデータは必ず「CR+LF」で1行完了としていますので、上の関数で、CR+LFが削除された文字列として、SWR_SDdata[]の中にストアされます。

正規のSWRカーブファイル以外の場合、暴走しないように、EOFを見つけたり、1行の文字数が40を超えたら、ループから抜けます。 

.

以下はASCIIからUTF-16への変換関数です。

void Uint8toUint16(uint8_t *fname8) { //ASCIIをUTF-16に変換します。
        unsigned char i ;
        for (i=0;i<13;i++) {
            fname16[i]=fname8[i];
        }
    }   

以下が特定の16bitファイル名「fname16[]」をオープンして読みだす処理になります。

unsigned int  open_SD_card(unsigned char *fptr) {
   DEMO_STATE demoState = DEMO_STATE_NO_MEDIA;
   FILEIO_OBJECT file;
   unsigned char i;
    uint16_t SD_ER = 0;
    Uint8toUint16(fptr);

・・・・・

・・・・・

 if (FILEIO_Open (&file, (uint16_t *)fname16, FILEIO_OPEN_READ) == FILEIO_RESULT_FAILURE) {
 
                    demoState = DEMO_STATE_FAILED;
 
                    SD_ER=2;
                    break;
                    }
                    SD_ER=50;
 
        get_SDdata(&file);
        set_FREQ_data(&SWR_SDdata,1);

読み込みは全部で225行に渡りくりかえされますが、それが終わるとファイルクローズします。 

 if (FILEIO_Close (&file) != FILEIO_RESULT_SUCCESS) { //ファイルクローズ                     demoState = DEMO_STATE_FAILED;

                  SD_ER=3;

                    return SD_ER;

                  }          

クローズが失敗したらメインルーチン側で強制的にドライブアンマウントを実行させます。

クローズが成功してもドライブをアンマウントします。

FILEIO_DriveUnmount ('A'); //ドライブアンマウント

SD_ER=20;

return SD_ER;

・・・・・・・

・・・・・・・

ファイルを削除する時は以下のコマンドとなります。

 if (FILEIO_Remove ((uint16_t *)fname16) != FILEIO_RESULT_SUCCESS) {
                        SD_ER=10;
                        }
                    break;

エディター上ではTABを使い、行の整列がきれいに出来ているのですが、このブログに貼り付けるとメチャクチャになって、大変読みにくくなってしまいました。

このデモプログラムのなかでは、かなり詳しいエラーメッセージが定義され、それが番号で返されますが、そのままでは、かえって混乱しますので、新たにSD_ERという変数で、勝手にエラー番号を定義し、ループからの抜けや、メインルーチン側でのエラー処理に使っています。

出来てしまえば、簡単な記述で完成するのですが、ここまでやるのに優に1か月かかりました。

実際にアンテナアナライザーに組み込んだ状態はここで紹介しています。

INDEXに戻る

2015年9月17日 (木)

PICマイコンからSDカードへのファイル書き込み

<カテゴリー:PICマイコン

LCD表示のアンテナアナライザーの自作の中で、周波数対SWRのグラフを描かせるところまで成功しました。 そこで、このグラフをPCに取り込めないか、試行錯誤しておりました。 そして、やっと、PICマイコンでSDカードにファイルを書き込む事が出来るようになりました。 まだ、数行のテキストデータしかないファイルを書き込んだだけで、グラフデータは未完成ですが、ここまで、出来ると、後は時間の問題となります。

今回は、PICマイコンからFAT32のファイルシステムでフォーマットされたSDカードにテキストファイルを書き込む方法を紹介します。

ハードの構成です。 アンテナアナライザーのハードに秋月で売っているSDカードソケットを接続した、単純な回路となっております。

Pic_sd_schema

 検討するソフトもこのSDカードの部分のみで、LCD表示は実装していません。

秋月から「SDカードスロットDIP化モジュール」という名前のソケットを買ってきて、これを配線図のごとく、マイコンの空きピンに接続します。PIC24FJ128GB106はi/o設定が自由にできますので、このような場合、非常に便利です。

Sd_card0そして、左の画像のごとく実装しました。

この状態でSDカードをドライブするソフトはMicrochipが無償で提供しているfileioというアプリケーションを使います。

このアプリの説明を読んでいると、私のようにC言語のポインターもまともに扱えない者でもなんとかPCで読めるファイルを書き込めるかも知れないと思うようになりました。

しかし、これが間違いの始まりで、検討を開始してからすでに1か月。 やっとのことで、FAT32のファイルシステム上に自作のファイルを書き込む事に成功しました。

Pic_fat32file0 上はエクスプロラーでSDカード内のファイルを表示させたものです。

Sample long file name.txtはデモプログラムが見本として作成したファイルです。

SWR12345.txtは私が作ったファイルです。 いずれも2行、20文字くらいのファイルですが、ファイルの中身は、これから好きに変更できます。

ここまで出来るまでの工程を以下説明します。

MicrochipのサイトからMLAと言われるアプリケーションファイルをダウンロードし、デフォルトの設定のままインストールします。 私がインストールしたファイル名は以下の名前でした。

mla_v2015_08_10_windows_installer.exe

デフォルトでインストールした後、MPLAB Xから以下のプロジェクトを探し

C:\microchip\mla\v2015_08_10\apps\fileio\sd_card_demo_lfn\firmware\MPLABX

fileio_sd_card_demo_lfn を読み込むと、同名のプロジェクトがオープンします。

このプロジェクトができましたら、マイコンの品種設定とi/oの設定を書き換える事により簡単にデモプログラムが動作します。・・・・とはなりませんでした。

Mplabx_sd

上のダイアログはMPLABXにてプロジュクトをオープンした時の画面ですが、上の方にICの品種を指定するランがありますので、実際に使用しているICファミリーを選択します。 

私の場合、実際に使用しているICはPIC24FJ128GB106ですので、ファミリー名はpic24fj256gb110となります。 使用可能なICのファミリー名が左側の「exp16」フォルダーの下に表示されていますので、確認できます。ここにリストされた以外のICで、このデモソフトが動作するかは不明です。

リンクされたファイルには同じ名前で中身の違うものがいくつかあります。main.c やsystem.c が該当しますので、他のホルダーでプロジェクトを構築する場合は、一度デモプロジェクトをオープンし、そのとき表示されるファイルをコピーして他のホルダー移すことで間違いを防ぐ事ができます。 事実、最初、リンクを頼りにファイルをコピーしてきて、独自のホルダーに集めてbuildをかけたところ、エラー続出で困り果てた事がありました。 この為、main.c とsystem.c はそれぞれ、SD_main.c とSD_system.c いう名前にし、のちのち間違わないようにした上で、独自のフォルダーへ移動させ、オリジナルのファイルは元の場所にそのまま残しました。 

まず、lfn(ロングファイル名)を選んだのに、リンクされたヘッダーファイルはlfnなしの普通のfileio.h。 これをハンドでfileio_lfn.hに入れ換えました。 ソースファイルもlfnではなかったような記憶ですが確かでありません。もし、違ってましたらソースファイルもfileio_lfn.c に入れ換えて下さい。

また、system.c の中の一部を以下のように書き換えました。

#pragma config FNOSC = FRCPLL//OSCを32MHzのCR発振に変更

#pragma config FWDTEN=OFF

ただし、このままでは16MHzにしかなりませんでしたので、main()の中で、以下を

追加し32MHzにしました。

OSCCON = 0b0001000110100001; //Fosc FRCPLL 32MHz
 CLKDIV = 0x0000;

また、青色の設定は後日、追加したものです。 このPICマイコンはデフォルトでウォッチドッグタイマーがONになっており、約2分20秒でリセットがかかる原因になっていました。 これが時々暴走する原因と解るまで3週間くらいかかりました。

また、i/oの設定も変更しました。

void USER_SdSpiConfigurePins_1 (void) {     //Initialize the SPI    

RPINR20bits.SDI1R = 25;    //修正

RPOR10bits.RP20R = 7;    //修正

RPOR11bits.RP22R = 8;    //修正

    //enable a pull-up for the card detect, just in case the SD-Card isn't attached    

//  then lets have a pull-up to make sure we don't think it is there.    

//CNPU5bits.CN68PUE = 1;//プルアップはハードで行っていますので、この行は不要です。   

// Deassert the chip select pin    

LATDbits.LATD2 = 1;    //CS端子1に設定

// Configure CS pin as an output    

TRISDbits.TRISD2 = 0;    //CS端子出力に設定

// Configure CD pin as an input    

TRISDbits.TRISD1 = 1;    //CD端子入力に設定

// Configure WP pin as an input   

// TRISDbits.TRISD1 = 1; //この行はコメントアウト

}

・・・・・

・・・・

inline void USER_SdSpiSetCs_1(uint8_t a) {

    LATDbits.LATD2 = a;   //CS端子修正

}

inline bool USER_SdSpiGetCd_1(void) {

    return (!PORTDbits.RD1) ? true : false;//CD端子修正

}

inline bool USER_SdSpiGetWp_1(void) {

    //return (PORTFbits.RF1) ? true : false;//コメントアウトして0を返す

    return 0;

}

ここまで修正してBuildをかけてエラーが出なかったら、成功です。

しかし、PCでFAT32にフォーマットしたSDカードを用意し、マイコンにプログラムを書き込んでもファイルは出来ません。

今度はmain.c の定義の部分を変更します。

typedef enum
{
    DEMO_STATE_MEDIA_DETECTED = 0,
    DEMO_STATE_NO_MEDIA,
    DEMO_STATE_DRIVE_MOUNTED,
    DEMO_STATE_DONE,
    DEMO_STATE_FAILED
} DEMO_STATE;

DEMO_STATE_NO_MEDIA=0という記述が最初の行にありますので、これを上記のごとく2行目に移し、"=0"の文字を削除します。 DEMO_STATE_MEDIA_DETECTEDを一番上にして、"=0"を追記しておきます。これは、Maicrochipのデモ機はCDが0の時ノーメディアなのに対して、秋月のソケットはCDが1のときノーメディアになっている為です。

以上の手直しでデモ用のファイルがSDカード内に出来るようになりました。

次に自作のファイル名でファイル作成にトライです。 ところが、出来たファイル名は文字化けして読めない上、ファイルの中身も空です。 ファイル名は「SWR00001.csv」で始まる連番とする予定ですので、この数値の部分はunsigned int で1から始まる整数です。これをファイルに書き込めるようにASCII変換してファイル名としたのですが、うまく行きません。

色々調べて、判った事は、FAT32のファイル名はASCIIコードではないということでした。ファイル名はutf-16という16bitの文字でエンコードされていました。 XC16の中にあるストリング系の関数は使えませんので、自分でASCII to utf-16の変換ルーチンを作る必要がありました。 

幸い、ASCIIコードの文字だけに限れば、8bitのASCIIコードの上部に0x00のコードを加えて、16bitにするだけなので、変換ルーチンは私でも作れましたが、日本語のファイル名は使えません。

このようにして、「SWR12345」のようなファイル名を付けたテキストファイルを作る事が出来るようになりました。このファイル名の数字の部分を連番のファイル名にし、拡張子をcsvにするとOKとなります。

SDカードは、128Mと8Gの物をテストしましたが、いずれもFAT32でフォーマットしてあれば問題なく使う事ができました。 exFATでフォーマットしたSDカードの場合、エラーがでます。

この小さなデモファイルを作る為に必要なROM容量は約44.9Kバイトです。これから実験しようと考えているなら、ROM容量64Kでは心細く、最低でも128K品が必要でしょう。

ところで、出来たファイルにちゃんとタイムスタンプが付いています。どうやって時間を計っているのでしょうかね。マイコンボードは使わないとき電源OFFなのですが。

このSDカードドライブ機能をアンテナアナライザーに実装する事にします。

SWRグラフをSDカードへセーブ へ続く。

INDEXに戻る

2015年8月14日 (金)

PIC24FJ128GB106 データメモリー不足

<カテゴリー:PICマイコン

TFT LCDにグラフィックや文字を表示させていますが、メモリー容量を64Kから128Kに替えた為、新たにフォントを追加する事にしました。 フォント作成アプリで大文字、小文字、数字、記号などを作り終え、これをincludeファイルにして、コンパイルすると、エラーになります。  出てくるコメントはリンカーエラーとの事で、メモリーが不足しているような内容です。

これらのエラーコメントを頼りにインターネット内で検索すると、Microchip(USA)のFAQページにメモリーを拡張しなければデータサイズは32Kまでと言う説明が見つかりました。 ただし、どうすれば、32K以上のデータメモリーを使えるのかは、やりとりが英文である事もあって、良くわかりません。

そこで、日本語の情報を探すと、データメモリーが32Kまでで制限されている事。 これを32K以上に拡張する為には、レジスターの設定やアドレッシングなど、変更する必要は判りましたが、肝心なXC16による記述方法が良く判りません。

結局、インターネットから探しだした、以下の記述でコンパイラーがエラーを出さなくなり、ちゃんと文字の表示が可能になりました。

コンパイルエラーになった記述例

const unsigned char Font7_space[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };//ASCII 32
const unsigned char Font7_sharp[] = { 0xb, 0xa, 0xa, 0x3f, 0xa, 0x1a, 0x1a, 0x3f, 0x16, 0x16 };// ASCII 35

・・・・・・

・・・・・・

const unsigned char *Font7_table[] = {
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //ASCII 0-15

・・・・・

・・・・・

コンパイルエラーが無くなった記述例

__eds__ unsigned char Font7_space[] __attribute__((eds)) = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };//ASCII 32
__eds__ unsigned char Font7_sharp[] __attribute__((eds)) = { 0xb, 0xa, 0xa, 0x3f, 0xa, 0x1a, 0x1a, 0x3f, 0x16, 0x16 };// ASCII 35

・・・・・・

・・・・・・

__eds__ unsigned char *Font7_table[] __attribute__((eds)) = {
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //ASCII 0-15

・・・・・

・・・・・

Aafont7

左の[SWR ANALYZER]の文字が今回作成した10x6のフォントです。

文字を書き込むとき、フォントアドレスをポインターで指定しますが、このポインターの型宣言も下記のようにする必要がありました。

__eds__ unsigned char *fontptr;

INDEXに戻る

2015年8月 3日 (月)

PIC24FJシリーズ SPI 誤動作

<カテゴリー:PICマイコン

アンテナアナライザーのLCDドライブ用に使用していたPIC24FJ64GA004のROMエリアがほぼフルになりましたので、128Kに換える事にしました。 選んだマイコンは、将来USB機能やSDカードを組み込むかも知れないとの考えから、PIC24FJ128GB106という品番のICにしました。 

Aa59pic24fj128gb106

左の画像が、128Kの64pin TQPF品に入れ替えた実装基板です。 変換基板の大きさが、44pinのときより小さくなっている関係で、以外とすっきり配線できました。

回路図的には、44pinの時と同じ構成で、一部i/oの割り当てを変更しただけで、さっそく動作確認です。 ところが、LCDの表示は問題なく表示されますが、コントロールマイコンとの通信がうまくいきません。 周波数表示はでたらめで時々暴走します。 UART通信のプログラムが異常なのかと、色々試しましたがうまくいきません。 じたばたしている内に、通信もうまくいかないのに、さらに、26バイトの伝送に15m秒くらいかかっている事が判り、LCDの表示速度も遅くなっている事に気付きました。 ボーレート38.4Kでは不足みたいです。 56K以上にアップする案もありましたが、 キー入力をADに変更して、ラッチアップの対策もできましたので、残りのUP,DOWNのキーもADに変更する事によりi/oポートが2本余ります。 この際、通信方式もi/o 1本のUARTからi/o 3本のSPIへ変更する事にしました。

しかし、これが、またまた、訳の判らない誤動作に悩まされる事になってしまいました。

時々、伝送に成功しますが、一度リセットをかけると、伝送データがでたらめになります。 約2週間悩んだ末、判った結論は、またまた、伝送路のリンギングによるマイコンのラッチアップでした。 ただし、ラッチアップの影響が小さい為、時々まともに動作するのは、プログラムの性ではないかと、ああでもない、こうでもないとやっていたのがいけなかったようです。 ふと、ハードが原因ではないかと、SPIのクロックやデータの波形をチェックしてみました。

Aa59spi0

Aa59spi1

上の画像は左が対策前の、クロック(下)とデータ(上)です。 右の画像は対策後の波形です。 対策前は、クロックにも、データにもリンギングのオーバーシュートやアンダーシュートが発生し、いずれも時々0.5Vを超えています。 これが伝送データがでたらめになる原因でした。 対策内容は、各ラインに1KΩの直列抵抗を挿入し、リンギングの発生をおさえますが、抵抗だけでは不十分でしたので、GNDとの間に68Pのコンデンサも追加しました。 波形がきれいになって暴走の確率はかなり減少しました。 

しかし、時々、電源ON直後に暴走します。 ただ、基板のGNDラインを指でつかむとか、オシロのGND端子へ接続すると完璧に直ります。 このような症状の原因はノイズです。 ふたつのマイコンのうち、どちらで暴走しているか確認したところ、コントロール側の24FV32KA302が暴走しています。 さらに、このマイコンの入力関係をひとつづつ殺して確かめても暴走するときは暴走します。 最後にたどりついたところはMCLR端子でした。 この部分についてデータシートを再確認したところ、推奨回路はMCLR端子にシリーズに100から470Ωを入れろと書かれていますが、8bit時の延長で抵抗は入れてありませんでした。 そこで、470Ωを追加し、10回くらいのPOWER ON/OFFでは暴走が起こらない事を確認できました。 しかし、頻度は少ないですが、たまに誤動作します。 このマイコンのデータシートには、さらに0.1μFでGNDへ落とせと書いてあります。  さっそく0.1μFのコンデンサを追加したところ暴走が起こらなくなりました。 しかし、PICKIT3の説明書では、MCLRラインにコンデンサを接続するなと書いてあります。 試にこのラインに0.1μFを接続したままで、フラッシュメモリーの書き換えを行ってみましたが、問題なく書き換えが出来ました。 もし、書き換えがうまくいかない時は、コンデンサを外し、アナライザーが完成したら、コンデンサを追加する事にして、コンデンサは追加したままにしています。

LCDドライブ用の24FJ128GB106のMCLRラインにはまだシリーズ抵抗は入っていませんので、抵抗だけは追加する事にしました。

対策済回路図をダウンロード

Aa59_spi2

このSPI通信は、PIC24FV32KA302をマスターとして、PIC24FJ128GB106をスレーブとした一方通行のシリアル通信です。 クロックは約156KHzとし、マスター側はワード(16bit)伝送で割込みなし、全17ワードを連続送信し、その間、CEとしてLの信号を送ります。 スレーブ側は、CE信号がLになったらこれを割込みで捉え、受信バッファのインデックスを0にした後、1ワード受信する度に割込みを発生させ、17ワードのデータをバッファにストアさせます。 CE信号を送ったり、CEを受けてインデックスを0にする動作以外、すべて、データシートにかかれた説明通りの設定です。 

上の画像は、下のパルスがSPIのクロック(SCK)で、上のパルスが受信割込みが発生したときのダミー信号です。 1ワード受信する度に割込みが発生し、先頭ワードのインデックスを0番として順次17ワードを受信バッファに格納していきます。

送信側のPIC24FV32KA302のmain内の初期設定と送信ファンクションは以下です。

main () {

・・・・・・・・・

SPI1CON1 = 0b0000011000111100;//マスターモード クロック1/64
SPI1CON2 = 0b0000000000000000;
SPI1STATbits.SPIROV = 0;
SPI1STATbits.SPIEN = 1;//SPI1有効化

・・・・・・・・・・・・・

送信処理

void sendDATA() {
    unsigned char i;
    SPIFlg = 0;//CE信号をL
     __delay_us(20);
    for (i=0;i <17;i++) {
        while(SPI1STATbits.SPITBF);
        SPI1BUF = TXData[i];
        }
     SPIFlg = 1;//CEをH
}

受信側PIC24FJ128GB106の初期設定と受信割込みルーチン

main() {

・・・・・・・・・・・・・・・

RPINR0bits.INT1R = 21;//INT1をRP21に割り当て(RG6)
 RPINR20bits.SCK1R = 26;//SCK1INをRP26に割り当て(RG7)
 RPINR20bits.SDI1R = 19;//SS1INをRP19に割り当て(RG8)
 SPI1BUF = 0x0;//SPIバッファークリアー
 IFS0bits.SPI1IF = 0;//SPI割込みフラグクリアー
 IEC0bits.SPI1IE = 1;//SPI割込み有効
 IPC2bits.SPI1IP = 3;//SPI割込み優先レベル3
 SPI1CON1 = 0b000011000000000;//SDO使用せず。スレーブモード
 SPI1CON2 = 0b000000000000000;//フレーム未使用
 SPI1STATbits.SISEL = 1;
 SPI1STATbits.SPIEN = 1;//SPI1有効化
 INTCON1 = 0b000000000000000;
 INTCON2 = 0b000000000000010;//INT1 ネガティブエッジ
 IFS1bits.INT1IF = 0;// INT1 割込みフラグクリアー
 IEC1bits.INT1IE =1;//INT1割込み許可
 IPC5bits.INT1IP = 3;//INT1割込み優先レベル3

 ・・・・・・・・・・・・・

CE割込み処理

void __attribute__((interrupt, no_auto_psv)) _INT1Interrupt(void) {
    IFS1bits.INT1IF = 0; //割り込みフラグ解除
    RXindex = 0;
}

SPI受信割込み処理

void __attribute__((interrupt, no_auto_psv)) _SPI1Interrupt(void) {
    unsigned int i;
 //    LED=1;
    IEC0bits.SPI1IE = 0;//受信割込み禁止
    IFS0bits.SPI1IF = 0; //受信割り込みフラグ解除
    i = SPI1BUF;
    RXdata[RXindex] = i;
    RXindex++;
    if (RXindex > 16) {
       RXreadyflag = 1;//全データ受信完了フラグ
       RXindex = 0;
       }
   IEC0bits.SPI1IE = 1;//受信割込み許可
//      LED=0;
}

INDEXに戻る

2015年6月25日 (木)

PIC24FV32KシリーズのEEPROM読み書き

<カテゴリー:PICマイコン

アンテナアナライザーのコントローラーとして、PIC24FV32KA302というマイコンを使っていますが、このマイコンに内臓されたEEPROMは、8bit系のマイコンとは異なり、プログラムメモリーのアドレス上に配置されています。 従い、EEPROMの書き込み読み出し方法は、従来の8bit系とは異なっています。

このEEPROMに書き込んだり、読み込む為の、サンプルプログラムはデータシートの中に出てくるのですが、イマイチ良く判りません。WEB上でサンプルを探しておりましたら、Microchipのホームページ内のFAQのところにひな形のプログラムがありました。 これをコピペしたら、エラーなくコンパイルされ、ちゃんと読み書きできました。

日本語ページでは、なかなか見つける事が出来ませんでしたので、以下そのソースを紹介します。

//データEEPROMへの読み書き

unsigned int eeRead(unsigned int address) {

  while(NVMCONbits.WR); // wait for any last write to complete

  TBLPAG = 0x7f; // eprom is a t 0x7ffe00

  return __builtin_tblrdl(0xFE00+address);

  }

 void eeWrite(unsigned int address, unsigned int data) {

   while(NVMCONbits.WR); // wait for last write to complete

   NVMCON = 0x4058; // Set up NVMCON to erase one word of data EEPROM

   TBLPAG = 0x7f; // eprom is a t 0x7ffe00

   __builtin_tblwtl(0xFE00+address, 0xffff);

   asm volatile ("disi #5");

    __builtin_write_NVM(); // Issue Unlock Sequence & Start Write Cycle

   while(NVMCONbits.WR); // wait for errase to complete

   NVMCON = 0x4004; // Set up NVMCON to write one word of data EEPROM

   __builtin_tblwtl(0xFE00+address, data); // Write EEPROM data to write latch

   asm volatile ("disi #5");

    __builtin_write_NVM();

   }

書き込みは下の1行です。

eeWrite(address,data);

addressがEEPROM内の相対アドレスで0から254までの偶数を指定します。

dataは書き込もうとするワードデータ(16bit)です。 書き込みは16bit単位で行われますので、8bit単位で行いたい時は、書き込む前に、ふたつの8bitデータを連結するか、空の8bit(例えば0x00)と書き込みたいデータを連結したワードデータを用意します。

読み出しは下の1行です。

DATA=eeRead(address);

DATAに16bitデータが格納されます。

PIC24FJ64GAシリーズのフラッシュメモリーに書きこむ例はこちらにあります。

INDEXに戻る

2015年5月30日 (土)

TFT LCDによるアナログメーター 3

<カテゴリー:PICマイコン

Aameter2_2

PC上で動作するコードジェネレーターのバグと、C言語のポインターの使い方でかなり苦労しましたが、左のような、アンテナアナライザーの表示画面ができました。 

なぜLCD上の疑似アナログメーターの表示にこだわるかと言えば、それは、マルチファンクション画面が得られるからです。 画面はこれで完成ではなく、アナログメーター部分を消して、周波数対SWRのグラフを描かせる事により、LCD表示のアナログメーターも生きてくる訳です。 しかし、ここまでの表示で、const用に使えるROMエリアを含めて85%くらい使っており、これ以上のグラフィックを仕込むとエラーになります。 SWRのグラフ表示は、実際にハードと結合した時の様子を見ながら考える事にします。

通常、プログラムの効率化の為、共通の関数を条件判断しながら、使い回ししますが、これをやると、条件判定の為、動作が少しだけ遅くなります。今回のプログラムでも、メーター指示や、数値の表示の中で、IF文が多くなると、目に見えてメーターの動きはおそくなりました。

対策としては、条件判定を必要最小限に抑える代わりに、関数をいくつも設けることにしました。ROMの容量アップになりますが、プログラム用の容量より、グラフィック用のROM容量がはるかに大きく、全体的にはあまり影響はありません。

残り15%のROM容量でどこまで出来るかは、これからの作業になりますが、ROM容量128Kバイトのマイコンは64pinのQFPですので、出来ることなら、この44pinの64Kに収めたいところです。 また、クロックも現在20MHzですが、これを32MHzまで上げる事にします。

このLCDの表示状態で、SWRやZ,R,Xをリアルタイムにデジタル表示すると、アナログメーターの指針の動作速度は、どんどん遅くなっていきますが、 その上で、周波数カウンターを動かすと、周波数カウンターの基本ゲート時間が10ミリ秒必要であり、メーターの指針の動きはもっと遅いものになりそうです。 改善策としては、周波数カウンターは、外付けPICマイコンで処理し、カウントした結果だけをもらうという案になりそうです。

また、RやXを表示させるためには、10000倍した整数計算では、その精度が不十分で、32bit浮動小数点による計算はマストですから、これもLCD表示マイコンから切り離した方がよさそうです。

これら、周波数カウンターやR、Xのベクトル計算も、LCD上でのグラフィック表示がなければ、8bitマイコンでも十分処理可能なものです。

これからハードの設計を始めますが、基本設計はほとんど出来ていますので、蛇の目基板を使い、いかにして手作りするかが、本当の課題です。 完成はいつの事やら。

アンテナアナライザーの製作(センサー回路) に続く。

2015年6月30日追記

ハードウエーアーが基板状態ですがほぼ完成し、LCDアナログメーターの改善を行う事が出来る時期になりました。 当初、メーターの振れ分解能は1度きざみでしたが、動きが粗く、とてもアナログメーターの動きをまねる事ができませんでしたので、LCDの1ピクセル単位の変化となる、0.25度きざみでドライブする事にしました。 しかし、0.25度きざみでそのまま駆動すると、ゼロから無限大までの移動時間は10秒を超えてしまいます。 動きはスムースですが、実用的では有りません。

Aa50meter3_2

そこで、目標の角度と、現在位置の差を計算し、T/Gに対して数度しか離れていない場合、0.25度きざみで送り、その倍の差が有る場合、0.5度きざみで送り、同様に差が倍になるごとに送る角度も2倍にし、最大で2度きざみで送るようにしました。 この細工により、T/G角度近くになると、指針の動きにブレーキがかかりますので、本物のメーターの動きに、より近くなりました。

結果は非常に良好で、7MHzのアンテナをつないで、実際にSWR最少周波数を探す操作をすると、かなりスムースに指針が追従し、なんなく共振点に周波数を合わせる事が出来るようになりました。 本物のアナログメーターには及びませんが、さほど違和感なしに操作できます。 これから完成度を上げていきますが、ROM容量が、目いっぱいの状態ですので、マイコンを変更するまでは、とりあえず、お預けとなりそうです。

左のLCD画像は最新の表示画像で、50Ωのダミー抵抗を装着した時の表示です。

アンテナアナライザーの製作(センサー回路) に続く。

INDEXに戻る

2015年5月12日 (火)

TFT LCDによるアナログメーター 2

<カテゴリー:PICマイコン

 8bitのPICマイコンでは容量不足で、まともにLCDの表示が出来なかった為、マイコンを16bitに替え、かつLCDも一回り大きな2.4インチサイズにして、実用サイズのLCDアナログメーターを実験中です。

16bitpic_pwb_4

16bitpic_lcd

マイコンはi/oに不足がありますが、とりあえず簡単に実験できそうな、PIC24FJ64GA004という16bit品と、前回と同じメーカーDisplaytechの、DT024CTFTという、320x240ピクセル2.4インチサイズで作ることにしました。 マイコンが16bit品になったので、コンパイラもXC16に変更必要です。そこで、開発環境も、MPLAB Xに変更する事にしました。 しかし、これが、くせもので、従来のやり方では、全く動きません。 すでに通り過ぎた方は、問題ないにしても、これから、XC16やMPLAB Xの環境でPIC24xxxの開発を始めようと思っている方に多少なりとも、役にたつならと、失敗と対応方法を紹介します。

まず、MPLAB Xですが、エジターの日本語が文字化けして読めません。 WEBで調べていくと、プロジェクトを作るときにEncodingの指定をやるのだそうですが、それを見落としてプロジェクトを作ってしまっているので、後から、Encodingを変更する方法を探す必要がありました。 

プロジェクトをオープンして、プロジェクト名の周りが青色になっている状態で、マウスを当て、右クリックすると、一番下にPropertiesがありますので、これをクリックします。出てきたダイアログの一番上にるGeneralの文字をクリックすると、中央下にEncodingの設定ランがあります。その中から、Shift_JISを選択すると、文字化けは直ります。

初期段階として、PICのソースファイルにConfig事項を書き並べて、チップの初期設定をおこないますが、HI-TECH CとXC8やXC16では全く書式が異なります。

HI-TECH Cによる16F1939のConfig記述例

 __CONFIG ( FOSC_INTOSC & WDTE_OFF & PWRTE_ON
 & MCLRE_OFF & CP_OFF & CPD_OFF & BOREN_OFF & CLKOUTEN_OFF & IESO_OFF
& FCMEN_OFF);
 __CONFIG ( WRT_OFF & VCAPEN_OFF & PLLEN_OFF & STVREN_OFF & BORV_LO
& LVP_OFF );

これに対して、XC16で24FJ64のconfig記述例

// コンフィギュレーション設定 Fosc=20MHz Xtal
#pragma config POSCMOD = HS, I2C1SEL = PRI, IOL1WAY = ON
#pragma config FCKSM = CSDCMD, FNOSC = PRI
#pragma config WUTSEL = LEG, IESO = OFF, WDTPS = PS1
#pragma config FWDTEN = OFF, ICS = PGx1, COE = OFF, BKBUG = OFF
#pragma config GWRP = OFF, GCP = OFF, JTAGEN = OFF

XC16をデフォルトでインストールすると、以下のホルダーの中に、各PICの品種ごとに、どのように設定するか説明があるのですが、書いてある単語が何を意味するのか判らず、結局、該当チップの英文データシートを読む必要が生じます。それも大変な作業で、今回のPIC24FJ64の設定がなんとなく判るまで2日間もかかりました。 それでも上の設定が正しいのかは?です。とりあえず動いいていますので、良しとします。

C:\Program Files (x86)\Microchip\xc16\v1.24\docs\config_docs

最近のPICマイコンは、i/oピンの多重化がすさまじく、何もしなければパラレルポートを使う事が出来ません。このマイコンも、端子機能はピン配置図に書かれている名称の左から順に優先度が高いと説明されていますが、一番右側に書かれたパラレルi/oをそのまま使う方法が判りません。

ほとんどのi/oで一番左側に書かれている機能はADです。 ADを使うか使わないかを最初に設定しないと、i/oをHに設定したのに、いつのまにかLになっているとかの異常動作に遭遇します。 HI-TECH CでもADは最初に設定する事が必要でしたが、16bitになって、ほとんど全てのi/oがAD対応になっていますので、面倒がらずに、全部設定が必要でした。 ADの設定を行うと、各ピンの一番右側に書かれた端子機能をそのまま使う事ができました。 

次にHI-TECH CではLATB1などのようにi/oのビット指定が出来るのですが、この単語ではエラーになります。これらの定義はincludeファイルの中にあるはずですが、そのファイルを見つける事ができませんでした。結局、WEBで調べてLATBbits.LATB1のように記述したら良いと判るまで、またまた2日間もかかってしまいました。 16bitをパラレルで一挙に書き込む場合はLATB = 0xFFFFでOKでした。

とりあえず、マイコンはソフトで書かれた通りi/oのH,Lの設定が出来るようになりましたが、今度は、LCDがまともに動作しません。 このメーカーのホームページにサンプルコードがありますが、このクラスのLCDは8bit RGBドライブオンリーで、マイコンからのパラレルドライブやシリアルドライブの実働例はありません。FAQなどを調べていくと、世界中のユーザーが困っているようです。 私の実験では、マイコンからのパラレル8bitドライブはなんとかなっても、シリアルドライブは全く不可というのが実態のように思えます。多分、自社でもテストした事がないのでしょう。

このような環境で、案の定、16bitドライブにしてもまともにカラーが出ません。悪戦苦闘の末判った事はRGBモード時設定するように説明されたカラーコードフォーマットの指定をマイコンからのパラレル接続でも行わないとダメという事でした。

このLCDは以下の初期設定で16bitパラレルドライブの基本的な動作は可能となります。

IM0をHとして、IM1-IM3はL(GND)にしておき、ハードリセットをかけた後のイニシャル処理です。

void init_LCD() {
 lcd_CMD(0x01);//ソフトリセット
 __delay_ms(120) ;
 lcd_CMD(0x11);//Sleep Out
 __delay_ms(120) ;
 lcd_CMD(0x13);
 lcd_CMD(0x0036);//Memoryアクセス(画面のスイープ方向設定)
 lcd_DATA(0x0048);//画面は縦置きOnly
 lcd_CMD(0x3a);//カラーモード書式設定
 lcd_DATA(0x55);//16bit(5-6-5)        この設定が必要でした。
 lcd_CMD(0x002A);//カラムアドレスセット
 lcd_DATA(0x0000);//SC[15-8] 0から
 lcd_DATA(0x0000);//SC[7-0]
 lcd_DATA(0x0000);//EC[15-8] 319まで
 lcd_DATA(0x00EF);//EC[7-0]
 lcd_CMD(0x002B);//ローアドレスセット
 lcd_DATA(0x0000);//SP[15-8] 0から
 lcd_DATA(0x0000);//SP[7-0]
 lcd_DATA(0x0001);//EP[15-8] 239まで
 lcd_DATA(0x003F);//EP[7-0]
  lcd_CMD(0x0029);//Display ON 検討中はこのタイミングで。
 lcd_CMD(0x002C);
 __delay_ms(200) ;
 
}

今回の配線図を下記からダウンロードできます。

マイコンとLCDは専用ラインでつながっていますので、CE端子は常時Lで良く、またLCDの内部情報の読み出しも行いませんので、RD端子も常時Hとしております。

LCDMeter0.pdfをダウンロード

Lcd320meter1

開発開始してから約1週間経過した時点で左のようなアナログメーターの表示に成功しました。

前回のドット数は160x128でしたが、今回は320x240でそれなりに分解能も向上しておりますが、単純に約4倍の面積に拡大しただけでは、このような綺麗なグラフィックにはなりません。 

まず、JW CADを使い、正確な目盛板を作成します。 JW CADのフォントは限られていますので、グラフィックの部分のみを作画して、これをスクリーンショットでGIF画像に変換します。 この時のサイズは面積比で16倍以上あります。 この画像をWindows標準のペイントで読み込み、文字を入れます。フォントも色も豊富にありますので、デザインは簡単です。

デザインが終わったら、実際のLCDに表示するピクセルサイズまでペイントで縮小します。 この状態での各ピクセルのカラーデータをそのまま取り込むという手法で実現できます。

PCでの画像処理は、その豊富なアプリのおかげで、簡単に実現できますので、これをマイコンが扱えるデータに変換する為に、変換プログラムを作る必要が生じます。 PICのマイコンとLCDをにらみながら、ちまちまソフト開発をやるはずでしたが、 このSWRメーターの目盛が表示できたのを境に、マイコンプログラムの開発ではなく、PCのアプリ開発がメインになってしまいました。

そして、さらに、1週間くらい過ぎた時点で、PCアプリが完成しました。

下の画像は、PCの画面上に表示された、LCD表示用カラーコードジェネレーターです。  LCDと同じピクセルサイズに縮小したグラフィックデータを読み込むと、C言語で扱えるLCDへ表示する為のデータファイルを出力します。 出力されたファイルを#include命令で読み込み使う事ができるようになります。  バグだらけのアプリでしたが、なんとか動作するようになりました。

Ccg0

 このアプリはTcl/TKと呼ばれるインタープリンターで作られておりますので、動作は遅いですが、コードジェネレーターですから、たとえ1分かかろうが問題ありません。  実際のところは数秒で出力されます。

バグだらけですが、ソースをダウンロードできます。Ccord_Generator4.tclをダウンロード

defaultcolor.txt を同じディレクトリーに置いてRUNさせて下さい。defaultcolor.txtをダウンロード

グラフィックデータをC言語で出力するのはOKですが、フォントデータを出力させる場合、都度ソースを微調整していましたので、このままでは機能しません。 取説が無いので作った本人も、もう忘れてしまいました。

このアプリはTcl/Tkというインタプリンターをインストールする必要があります。インストールの詳細は「Tcl/Tk」で検索してください。 ダウンロード元は全部英文で、個人情報の登録が必要です。

メーターの振れ角を66度として、0.5度きざみで指針データを作り、これをROM上に配置して指針の動きを表現するもので、PC上でのシュミレーションではうまくいってましたが、いざPIC24Fのマイコンに書き込む作業をしたところ、ROM不足でエラーとなってしまいました。

なぜなら、この指針用データが90Kバイトくらいあり、完全なメモリー不足でした。 本来は、もっと早く気付くべきところですが、アプリが完成して、コードを出力したら、そのファイル容量が170Kバイトくらいを示しましたので、やっと判った次第です。 データのスパンを1度ごとにして、容量を半分にしてみましたが、指針データ以外で24Kくらい使っていますので、やはり足りません。

現在のROM容量64Kに収まる範囲で可能な方式として、指針データは常に計算で出し、指針より少しだけ広い四角い範囲のグラフデータに、指針データを重ねると、ちょうどドット数の多いフォントと同じようなデータが作れますので、これをグラフ画面上に上書きすることにしました。

Lcdswrmeter2

左の画像は、そのようにしてメーター目盛の上に、指針とその周囲の目盛画像を上書きしたものです。最初の案より指針データを計算する分だけ動作が遅くなっています。

この目盛のSWR1.0から無限大までの指針移動時間は実測で、約3.3秒ありました。指針位置の計算はsin()と平方根で出していました。

Y座標は、半径やXの値を2乗してから、平方根ですから、かなり時間がかかりそうです。 そこで、平方根を止め、Xはsin()で、Yはcos()で計算させると、指針の速さは約2.7秒まで改善しました。

三角関数は時間がかかると思われますので、sin()の0度から90度までを予め、PCで計算し、その結果を10000倍した数値を整数として、配列に記憶させ、sin(deg)はそのまま取り出し、cos(deg)はsin(90-deg)で取り出す事にしました。   結果は約1.3秒まで改善しました。

関数のなかを見渡して、繰り返しループの中で、初期設定など、結果が変化しない処理事項を取り出し、ループの外に置くとか、見やすくするために置いた変数を固定値に変えるとかの作業を行った結果SWR1.0から無限大までの指針移動時間は約1秒まで改善出来ました。

Lcdswrmeter3

次に、一部、浮動小数点(double)を使用していた計算式を10000倍の整数計算した後、四捨五入した整数に直す方法で、全ての計算を整数で行った結果、ゼロからフルスケールまでの時間は約0.65秒となりました。

左の画像はその速さで指針が動いている時のショットです。動きが速いので、指針もボケて写っていますが、見た目のチラツキは少ないです。

アナログメーターの指針移動時間で違和感が無いのはゼロからフルスケールまで0.3秒くらいの移動時間ですから、あと半分くらいは短縮必要です。

しかし、 現在はメータードライブだけしかやっていませんので、例えば、SWRメーター以外にインピーダンスメーターも同時に表示したり、周波数カウンターの周波数表示など、負担が増えるばかりで、指針の移動スピードもどんどん遅くなってしまいます。

また、この方式の場合、チラツキは最少に抑えられますが、指針の移動スパンは1度以内に限られます。VUメーターではないので、かなり遅い追従時間でも問題は無いと思われますが、実際に作ってみないと、何とも言えません。

次回は、LCDの全画面表示にトライします。

TFT LCDによるアナログメーター 3 に続く。

INDEXに戻る

2015年5月 4日 (月)

TFT LCDによるアナログメーター1

<カテゴリー:PICマイコン

AadigitaltestPICのマイコンを使用して、アンテナチューナーのコントローラーやATUの製作を行ってきましたが、この過程で、SWR計も作ってきました。 PICマイコンに少し、慣れたころ、このマイコンのAD入力にCAA-500のインピーダンス検出DC信号や、SWR検出DC信号を加え、アンテナアナライザーによるインピーダンスやSWRのデジタル表示にトライし、RやXの表示も行えるところまで実験ができましたので、次の目標は、オール自作のアンテナアナライザーと決めました。 左の画像は、CAA500のセンサー基板に、PIC16F1939を使用した自作のマイコンボードとLCDディスプレーを接続し、マイコンで周波数や、SWR、インピーダンス、R、Xを表示させている実験風景です。

アンテナアナライザーのセンサー部分や、広帯域発振回路など、なんとかなりそうですが、これをメカニカルアナログメーターや、キャラクタ表示の液晶で実現してもMFJやコメットと同じなので、面白く有りません。  そこで、マイコンでは、無理と言われる、液晶表示の疑似アナログメーターの実験を始める事にしました。 最近の車のインパネは高精細度の液晶によるスピードメーターやタコメーターがすばらしいデザインの元で実装されております。またKENWOODの最新モデルにも、液晶表示のアナログメーターが実装され、デジタル駆動にもかかわらず、非常にわかりやすいアナログメーターとなっています。 これらの最新技術のLCDアナログメーターに及ばないにしても、安いマイコンと、安い液晶でどこまで、液晶表示のアナログメーターが実現できるかの実験記です。

使うマイコンは、少し役不足ですが、ATUに使ったPIC16F1939。 これで160x128ドットのTFT液晶をドライブします。 液晶は262K色対応で、普通の写真を表示させても、遜色のないカラー画像が表示できるという中国製です。

とりあえずは、TFT LCDを初期設定し、画像や、文字を表示できるところまでトライします。

この実験ボードの配線図です。TFT-LCD.pdfをダウンロード

実験に使うマイコンはROMもRAMもグラフィックLCDをドライブするには小さすぎますので、今回は、基本動作を得とくする事が目的となり、実践版は次の試作までお預けとします。

試用するLCDはDisplaytechのDT018ATFTという品番で、液晶ドライブIC ILI9163Cが内臓されています。 このILI9163Cという台湾製のICはインターネット上でも良くみかけるST7735とコンパチで、ST7735用のイニシャルルーチンでちゃんと初期設定されてしまいます。初期設定が成功したら、後は、ILI9163Cのデータシートを読みながら、ああでもない、こうでも無いと試行錯誤する事になりますが、いつのまにか、文字表示や自作したイメージデータの表示が出来るようになりました。

Pic_lcd_demo

左の画像は、なんとか表示できるようになったので、SWR計の目盛をLCD上に表示させたものです。SWR検出信号をADにつなげば、赤色の指針がSWRを指します。

メーターの目盛は3角関数とピタゴラスの定理を駆使して、描かれており、ブリッジの不平衡電圧を角度に変えて、目盛と同じ式で指針を表示していますので、指示誤差は有りません。

150x50ピクセルくらいの範囲で描画していますので、あまりきれいではありませんが、実験機としては十分です。

ただし、大きな問題があります。

動作がおそろしく遅いのです。

指針が移動するのに、0.5秒くらいかかります。1度移動しようが、60度移動しようが0.5秒です。 これでは、全く使いものにはなりません。  これは、指針も3角関数と、ピタゴラスの定理でXYドットをいちいち計算して表示していたのが最大の原因です。  

これを、指針のドットのみ1度ごとのXYデータの配列として記憶させて置き、測定された指針角度から、このイメージデータを呼び出し、表示させる事にしました。 角度データは80度分必要ですが、とりあえず10度分だけ作って振らせてみました。 指針は赤色で描画した後、一度白色で再描画し、指針を一度消し、次に新しい位置に、赤で描画するという事を繰り返します。 このドット単位での書き換え動作は、目盛と指針が重なった場所の目盛表示を復帰させるのも、ドット単位で行えますので、復帰させるドット情報も簡単に計算できます。 しかし結果は、かなり早くなりましたが、指針のチラツキが目立つようになりました。 まだまだ、改善が必要です。

次に、文字フォントと同じように8x16の書き換え可能なドットパターンを用意し、この範囲に含まれる目盛のドットに加えて、指針のドットも書き込み、これを指針角度に応じて、画面上に再描画させる動作を実験しました。この場合、指針の移動に伴い、旧指針を消すという動作と消えた目盛の復帰動作が不要になりますので、面を書き換える時間増より、コマンド切り替えの回数減少から、LCD側の動作速度がかなり早くなります。 また、ちらつきもほとんど無くなる事も判りました。 ただし、LCDにカラードットを書き込む前のドットパターン作成作業は複雑になりますので、マイコンのクロックを上げたり、16bit RISCタイプに変えるなど、対応が必要になると思われます。

次は、マイコンを16bit品に変え、かつLCDも320x240ドット品に変えて、動作速度の改善に取り組みます。

同じようなLCDをお使いになりたい時の為に、このLCD用の初期設定ルーチンだけですが、以下に示します。

void lcd_CMD(unsigned char CM) {//1-byteコマンド
      RS = 0;
      WR = 0;
      LATD =CM;
      WR = 1;
      RS = 1;
     }
void lcd_DATA(unsigned char DA) {
      WR = 0;
      LATD = DA;
      WR = 1;
     }

void init_LCD() {
      lcd_CMD(0x01);//ソフトリセット
       __delay_ms(120) ;
      lcd_CMD(0x11);//Sleep Out
      __delay_ms(120) ;
      lcd_CMD(0x36);
      lcd_DATA(0xC8);
      lcd_CMD(0x2A);
      lcd_DATA(0x00);
      lcd_DATA(0x00);
      lcd_DATA(0x00);
      lcd_DATA(0x9F);
      lcd_CMD(0x2B);
      lcd_DATA(0x00);
      lcd_DATA(0x00);
      lcd_DATA(0x00);
      lcd_DATA(0x7F);
      lcd_CMD(0x36);
      lcd_DATA(0xAC);
// lcd_CMD(0x29);//Display ON このコマンドは画面クリアーの後が良い。
      lcd_CMD(0x2C);
      __delay_ms(200) ;
 }

TFT LCDによるアナログメーター 2 に続く。

INDEXに戻る

2014年6月20日 (金)

エレキー回路の自作(PIC12F675)

 

<カテゴリ: PICマイコン >

再開局したころから、オートアンテナチューナー(ATU)を模索し、これを自作しようともくろみましたが、挫折が多くて今だに手づかずの状態です。 ここにきて、再度ATUの自作に挑戦しようと思いますが、ATUはそのコントローラーをマイクロコンピューター(マイコン)で作る必要が有り、マイコン開発は避けて通れない状況です。 現役時代はマイコン屋に仕様書を出して、バグを見つけては、ソフト屋をいじめるのが仕事でしたので、自らマイコンソフトを開発した事はありませんでした。 そこで、インターネットでも情報の多いPICマイコンの勉強を始める事にしました。

ハムがマイコンのソフト開発を勉強しようと思えば、最初の教材は、「エレキー」と相場が決まっています。 以下見よう見まねで作ったエレキー回路を紹介します。 なお、ソースファイルは、あまりにも恥ずかしくて公開する自信はありませんでしたが、かなりの方がこの記事にアクセスいただいておりますので、未熟ながら記事の最後の行でダウンロードできるようにしました。

Pickit3_2

使用するマイコンは、開発事例の多い「PIC12F675」とします。秋月で80円で売っていました。 開発環境はMPLAB IDEとHI-TECH Cそれに書き込みアダプターPICkit3です。 書き込みアダプター以外は無償アプリです。

まず、この開発環境構築でトラブリました。メインで使用しているPCはWindows7 64bitバージョンですが、アプリをインストールしてPICkit3を接続してもPICkit3がコネクト状態になりません。USBドライバーがうまくインストールされないようです。Helpをたよりにインターネットで調べていくと、Windows7の64bit版はトラブルらしく、わざわざ解決方法が絵入りで説明されていましたが、私のPCの表示とは一致しません。1日、ああでもないこうでも無いといじったあげく、64bit版を諦めて、Windows XP 32bit版に開発環境を構築する事にしました。インストールが完了し、PICkit3をつなぐと、簡単に認識され、かつファームウェーアーのアップデートを行うということで「OK」をクリックすると、アップデートされ、かつこのPICkit3が正常につながったとコメントがでました。 試に、このファームウェーアーをアップデートしたPICkit3を64bit版のPCにつないでみましたら、こちらも正常に動作するようになりました。  結局、マイクロチップが公式に言っている64bit PCによる不具合ではなく、自社のファームウェーアーにバグが有ったようですね。

やっとPICの開発の勉強ができる環境が整いましたので、PIC12F675の英文データシートとグーグル翻訳を駆使して、ハードの設計を行いました。グーグル翻訳の日本語はほとんど意味が判りません。翻訳された日本語文の中から、判らない単語のみピックアップして、後は英語の原文で理解するのが早いですね。

Elekey675

 上が、このエレキーの全回路図です。 ドットとダッシュの入力端子はマイコンの中の約20KΩの抵抗でプルアップしてあります。送信機に接続されるキー出力はN-MOS FETのオープンドレインとして可能な限り消費電流を減らしました。 また、キーイングのスピード調整は10KΩの可変抵抗で分圧された電圧をマイコンのA/Dコンバーターで読み込み連続可変できるようにし、かつこの可変抵抗器に加える電圧もマーク信号の時だけ加える事により電流を押さえます。 A/Dコンバーターへの信号源出力インピーダンスは10KΩ以下が推奨されていますので、可変抵抗器は20KΩでもOKですが、手持ちが無かったので10KΩとなっています。また、方形波ですが760Hzのサイドトーン信号も出力しています。このサイドトーン信号を実際に使う時は、この端子の後に2段くらいのCRフィルターを設けて高調波を少なくすると聞きやすい音になります。 電源は乾電池3本の4.5Vを想定しています。 CNP1のコネクターはPICkit3を接続する端子で、開発が終われば不要になります。

省電力の配慮をしたのに、SLEEPモード時の消費電流は360μAもあります。乾電池につなぎっぱなしで液漏れせずに使用できる消費電流は、過去の経験から140μAまではOKでしたが、メーカーの判らない100円ショップの電池でも安心していられるのは50μAくらいまでです。SLEEPモードにはいる手順が悪いのか、初期設定が悪いのかと、変更、コンパイル、確認を10数回も繰り返しましたが、一向に改善しません。 もしかしたら、ICが不良品?と予備のマイコンと交換したら、あっさりと直ってしまいました。 動作はすべて正常なのに、SLEEP状態の電流が多いという現象に遭遇しましたら、まず最初にマイコンチップを疑った方が早く解決できそうです。 ICは最初からの不良品ではなく、私が壊したと思われます。なぜなら、一度ラッチアップさせ、マイコンがアッチッチになった事がありましたので。

Elekey675b

最終的な消費電流は以下のようになりました。

マーク出力状態  1.4mA

スタンバイ状態   0.78mA

スリープ状態       1μA以下

マーク信号の出力が終わってから、約3秒後にスリープ状態へ移行します。

左の画像はスタンバイ状態での消費電流を測定したものですが、スリープ状態では、テスターの針はほとんどゼロを指します。 開発ボードにはLEDも見えますが、実際は使っていません。

一応完成したので、キーイングすると、今までのCK-100Aに比べて非常に打ちにくく、さらに時々スリープモードから復帰しません。 CWの短点はコンテストの時など30m秒くらいの長さしかなく、時には25m秒くらいの速さになる事もありますので、通常のチャタリング吸収手法は使えず、とりあえずチャタリング対策なしで設計していました。 キーを自作のキーに変えると、さほど気にならないのですが、GHDのキーにすると、打ちにくさが目立ちます。 そこでGHDキーのチャタリング波形をチェックしてみました。

Elekey675c

左の画像はGHDキーでキーダウンしたときのマイコンのGP4端子の波形です。一応1KΩと0.01μFのフィルターは入っていますがノイズを押さえる効果があっても、チャタリングの吸収は出来ておりません。  チャタリング吸収の為に、通常20~30m秒かけて、入力変化があったと判定させますが、この期間は次の入力を受け付けない訳で、短点、長点メモリーというエレキーには欠かせない機能が制限を受けます。 従い、このキーを受け付けない期間は出来るだけ短くする必要があります。 この為、タイマー0を使ったKey入力の状態チェックは約4m秒くらいで行っていました。 GHDキーのチャタリングを、デジタルストレージオシロで十数回測定した結果、上の画像が一番ひどいチャタリングで幅は5m秒くらいあります。 その為、チャタリング発生中に次のキー状態をチェックする事になり、多重割り込みが発生したり、キー入力を誤判定ていたものでした。

キーのチャタリングで5m秒はかなり優秀な方で、手入れが悪いと、10m秒くらいになる事もあります。 よって余裕をみて、タイマー0で割込みが発生してから、約15m秒は次の割込みを禁止し、短点、長点メモリーも機能している事を確かめて、とりあえず逃げました。

ソフト屋からみると、かなり低レベルの部分でトラブりましたが、とりあえず勉強になりました。

しばらく使っていましたが、どうもしっくりいかないので、キー入力のチェック間隔を約16m秒にした上で、割り込み処理中にあった15m秒の割り込み禁止期間は廃止し、かつ長点の長さを従来の3短点から3.3短点に変更しました。 これで、28ワード/分のコンテストスピードでも違和感なく打電できるようになりました。

エレキー用HEXファイルをダウンロード

HEXファイルは説明なしで更新しております。気になる方は最新のファイルをご利用ください。

Eleky675d_2

Elekey675case_2

出来上がったエレーキーは、小さな透明ケースに収納し、FT-450を使った移動運用時に持っていくことにしました。 50MHz 50W運用で時々誤動作がおこりますので、キー出力ラインにLCのフィルターを追加してあります。 LもCもジャンク箱から最初に掴んだものを取り付けましたので、定数は吟味しておりません。

ワンチップマイコンでは無く、プログラムの不要なICによるエレキーの製作はエレキー回路の追加 で紹介しております。

とりあえず、PICマイコンの開発ができるようになりましたので、本来の目的である、ATUの開発に着手しました。 バリコン式ATUの自作 1 を参照下さい。

スリープモードへの入り方、復帰の仕方のみ、ソースファイルを抜粋しました。

void interrupt TimerSleep( void ) {
     if (T0IF == 1) {             // タイマー0の割込み?
          TMR0 = 0x00 ;         // タイマー0の初期化
           if ((GP5 == 0) && (dashfg == 1)) {  
                dotmemofg = 1;
                dashmemofg = 0;
                }
      if ((GP4 == 0) && (dotfg == 1)) {  
             dashmemofg = 1;
             dotmemofg = 0;
             }
       slpcount++;//スリープカウンター
       T0IF = 0;
       }
 if (GPIF == 1) {//sleep modeからの割り込みチェック
       cnt0 = 0;
       GPIF = 0;
       GPIE = 0;
       } 
}

以下main()の中のループの一部です。

if (slpcount > 200) {//スリープカウントが200を超えたら
  GPIF = 0;
  GPIE = 1;
  asm ("sleep");//スリープモードへ
  asm ("nop");//スリープモードから復帰した時のダミー命令
  GPIE = 0;
  }

...

全ソースファイル elekey12f675.cをダウンロード

2017年2月追記

このエレキーの電池は100円ショップの単4アルカリ乾電池3本でしたが、2年8か月でとうとう力尽き、2017年2月に新品と交換しました。

INDEXに戻る