2009年06月27日

R8C/Tinyマイコンでエレキー

R8C/Tinyマイコンでエレキー

今回は、Renesasのマイコン R8C/15 R5F21154SP でエレキー(アマチュア無線用)を作ってみました。
エレキープロジェクト第10ステージとなりました。

今回使用したマイコンは、CQ出版社の「トランジスタ技術 2005年4月号」に付録していたものです。
長い間、本棚の肥しになっていました。

R8C/Tinyマイコンでエレキー

雑誌は既に品切れのようですが
付録マイコン基板の同等品であるMB‐R8CSがサンハヤト社から販売されています。
価格は、¥3,812です。

ポート配置はこちらです。
LED出力 → P11(負論理)
Buzzer出力 → P13(タイマZ波形出力)
Dot入力 → P34(内部プルアップ抵抗)
Dash入力 → P35(内部プルアップ抵抗)
速度調整 → AN8(VR入力)

ソフトウエア機能としては下記を使用しています。
A/Dコンバータ
タイマ(X)割り込み
タイマ(Z)波形出力
ポートの入出力/内臓プルアップ機能


いつも使用している発振器内臓ブザーがなくなったので、手元にあった適当なブザーを使いました。
そのため、タイマZを利用してブザー用のパルス出力を作りました。

また、デバッグには、あえて付属の「M16C R8C FoUSB/UART」を使用してみましたが、意外と使いやすかったです。
ただし、起動時にシリアル通信エラーになりやすいようです。

動作の様子はこちら



コンパイラを含め雑誌付属の開発環境でビルドしました。
ヘッダファイル(レジスタ定義)も雑誌付属のファイルをそのまま使用しています。

今後の公開予定は
Renesas H8/Tiny (HOS-µiTron4.0仕様)を使用したエレキー
Renesas SH-2(Interface付録) を使用したエレキー


ソースコードはこちらです。

//----I/O DESCRIPTION --------------------------------------------------------
//    LED出力        → P11(負論理)
//    Buzzer出力    → P13(タイマZ波形出力)
//    Dot入力        → P34(内部プルアップ抵抗)
//    Dash入力    → P35(内部プルアップ抵抗)
//    速度調整    → AN8(VR入力)
//----------------------------------------------------------------------------
// タイマXインターバルタイマ
//   ※カウントソース:f8=20MHz/8 (400nsec)
//   ※カウンタの設定:PREX=249,TX=199
//   ※タイマXインターバル周期:400nsec×(249+1)×(99+1)=10ms
//----------------------------------------------------------------------------
// A-D変換8ビットモード
//   ※8ビットモードによるA-D変換結果を変数へ格納
//      単発モード,周波数 f2選択,サンプル&ホールド有り
//----------------------------------------------------------------------------


#include "sfr_r815.h"                 // R8C/15 SFR定義ファイル

//----------------------------------------------------------------------------
//    Define Code Parameter
//----------------------------------------------------------------------------
#define    PARA_ALL_OFF    0x00
#define    PARA_DOT_ON        0x01
#define    PARA_DOT_OFF    0x02
#define    PARA_DASH_ON    0x03
#define    PARA_DASH_OFF    0x04

#define    LIMIT_VALUE        0x03            // チャタリングフィルタ用

#define    MAX_SPEED        3
#define    MIN_SPEED        15


//----------------------------------------------------------------------------
//    Define User Memory
//----------------------------------------------------------------------------
unsigned int    ParaTime;
unsigned int    ADCData;
unsigned char    Timer100ms;

unsigned char    ParaCode;
unsigned char    CntDotOn;
unsigned char    CntDashOn;

//----------------------------------------------------------------------------
// Sub関数
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// ボリューム電圧値
//----------------------------------------------------------------------------
unsigned char volume() {
    unsigned char tmp;

    adst = 1;                     // A-D変換開始
    while(adst == 1);             // A-D変換が終了するまで待つ
   
    tmp = ad & 0x00ff;            // A-D変換結果を保存する
    return tmp;
}

//----------------------------------------------------------------------------
//    LEDを点灯する処理
//----------------------------------------------------------------------------
void LED_ON() {
    p1_1  = 0;                    // ポートP1_1 Lレベル設定
}

//----------------------------------------------------------------------------
//    LEDを消灯する処理
//----------------------------------------------------------------------------
void LED_OFF() {
    p1_1  = 1;                    // ポートP1_1 Hレベル設定
}

//----------------------------------------------------------------------------
//    Buzzer On する処理
//----------------------------------------------------------------------------
void BUZZER_ON() {
    //p1_2  = 1;
    tzocnt= 0;                    // 波形出力 On
}

//----------------------------------------------------------------------------
//    Buzzer Off する処理
//----------------------------------------------------------------------------
void BUZZER_OFF() {
    //p1_2  = 0;
    tzocnt= 1;                    // 波形出力 Off
}

