Top Page SD330 コントローラ製作
自作工程のメモとして
2010.Dec
2011/03/06:更新中


  2010年10月公開の「SD330 ベランダ設置」 で予定していましたSD330の自動コントローラが、やっと実現性を帯びてきましたのでこれから順次公開していきます。
 実は、先の公開からほとんどQSOはせず、土・日曜日はほとんどこれに係りきりで、その間に回路作成・ブレッドボードで実験・半田付け・シャー シ加工や、プログラミングを続けてきました。 また、初めてPIC用のCコンパイラーを使いました。
Cコンパイラーは、あまり情報が無いMikroCですが、サンプルが充実しているのと、記述の前提となるプリプロセッサーの宣言等が省略されてい るため、あっけなく動いたのと、他の公開コードをそのまま実行できず何日も悩んだりして、結果的に楽しむことができました。

以下は、ブレッドボードに続く試作2号で、しばらくこのままでデバッグを続ける予定にしています。

*このコントローラを改造して、Hi-Q-4/160 用のコントローラを公開しています。(2013/01/04)

 

■ブロックダイアグラム

以下のような大まかな構想を実現しようと、取り掛かかりました。
2011年1月現在、赤外線の受光処理は実現しておりませんが、試作2には部品を組込み済みで、本掲載の最後のあたりで紹介できる予 定です。(2011/02/11:追加掲載)

構想の概略
1.DDSを使ってSWアナライザーと同様に、スクリュードライバーアンテナを調整する。
2.現RIGの周波数信号を(CI−Vで)取り込み、スタートSWを押せば自動的に同調操作をする。
3.手動でも、発振周波数を変更でき、自動モードと同様にスタートSWで同調操作をする。
4.赤外線を使ったリモコンで、電源ON以外の主要な操作を実施できる。

 

