PC から,リアルタイム信号処理を行っている Nucleo-F446 を制御する例.

Dependencies:   mbed SerialTxRxIntr F446_AD_DA_Multirate

main.cpp

Committer:
MikamiUitOpen
Date:
2021-04-12
Revision:
14:2f1af14e6c0d
Parent:
13:bcaee883b812

File content as of revision 14:2f1af14e6c0d:

//----------------------------------------------------------------------
//  NUCLEO-F446RE で アナログ信号の入出力の際に,出力の標本化周波数を,入力の
//  標本化周波数の4倍にするクラス F446_Multirate を使い,PC からの指令でパラ
//  メータを変更する例
//
//  処理の内容:AD 変換器からの入力に倍率を乗算し DA 変換器に出力する
//      倍率は PC からの指令で変更する
//      PC からの指令: 0 ~ 5000(0.0 ~ 1.0 倍に対応)
//      音量調整あり/なしは PC からの指令により ACTIVE/THROUGH の切り替えが可能
//
//  PC 側にデータを送る際のフォーマット
//      先頭の1文字で送る内容を区別する
//          L: ラベルに表示する文字列
//          S: スライダ(TrackBar)のツマミの位置
//          M: ステータス・バーに表示する文字列
//
//  PC 側のプログラム
//      F446_AD_DA_Ctrl
//
//  2020/04/12, Copyright (c) 2020 MIKAMI, Naoki
//----------------------------------------------------------------------

#include "F446_Multirate.hpp"
#include "SerialRxTxIntr.hpp"
#include  <cctype>          // isalpha() で使用
#pragma diag_suppress 870   // マルチバイト文字使用の警告抑制のため

using namespace Mikami;

const int FS_ = 10000;              // 入力の標本化周波数: 10 kHz
F446_Multirate myAdDa_;             // 出力標本化周波数を4倍にするオブジェクト
SerialRxTxIntr rxTx_(32, 115200);   // Serial クラスの受送信割込み用オブジェクト
                                    // ボーレート:115,200 baud

void SendParm(float param);             // パラメータの値を送信
void Respond(bool &sw, float &param);   // 受信バッファのデータが有効になった場合の処理

int main()
{
    // 以下の割り込み優先順位の設定を忘れないこと
    NVIC_SetPriority(ADC_IRQn, 0);      // ADC 終了割り込み:最優先
    NVIC_SetPriority(USART2_IRQn, 1);   // USART2 割り込み:次に優先

    float volume = 0.4f;    // 音量を決める変数(初期値)
    bool sw = true;

    myAdDa_.Start(FS_, A1); // 標本化を開始する,入力:A1
    while (true)
    {
        //------------------------------------------------------------
        // ここにディジタルフィルタ等の処理を記述する
        float xn = myAdDa_.Input(); // 入力
        float yn = sw ? volume*xn : xn;
        myAdDa_.Output(yn);         // 出力
        //------------------------------------------------------------

        Respond(sw, volume);    // PC からの指令に対応する処理
    }
}

// 受信バッファのデータが有効になった場合の処理
//      必要に応じて param の計算方法を変更すること
void Respond(bool &sw, float &param)
{
    if (!rxTx_.IsEol()) return; // 受信バッファのデータが有効ではない場合は処理を行わない

    string str = rxTx_.GetBuffer();
    if (str == "ENQ")
    {
        rxTx_.TxString("ACK\n");    // PC からの "ENQ" に対して "ACK" を送信する
        SendParm(param);            // 最初に Label に表示する文字列を送信

        char buf[16];
        sprintf(buf, "S%5d\n", (uint32_t)(5000*param));
        rxTx_.TxString(buf);        // 起動時のスライダ(TrackBar)の位置を送信

        rxTx_.TxString("M入力信号をそのまま出力します.\n");
    }
    else    // "ENQ" 以外の処理
    {
        if (isalpha(str[0]))    // 先頭が A ~ Z, a ~ z の場合
        {
            if (str == "ACTIVE")  sw = true;
            if (str == "THROUGH") sw = false;  
        }
        else                    // 先頭が A ~ Z, a ~ z 以外の場合
        {
            // PC から送信されるデータの範囲: 0 ~ 5000
            // param の値に変換する,0 <= param <= 1
            param = atoi(str.c_str())/5000.0f;

            // PC の Label に表示する文字列を送信
            SendParm(param);
        }
    }
}

// パラメータの値を送信(必要に応じて sprintf() の内容を変えること)
void SendParm(float param)
{
    char buf[32];
    // Tera Term を使わない場合は,"\r" は無くても構わない
    sprintf(buf, "L音量: %3d %%\r\n", (int)(param*100));
    rxTx_.TxString(buf);    // label1 に表示する文字列を送信
}