//----------------------------------------------------------------------------
//    Dotポートチェック
//----------------------------------------------------------------------------
char ChkDotPort() {
    if (p3_4 == 0)    return 1;
    return 0;
}

//----------------------------------------------------------------------------
//    Dashポートチェック
//----------------------------------------------------------------------------
char ChkDashPort() {
    if (p3_5 == 0)    return 1;
    return 0;
}

//----------------------------------------------------------------------------
//    Set Output port
//----------------------------------------------------------------------------
void SetOutput()
{
    if ((ParaCode == PARA_DASH_ON) || (ParaCode == PARA_DOT_ON)) {
        LED_ON();
        BUZZER_ON();
    }
    else {
        LED_OFF();
        BUZZER_OFF();
    }
}

//----------------------------------------------------------------------------
//    Check Input port
//----------------------------------------------------------------------------
void ChkInputPort()
{
    // for Dot
    if (ParaCode != PARA_DOT_ON) {
        if (CntDotOn < LIMIT_VALUE) {
            if (ChkDotPort())            //    Dotポートチェック
                CntDotOn ++;
            else
                CntDotOn = 0;
        }
    }
   
    // for Dash
    if (ParaCode != PARA_DASH_ON) {
        if (CntDashOn < LIMIT_VALUE) {
            if (ChkDashPort())            //    Dashポートチェック
                CntDashOn ++;
            else
                CntDashOn = 0;
        }
    }
}

//----------------------------------------------------------------------------
//    Set Parameter Dash
//----------------------------------------------------------------------------
char SetParaDash()
{
    if (CntDashOn >= LIMIT_VALUE) {
        CntDashOn = 0;
        ParaCode = PARA_DASH_ON;
        ParaTime = (ADCData * 3);
        return 1;
    }
    return 0;
}

//----------------------------------------------------------------------------
//    Set Parameter Dot
//----------------------------------------------------------------------------
char SetParaDot()
{
    if (CntDotOn >= LIMIT_VALUE) {
        CntDotOn = 0;
        ParaCode = PARA_DOT_ON;
        ParaTime = ADCData;
        return 1;
    }
    return 0;
}


//----------------------------------------------------------------------------
//    キー処理メイン関数
//----------------------------------------------------------------------------
void key_sequence(void)
{
    unsigned char tmp;
   
    Timer100ms ++;
    if (Timer100ms > 10) {
        Timer100ms = 0x00;

        tmp = volume();
        if (tmp > 0x00) {
            ADCData = 0xff & (tmp >> 2);
            ADCData += MAX_SPEED;
        }
    }

    if (ParaTime != 0) {
        ParaTime --;
        if (ParaTime == 0) {
            if (ParaCode == PARA_DOT_ON) {
                ParaCode = PARA_DOT_OFF;
                ParaTime = ADCData;
            }
            else if (ParaCode == PARA_DASH_ON) {
                ParaCode = PARA_DASH_OFF;
                ParaTime = ADCData;
            }
            else if (ParaCode == PARA_DOT_OFF) {
                if (!SetParaDash())
                    ParaCode = PARA_ALL_OFF;
            }
            else if (ParaCode == PARA_DASH_OFF) {
                if (!SetParaDot())
                    ParaCode = PARA_ALL_OFF;
            }
            else {
                ParaCode = PARA_ALL_OFF;
            }
            SetOutput();
        }
    }

    ChkInputPort();
    if (ParaCode == PARA_ALL_OFF) {
        if (!SetParaDot())
            SetParaDash();
    }
    SetOutput();
}


//----------------------------------------------------------------------------
// メインクロック切替関数
//----------------------------------------------------------------------------
void set_MainCLK(void)
{
    prc0 = 1;                     // プロテクト制御(書き換え許可)
    cm13 = 1;                     // Xin-Xout端子切り替え
    cm05 = 0;                     // Xin-Xoutメインクロック発振
    cm06 = 0;                     // 8分周以外(分周なし)
    asm("nop");                    // 発振の安定待ち
    asm("nop");                    //    (同上)
    asm("nop");                    //    (同上)
    asm("nop");                 //    (同上)
    ocd2 = 0;                     // メインクロック選択
    prc0 = 0;                     // プロテクト制御(書き換え禁止)
}


//----------------------------------------------------------------------------
// 入出力端子初期設定関数
//----------------------------------------------------------------------------
void set_Port(void)
{
    drr1  = 1;                    // ポートP1_1 駆動能力High設定
    drr2  = 1;                    // ポートP1_2 駆動能力High設定
    drr3  = 1;                    // ポートP1_3 駆動能力High設定
    pd1_1 = 1;                    // ポートP1_1 出力モード設定
    pd1_2 = 1;                    // ポートP1_2 出力モード設定
    pd1_3 = 1;                    // ポートP1_2 出力モード設定
    p1_1  = 1;                    // ポートP1_1 Hレベル設定
    p1_2  = 0;                    // ポートP1_2 Lレベル設定
    p1_3  = 0;                    // ポートP1_3 Lレベル設定
    pu07  = 1;                    // ポートP3_4 - 3_7 プルアップ
}