■回路図 (2011/02/11:追加  2011/03/12: 変更

プリント基板でもつくる時には電源のON/OFF回路を再検討したいと思いますが、当初予定していた機能はこの回路で動作するよう になりました。サンプル回路等の寄せ集めですが、何かの参考になれば幸いです。
(水魚堂さんの回路図エディタBSch3Vを使用させていただきました。)

CI-V関連の回路を一部変更しました。(2011/03/06)
ANTリレー部分を修正しました。(2011/03/12)

 

1.DDSの選定(DDS−60)

 HF帯(30MHz)できれば50MHzまでカバーするためのDDSは、当初から手持ちのAD9834では無くAD9851を使う予 定にしていました。 そこでWeb上で検索しているとN2APBさんの「DDS−60」が目に留まり、日本国内で実際に使用している方も いらっしゃるようですので、注文してみることにしました。

PayPalも初めて使用しましたが、注文から2週間程度で届きました。最初、PayPalの登録時に日本語の住所・氏名を使ったため に、英語表記の住所を送るようメールが来たりして手間取りました。(その後、英語表記に変更)
 更に、その後もう一個追加で注文し、合計2個の「DDS-60」が現在手元にあります。 私は、KITではなく完成品(85$)を注文 しましたが、円高のメリットを初めて体験し、得した気分になりました。

 

2.試作1(ブレッドボード) と 開発 ツール類

回路は、Web上で公開されているものの寄せ集めのようなもので、最初はブレッドボード上で実験して修正をしていき、ほぼ現在のもので 落ち着くと思われます。

■ブレッドボード

このときは、PIC 16F877Aを使ってスタートしました。 左上のDDS−60の近くにある銅箔がむき出しのプリント基板は、 Calkitの「50Ω インピーダンスブリッジ」です。その基板上にあるトランスの向きを変更して、「リターンロスブリッジ」として使 用していました。

その「リターンロスブリッジ」の信号をAD8307:ログアンプで受けて、PICのAD端子に取り込んでいます。
後にYahooのオークションで「方向性結合器」(以下、方結器)を見つけ、より性能が良いのではと思い入手後現在も方結器を使っていま す。
実験段階でしたのではっきりしたことが言えませんが、この「リターンロスブリッジ」でもSWRの最低点は方結器と遜色なくディップしてい たように思います。ただし、ブレッドボード上で裸の状態でしたので、安定度からすると実使用は難しく、シールドBoxに入れればよいので すが、その工作が大変で方結器としました。

■PICライター(2011/01/01:追記)

PICライターは秋月電子の「PICプログラマV4」で、今回ファームウェアーをV6.72にアップしてやっと本格的に使うようになり ました。
当初は、書き込みの都度ゼロプレッシャーICソケットから外して、秋月PICプログラマに載せていました。しかし、一つひとつの処理を手 探りで実験しながら進めているため書き込み回数も多くなり、ICSPに切り替えるためPICkit2でも購入しようかと考えましたが、 JR3TGSさんのホームページで秋月PICプログラマV4をICSPで使う方法が紹介されていて、その通りできたため、以下のようなア ダプタを作ってICSP接続しています。

ただし、Sunhayatoの基板(MB-P02:販売完了品)を使った関係で、+5Vライン(32Pin)を追加してそのまま接続で きるようにしています。

 

ケーブルは全長55cmぐらいの長さになります。(あまり長いと誤動作するとのことでしたので)

 

そのまま載せるだけで、秋月「PICプログラマV4」で意識することなくプログラミングできます。

 

下の画像にあるプログラムSW(下部中央)の左が、ICSP用のソケット(CN1)になります。 プログラムSWで切り替えると、周辺 回路が切り離されてPIC単体に対してICSPの書き込みができます。 このMB−P02基板は、数年前に1セット購入していて今回まで 使わないまま保管していました。
現在は販売完了品になりましたが、使ってみると大変便利に使うことができました。

 

■Cコンパイラー MikroC PRO Ver.4.6(2011/01/01:追記)

PICのCコンパイラーは初めて使うことになります。今までアセンブラで処理していましたが、いくらなんでも今回の処理は、相当の手順 が必要となり、新しいことに挑戦するつもりで、2Kワード以内ならそのまま使えるMikroCを試用しているうちに、何とかなりそうだと いう感触がありライセンスを申し込みすることにしました。
公開情報の少ないMikroCですが、Helpが充実していることと、バージョンアップも頻繁に行われていて、それにかかる追加の料金が 発生しない(2010年12月現在)ことで採用しました。

これも、11月始めからVer4.15を使っていて途中でV4.60にバージョンアップしましたが、以前のバージョンをアンインストー ルして新版をインストールし、登録用のCD−Rを入れることで制限無く使えています。
ライセンスの登録は、マイクロテクニカ社を通じて申請し10日程度すればCD−Rを送ってくれます。

以下の水色のマスク部は、姓名が入ります。

 

3.試作2 汎用ケースに実装 (2011/01/01:追記)

 文頭にもありますように、試作2としてリードの「P−12」ケースに収めてみました。サイズは、W:250・H:60・D:150で すが、実現できるか半信半疑で本格的なケースを選択するのを躊躇しており、うまく動けばそのとき考えることにしました。 しかし、この ケースも加工することに半日以上費やしましたし、自分で使う物だと格好を気にしてもしょうがありませんので当面はこのまま使うことになる と思います。

後ろ側から見た画像です。
左から、RIG・ANT・SD330モーター・CI−V・主電源SW・13.8V(15V)ソケット、となります。 また、ACアダプ ター用の穴は広げすぎて不恰好になっています。

 

こちらは、左側のリードリレーが電源保持用で、右側がアンテナと13.8Vの供給リレーです。リードリレーは約30年以上前の物をパー ツBoxの中から探し出して使っています。こんな機会が無いとこの先も使わずじまいのまま終わってしまうことになったかも知れません。 (動いてよかった)

 

こちらが「方向性結合器」方結器(ZFDC-10-5)で、中古ですがミニサーキット社のカタログ価格程度で入手しています。また、 SMAコネクターは秋月電子(他の部品もほとんどが秋月)からの通販で入手しましたが、一部は大阪・日本橋の各パーツショップからのもの も有ります。

 

DDS−60を中心とした画像。
左下は、AD8307:ログアンプで、入力のコンデンサーは回路上は1つですが、2種類を挿せるようにICソケットを使っています。ま た、終端としての50Ωもソケットで外すことができるようにしています。

 

4.DDS−60(AD9851)のコー ディング (2011/01/08:追記)

使っている人がいるということで、パーツだけ先に注文しました。久しぶりに一からデータシートを眺めながら色々実験をしてみましたが、 後閑さんの公開情報を参考にしても、DDS−60がリセット回路を持たないため、起動のシーケンスや、MikroCのバ グ?に悩まされ、正しい記述が何かということを何日も考え続けました。(正しい表記方法があるとは思いますが、読 みきれませんでした)
動いてしまえばカンタンなことでしたが、他の方の参考になれば幸いです。(2011/01 /15:バグ?部分が正常動作となりました。私の勘違い)

■DDS−60の周辺回路

DDS−60は、PICのREポートにつないでいますが、DDS−60の外部にリセット回路は出ていなく、データの供給線(3本)のみ となっています。
REポートを採用したのは、特に意味は無く、丁度3ビット分が独立していて都合がよさそうだからでした。

■DDS−60の起動

起動は、空のパラメータを送る。
データシートを眺めていると、初期値のパラレルモードからシリアルモードへ変更するために、電源ON後にDDS−LOAD信号を送り込む 必要があり、その関数( DDS_on(void) )として、以下のように記述してみました。

//// Port E 定義 DDS Controle
sbit DDS_CLOCK       at RE1_bit;                // DDS-60 CLOCK
sbit DDS_LOAD        at RE0_bit;                // DDS-60 LOAD
sbit DDS_DATA        at RE2_bit;                // DDS-60 DATA
sbit DDS_CLOCK_Direction    at TRISE1_bit;
sbit DDS_LOAD_Direction     at TRISE0_bit;
sbit DDS_DATA_Direction     at TRISE2_bit;

// 省略


main()
{


TRISE = 0x00;                      //  set direction to be output

// 省略


}

// DDSの設定制御 //// 電源ON時に実行する ///////////////////////////
                ///// 初期のパラレルモードからシリアルモードに設定
void DDS_on(void)
{
    int di;
            delay_ms(1);
            DDS_CLOCK = 1;                      //W0ロード
            delay_us(1);
            DDS_CLOCK = 0;
            delay_us(1);
            DDS_LOAD = 1;                       //シリアルモード設定
            delay_us(1);
            DDS_LOAD = 0;
            delay_ms(1);

/// 日本語データシート(P11)で推奨しているため、
/// シリアルモード設定後、直ちに最初のダミーデータを送り込む。
/// 周波数は0Hz、x6 モードのみ設定。2010/11/21:JLB

    for(di=0; di<40; di++)
    {
        if(di == 32)
            DDS_DATA = 1;
        else
            DDS_DATA = 0;

        delay_us(1);
        DDS_CLOCK = 1;
        delay_us(1);
        DDS_CLOCK = 0;
        delay_us(1);
    }
    DDS_LOAD = 1;                       //周波数値ロード指示
    delay_us(1);
    DDS_LOAD = 0;
}

 

■DDS周波数の設定

後閑さんのサンプルをそのまま利用させていただいています。

PICFun AD9851 で検索すれば最初に出てきます。

これにも1週間程度悩み、デバッグのためのコードを埋め込み実験を繰り返して、代替処理を記述して動かしていましたが、MikroCに おける型宣言の見直しとポート出力の記述変更だけで、動作することが確認できました。(2011/01/15:MikroC PRO for PIC v.4.60.0.0)

/// 周波数設定値
static union {                           // 後閑氏のサンプルに有った共用体の
            unsigned long    Phase;      // 記述。型はMikroCに変更。
            unsigned char    iPhase[4];  // 
    } DDSdata;                           // 2011.01.15 JLB
                                         //  

 

//////  周波数(10進)をDDSに送出 関数  ///////
void DECtoDds(long dds_f )
{
        int i, j, mask;
        float Para;

        Para = 23.86093 * dds_f;            //2の32乗÷180MHz=23.86092942
        DDSdata.Phase = (unsigned long)Para;

        //IDirect = 1;               // IRP bit must be set manually for
                                   // indirect access to 'sub' variable
                                   // コンパイラーからsub[4] を使うときは 
                                   // マニュアルでIRPをセットするよう指示
                                   // が有ったため。2010.12.25 JLB
                                   // (これが無いとDDSがうまく発振しない)
                                   // しかし、18F452 では不要でした。
                                    

        //// 周波数値32ビット出力する
        for(i=0; i<4; i++)
        {
                mask = 0x01;                 //ビットマスクの初期設定
                for(j=0; j<8; j++)
                {
                    if(DDSdata.iPhase[i] & mask)
                        DDS_DATA = 1;
                    else
                        DDS_DATA = 0;
                    delay_us(1);
                    DDS_CLOCK = 1;                  //ビット送信クロック
                    delay_us(1);
                    DDS_CLOCK = 0;
                    mask = mask << 1;                //ビットマスクのビットシフト
                }
        }
        /// 設定制御8ビット出力
        mask = 0x01;                                      //ビットマスクの初期設定
        for(j=0; j<8; j++)
        {
                if(0x01 & mask)                           //6倍モードのみ1
                    DDS_DATA = 1;
                else
                    DDS_DATA = 0;
                delay_us(1);
                DDS_CLOCK = 1;                    //ビット送信クロック
                delay_us(1);
                DDS_CLOCK = 0;
                mask = mask << 1;                 //ビットマスクの1ビットシフト
        }
        DDS_LOAD = 1;                                //周波数値ロード指示
        delay_us(1);
        DDS_LOAD = 0;

        //IDirect = 0;

}

 

5.CI- Vによる周波数データの取込み (2011/01/22:追記)

CI−V回路は、アイコムのトランシーバを使っている関係で、連動することを最初から想定していました。現在は、IC−7600Mを 使っておりUSB端子からCI−Vコントロールをしていますが、PC側とは別系統で従来の3.5mmモノラルジャックで取出せる端子も空 いているため、直にその端子からの信号を取り込むことを考えていました。しかし、今までPICに直接接続したときにPIC側の信号が負論理正論理かを意識したことが無く、迷いました。(インバータを入れるか入 れないか)

これも、ブレッドボードの実験の時に確認できた回路ですが、以下のように接続して問題なく動作しています。

追記:本機を電源OFFにしていると、CI-V信号が引き込まれる現象が発生し、前日は ダイオードを挿入した修正をしましたが、その後も時々発生しており大掛かりな修正をしました。
先ず受信関係は、ポートならびにプルアップ抵抗からの引き落としをダイオードで阻止しています。
更に送信関係は、トランジスタ(2SC1815)でインバータを2段入れてPIC側のポートの影響をCI-Vへ与えないように変更し ました。
これにより、変 更前の本機の電源OFF時の状態は、通常3.3VあるCI-V信号が、ポートへの引き落としにより1.7Vから1.4Vぐらいまで下 がっており、PC等へ行く信号を引き落としていましたが、この回路変更で、電源OFF時でもCI-V信号は3.1Vまで回復していま す。
また、電源を入れたときは、プルアップの関係で5V付近の電圧を示しています。
(2011/03/06)

 

また、CI−Vの制御ですが、当初コントローラから周波数データを読み取るための起動コマンド(03)をどんなフレームで送り込めばよ いのかが分からず、フリーで公開されているDF4ORさんのCI−V TESTを使ってみました。
最初の行(E1 7A 03)となっている箇所は、FE FE 7A E1 03 FD の6バイトを送り込んでいます。

その応答が、7A E1 03 50 89 06 14 00 で、先頭のFE FE と最後のFD が省略されて表示されているところです。
更に、7A 00 00 と続いているところは、RIGのVFOノブを動かしたときに出力される信号で、本来はこの信号を取込めば事足りるのですが、RIGの10キー部でバンド チェンジした時はこの信号が出ません。そのため、特定の場合に周波数が取込めることが必要になってきます。
(2018/01/28:実信号は受信アドレス送アドレスの順ですが、ソフトで送受の順に書き換えているため修正します。)

 

CI=Vの信号受信は、実験段階では、通常の記述をしていましたが、動作確認後は割込みを使って取込んでいます。
civ_count で1バイトごと読み取りながら、フレームと照合して、BCDデータとして格納しています。
main() では、そのカウンターが11になったのを確認して、実周波数として取込んでいます。

// 省略

/ UART LCD ...
char civ_address = 0x7A;                    // iCOM IC-7600 CI-V Address
char pc_address = 0xE1;                     // PC address default 0xE0
int civ_count = 0;                          // CI-V割り込みで11桁読込みカウンタ
char civ_get_str[6] = { 0xFE,0xFE,0x7A,0xE1,0x03,0xFD };

// 省略


////////////////////////////////////////////////////////////////////////////////
// 割込み処理をここへ記述する。
// CI-Vは、9600bpsで11Byte受取るのに約11.5mSかかるため、割込みを使用。
////////////////////////////////////////////////////////////////////////////////
void interrupt() {
     if(PIR1.RCIF){

       if (UART1_Data_Ready() == 1) {            // If data is received,
                 uart_rd = UART1_Read();    // read the received data,
            switch (civ_count) {

            case 10:        if (uart_rd == 0xFD)
                                civ_count++;   // 周波数データ取り込み完了
                                else civ_count = 0;
                            break;
            case 9:         if (uart_rd == 0x00){
                                civ_bcd[3] = 0x00;
                                civ_count++;}
                                else civ_count = 0;
                            break;
            case  8:        civ_bcd[0] = uart_rd;
                            civ_count++;
                            break;
            case  7:        civ_bcd[1] = uart_rd;
                            civ_count++;
                            break;
            case  6:        civ_bcd[2] = uart_rd;
                            civ_count++;
                            break;
            case  5:        if(uart_rd == 0xfd)
                                civ_count = 0;
                                else civ_count++;
                            break;
            case  4:        if(uart_rd == 0xfd)
                                civ_count = 0;
                                else civ_count++;
                            break;
            case  3:        if(uart_rd == 0xfd)
                                civ_count = 0;
                                else civ_count++;
                            break;
            case  2:        if(uart_rd == 0xfd)
                                civ_count = 0;
                                else civ_count++;
                            break;
            case  1:        if (uart_rd == 0xFE)
                                civ_count++;
                                else civ_count = 0;
                            break;
            case  0:        if (uart_rd == 0xFE)
                                civ_count++;
                                else civ_count = 0;
                            break;
            default:        break;
            }
        }
        PIR1.RCIF = 0;

      }
}




void main(){


// 省略


// 以下はwhile(1) ループの中の処理


// 周波数データをCI-Vから取込み、DDSの発振周波数へセット(実発振はせず)
          if(civ_count == 11)                // CI-V to civ_bcd[]
          {
              BCD_move(dds_bcd, civ_bcd);
              BCDtoLcd(2, 8, dds_bcd);
              civ_count = 0;
          }


// 省略



// 処理シーケンスの関係で、先にSTART SWが離されたかを確認する。
      if((START_b4 != 0) && (SW_start == 1)) {  // START SWがOFFされた?
            if(AM_sw != 0) PIE1.RCIE = 0;       // USART 割込み禁止
            Freq = BCDtoDec(ant_bcd);
            Freq2 = BCDtoDec(dds_bcd);
            Freq_tmp = MOTER_search(Freq, Freq2);
            if(Freq_tmp == 0) {
                Lcd_Out(1, 5, "Err");           // 念のためErr表示
            }else {
                DECtoBcd(Freq_tmp);
                BCDtoBcd(acc_bcd, ant_bcd);
                BCDtoLcd(1, 8, ant_bcd);
            }
            START_b4 =0;
            if(AM_sw != 0) PIE1.RCIE = 1;       // USART 割込み許可
        }

      if(SW_start == 0){                        // START SWがONされた?
            if((AM_sw != 0) && (START_b4 == 0)){
                UART1_Write_Text(civ_get_str);  // CI-V読込みコマンドを送出しておく。
                Delay_ms(20);                   // 受信割込み待ちの時間。
            }
            START_b4 = 1;
         }
// 省略

}

 

6.赤 外線リモコンでコントロール (2011/02/11:追加)

当初から赤外線リモコンで操作できるようにと考え、赤外線受光センサー(秋月)を配線していましたが、取り掛かり始めたのがCI-Vの 処理を終えた1月20日前後からでした。
最初は、CI-V割込みの記述と同時に赤外線の信号有りを割り込みで検出し、その割込み状態を見てスタートSWと同じ動作(ANTのモー ターを受信周波数に合わせる)をさせて様子を見ていました。
ところが、部屋の蛍光灯を点灯すると、誤検出しているのが確認できましたので、本格的に取り組むことにしました。

採用した発光側は、手元に転がっていた空気清浄器のリモコンで、本体はすでに処分しており、ボタンが少ないのが決め手になりました。
これに決める前は、ホームセンターに売っている汎用のリモコンを考えていましたが、再利用で活用することにしました。

 

■信号解析

最初は、ほとんどの赤外線リモコンはNECフォーマットかと思い、実信号を見ずに仕様の通りプログラミングしたところ、全然反応せず以 前使ったフリーソフトの HandyOscillo に世話になりました。

このリモコンは、以下の<信号1>からスタート信号が5mS前後あることが分かります。また、図の信号は上下が逆転しているので、画面 上の上が0V側としてみてください。

<信号1>

 

次に、01信号ですが、まず「1」は、1.8mS程度あります。

<信号2>

 

更に「0」ですが、信号の最後のあたりに0状態が8ビット連続しているところから割り出すと、 0.9mS程度と確認できます。

<信号3>

 

もう一つの信号を見ると、以下のように最後の1バイトあたりに違いが出ています。

<信号4>

 

この赤外線リモコンの信号は8バイトになり、<信号4>は先頭から(LSB送出) 「 0x2c,0x52,0x19,0xf4,0x7b,0x37,0x0f,0x91」 となります。<信号3>の図は、最終バイトが 0x90 ですので、それぞれ4つのボタンに 0x90 〜 0x93 が割り当てられていることが分かり、やっとボタン別に機能を割り当てることができました。

 

プログラムの方になりますが、全体のソースは1600ラインほどになりましたし、コンパイル後のコードも46%程度使用している状態で すので、赤外線処理の関連部分のみを参考に書き出しておきます。
割込み処理では、タイマー割り込みで 0.1mS をカウント( t0_count )しています。この 0.1mS のカウントで、スタート信号の5msと、データ部については1.2mSより長短かで01を判定しています。

RB0/INT 割込みが有ると、赤外線の状態(IN_red)を65カウント(スタート+64ビット)し、簡単なエラー処理をして全部そろったら IR_flag を1にしています。
また、メインループでのチェックは、簡易的に8バイト目の照合だけで行っています。

メインループの処理手順についてですが、CI-Vの信号取り込み時間確保のため、あえて IR_flag が1の状態を後で確認して、モータースタートの処理は一周した次回のループで確認するようにしています。ただし、パワーOFFは、直後のタイミングで処理 しています。

// INFRA_red 関連の定義////////////////////////////////////////////
// 松下電工製の古い(10年前)空気清浄機のリモコン(EH3550/EH3560)
int IN_red;                 // INFRA_red 赤外線ポート割込みフラグ
char RC_poff[8] = { 0x2c,0x52,0x19,0xf4,0x7b,0x37,0x0f,0x90 };
char RC_start[8] = { 0x2c,0x52,0x19,0xf4,0x7b,0x37,0x0f,0x91 };
int  t0_count;              // 0.1mS Count Max 25.5mS
int  IR_flag;
char IR_buff[8];
int irx;


//省略

////////////////////////////////////////////////////////////////////////////////
// 割込み処理をここへ記述する。
// CI-Vは、9600bpsで11Byte受取るのに約11.5mSかかるため、割込みを使用。
////////////////////////////////////////////////////////////////////////////////
void interrupt() {
     if (INTCON.TMR0IF) {
          t0_count++;
          TMR0L = 131;                      // 131 to 256 = 125count(≒0.1mS)
          INTCON.TMR0IF = 0;
      }

     if(PIR1.RCIF){

       if (UART1_Data_Ready() == 1) {            // If data is received,
                 uart_rd = UART1_Read();    // read the received data,
            switch (civ_count) {

            case 10:        if (uart_rd == 0xFD)
                                civ_count++;
                                else civ_count = 0;
                            break;
            case 9:         if (uart_rd == 0x00){
                                civ_bcd[3] = 0x00;
                                civ_count++;}
                                else civ_count = 0;
                            break;
            case  8:        civ_bcd[0] = uart_rd;
                            civ_count++;
                            break;
            case  7:        civ_bcd[1] = uart_rd;
                            civ_count++;
                            break;
            case  6:        civ_bcd[2] = uart_rd;
                            civ_count++;
                            break;
            case  5:        if(uart_rd == 0xfd)
                                civ_count = 0;
                                else civ_count++;
                            break;
            case  4:        if(uart_rd == 0xfd)
                                civ_count = 0;
                                else civ_count++;
                            break;
            case  3:        if(uart_rd == 0xfd)
                                civ_count = 0;
                                else civ_count++;
                            break;
            case  2:        if(uart_rd == 0xfd)
                                civ_count = 0;
                                else civ_count++;
                            break;
            case  1:        if (uart_rd == 0xFE)
                                civ_count++;
                                else civ_count = 0;
                            break;
            case  0:        if (uart_rd == 0xFE)
                                civ_count++;
                                else civ_count = 0;
                            break;
            default:        break;
            }
        }
        PIR1.RCIF = 0;

      }
      if(INTCON.INT0IF == 1) {  //RB0/INT割込み 赤外線リモコン

          INTCON.INT0IE = 0;    //RB0/INT割込みの禁止
            switch(IN_red) {
                case 0:
                    t0_count = 0;
                    IN_red++;
                    TMR0L = 131;    // 131 to 256 = 125count(≒0.1mS)
                    INTCON.TMR0IE = 1; //Timer0/INT割込みの許可
                    break;
                case 1:
                if(xxx == 0) xxx = t0_count;
                    if((t0_count >= 40) && (t0_count <= 62)){   //実測4.9mS
                        t0_count = 0;
                        IN_red++;
                    }else{                                      //範囲を外れた
                        IN_red = 0;
                        INTCON.TMR0IE = 0; //Timer0/INT割込みの禁止
                    }
                    break;
                case 66:
                    IR_flag = 1;
                    IN_red = 0;
                    SENS_1 = 0;                   // Debug用LED点灯●
                    break;
                default:
                    if((IN_red >= 2) && (IN_red <= 65)) {   // 8Byte = 64bit
                        if(t0_count >= 21){                 // 2.1mS以上なら無効
                            IN_red = 0;
                            INTCON.TMR0IE = 0; //Timer0/INT割込みの禁止
                        }else{
                            irx = (IN_red - 2) / 8;
                            IR_buff[irx] = IR_buff[irx] >> 1;
                            if(t0_count <= 12){             // 1.2mSが敷居値
                                IR_buff[irx].B7 = 0;
                            }else{
                                IR_buff[irx].B7 = 1;
                            }
                            t0_count = 0;
                            IN_red++;
                        }
                    }
                    break;
            }

          INTCON.INT0IF = 0;    //RB0/INT割込みフラグクリアー
          INTCON.INT0IE = 1;    //RB0/INT割込みの許可
      }
}


void main(){




INTCON2 = 0b00111111;         // bit 7:  0 = Port B use pullup.
                                // bit 6:RB0/INT0 = Interrupt on falling edge
                                //   0 = RB0/INT0 ピンの立ち下がりエッジにより割り込み

  T0CON = 0b01010001;           // Timer Controle  ÷4
                                // bit 5:T0CS: TMR0 クロックソース選択ビット
                                //   0 = 内部命令サイクルクロック(CLKOUT)
                                // bit 3: PSAプリスケーラ割り当て 0=TMR0
                                // bit 2-0:プリスケーラレート 001=4


// 省略


// 以下はwhile(1) ループの中の処理


// 省略

      if(IR_flag == 2){
                                                // 赤外線割込みが有った?
            if(AM_sw != 0) PIE1.RCIE = 0;       // USART 割込み禁止
            Freq = BCDtoDec(ant_bcd);
            Freq2 = BCDtoDec(dds_bcd);
            Freq_tmp = MOTER_search(Freq, Freq2);
            if(Freq_tmp == 0) {
                Lcd_Out(1, 5, "Err");           // 念のためErr表示
            }else {
                DECtoBcd(Freq_tmp);
                BCDtoBcd(acc_bcd, ant_bcd);
                BCDtoLcd(1, 8, ant_bcd);
            }
            if(AM_sw != 0) PIE1.RCIE = 1;       // USART 割込み許可
            IN_red = 0;
            IR_flag = 0;
            INTCON.INT0IE = 1; //RB0/INT割込みの許可
        }

      if(IR_flag == 1){                         // 赤外線割込みが有った?

        if(IR_buff[7] >= RC_start[7]){
            if((AM_sw != 0) && (START_b4 == 0)){
                UART1_Write_Text(civ_get_str);  // CI-V読込みコマンドを送出しておく。
                Delay_ms(20);                   // 受信割込み待ちの時間。
            }
            IR_flag = 2;
         }

         if(IR_buff[7] == RC_poff[7]){
            IR_flag = 9;
         }

         if(IR_flag == 1) {
            IN_red = 0;
            IR_flag = 0;
            INTCON.INT0IE = 1; //RB0/INT割込みの許可
         }
         SENS_1 = 1;
      }


      if((OFFSW == 0) || (IR_flag == 9)){
          EEPROM_Write(0x00, ant_bcd[0]);
          EEPROM_Write(0x01, ant_bcd[1]);
          EEPROM_Write(0x02, ant_bcd[2]);
          POWER_on = 0;               // ここで電源OFF
          break;                      // 電源を落とすため関係ないが明示的に記述。
        }
// 省略

}

 

2011/02/11:ほぼ構想通りの動きをすることが確認できました。
また、初めてPICでC言語を使いました。冗長度の多いソースをだらだらと記述しましたが、間違いはコンパイラーが発見してくれ、最適化 処理もしてくれているようです。本当にMikroC が無ければ、途中で諦めていたと思いますし、「アセンブラーに戻れそうに無い」というのが現在の感想です。
この掲載が何かの参考になれば幸いです。

問い合わせ受付は終了しました。(20110718)

 

99.追記用(予備)