//----------------------------------------------------------------------------
// タイマX タイマモード初期設定関数
//----------------------------------------------------------------------------
void set_timerX(void)
{
    txck0 = 1;                    // カウントソースf8=20MHz/8 (400nsec)
    prex  = 249;                // カウンタの設定
    tx    = 99;                    //   400nsec×(249+1)×(99+1)=10ms
    ilvl0_txic = 1;                // タイマX割り込み優先レベル(レベル1)
    ir_txic    = 0;                // タイマX割り込み要求フラグクリア
}


//----------------------------------------------------------------------------
// タイマZ タイマモード初期設定関数
//----------------------------------------------------------------------------
void set_timerZ(void)
{
    tzwc  = 1;
    tzmod0= 1;                    // 波形出力モード
    tzmod1= 0;
    tzck0 = 1;                    // カウントソースf8=20MHz/8 (400nsec)
    tzck1 = 0;
    prez  = 49;                    // カウンタの設定
    tzpr  = 0;                    //   400ns×(49+1)×(0+1)=20ms (50Hz)
    tzocnt= 1;                    // 波形出力 Off
    tzs   = 1;                    // タイマZ開始
}


//----------------------------------------------------------------------------
// タイマX割り込み関数
//----------------------------------------------------------------------------
#pragma interrupt timerX_int (vect=22)
//----------------------------------------------------------------------------
void timerX_int(void)
{
    key_sequence();                // キー処理メイン関数
}


//----------------------------------------------------------------------------
// A-Dコンバータ(8bit)初期設定関数
//----------------------------------------------------------------------------
void set_AD_8bit(void)
{       
    ch0 = 0;                     // アナログ入力端子AN8選択
    ch1 = 0;                    //
    ch2 = 1;                    //
    adgsel0 = 1;                // ポートP1グループ選択
    cks0 = 1;                    // 周波数 f2選択
    bits = 0;                     // 8ビットモード選択
    vcut = 1;                    // Vref接続
    smp  = 1;                    // サンプル&ホールド有り
}


//----------------------------------------------------------------------------
// メイン関数
//----------------------------------------------------------------------------
void main(void)
{
    set_MainCLK();                // メインクロックの切替
    set_Port();                    // 入出力端子初期設定関数
    set_timerX();                // タイマX タイマモード初期設定
    set_timerZ();                // タイマZ タイマモード初期設定
    set_AD_8bit();                // A-Dコンバータ(8bit)の初期設定

    CntDashOn = 0;                // ユーザメモリの初期化
    CntDotOn = 0;
    ADCData = MAX_SPEED;
    ParaTime = 0;
    ParaCode = PARA_ALL_OFF;

    asm("FSET I");                // 割り込み許可
    txs = 1;                    // タイマXカウント開始

    while(1){                     // 繰り返し(タイマ割込み待ち)
        ;
    }
}


スクイズ機能で不用意にキーがメモリされてしまい、速度を上げると余計な符号が出る不具合があります。



同じカテゴリー(マイコン開発)の記事
Fusion PCBでエレキー
Fusion PCBでエレキー(2020-04-01 19:00)


この記事へのコメント
初めまして

兵庫県在住の廣瀬と申します。
R8C/15を用いてエレキーを実現した http://micom.hamazo.tv/e1872953.html を拝見しました。
現在、モディファイしたものを一部に組み込んだCQマシンをR8C/M12Aで作成中です。
完成したら、JARL兵庫支部の講習会等でキットを実費程度で有償配布したいのですが、ご了解いただけますでしょうか?
ハード/ソフトとも公開することを考えています。
エレキー部分の元が浜松マイコン工房作成のものであることを明示したいと思います。
当方、ソフト屋でないものですから、ソースは貴作成のものを汚してしまうことになります。
時期は2012年5月以降になると思います。
まことに勝手ながら、ソフトの使用可否、使用条件等についてご回答いただきたくよろしくお願い申し上げます。
Posted by 廣瀬進一 at 2012年03月27日 23:03
廣瀬様

コメントありがとうございます。

ブログに掲載したソフトをご利用頂けるとのこと了解です。
ぜひ、ご興味ある皆さんに配布して頂ければと思います。

R8C/15エレキーのソースについては特に使用条件等はありません。
下記内容のみ記載頂ければ幸いです。

>エレキー部分の元が浜松マイコン工房作成のものであることを明示

以上、よろしくお願いいたします。
Posted by 宇都宮 at 2012年03月28日 10:26
上の画像に書かれている文字を入力して下さい
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。

削除
R8C/Tinyマイコンでエレキー
    コメント(2)