Monthly Archives: 9月 2026

32ビットマイコン(PIC32MX210F016B)の動作確認

目的

32ビットマイコン用のMCC Harmonyを使ってベアメタル環境でLチカを行い、基本的な開発環境の使い方とマイコンの動作を確認する

ハードウェア実装

PIC32MX210F016BはDIP基板なのでブレッドボードに実装しました。図1に回路図を示します。今回のマイコンは動作電圧が2.3 V~3.6 Vなので5 Vを加えると壊れるので注意してください。

図1 PIC動作確認用回路(ピンの名称は省略しているので全てを正しく表現できていないので注意)

Vcapにはコンデンサを、AVddとAVssにはVddとGNDを接続しておかないとプログラムの書き込みがうまくいきませんでした。またデータシート上ではコンデンサを置く推奨箇所があったり使わない端子の処理をする様に指示がありますが最低限VcapとAVdd、AVss、Vdd、Vssだけ接続しておけばとりあえず動作します。誤動作だったり外来ノイズに対して弱くなるのできちんとした設計(処理)をするに越したことは無いと思います。

また図のPICの端子は記載以外にもピンの割り当て可能な機能がいくつもあるので詳しくはデータシートを参照してください。今回は表記を省略しています。

MCCで基本設定

Harmonyの使い勝手がさっぱりわからなかったためまずは簡単にタイマー割り込みを使ったLチカを作って試してみました。

MCC Harmonyは32ビットマイコン用のコードコンフィグレータでアプリケーション層(ソフトウェア的な処理)、ドライバー層(I2CとかUARTの制御群)、ペリフェラル層(UART、I2C、タイマーとかのハードウェア)を連携させて開発しやすくする便利ツールです。(私個人の雑な理解です)

16ビットマイコンと同じ様に32ビットマイコン(今回はPIC32MX210F016B)でプロジェクトを作成して、MCCが開いたら、Device Resourceをクリックして図の様にTMR1を追加します。Harmonyのシステムサービスを利用して便利な?(慣れないとタイマー割り込みで直接動作させる方がわかりやすいと思うこととシステムサービスを使うためにもいろいろと苦戦したため)開発を試してみようと思います。

図2 MCC Harmonyの起動画面
手順1 MCC HarmonyでTMR1を追加する

追加されたTMR1をクリックすると下図のようにペリフェラルのタイマー1が追加されます。次にSystemのTimeサービスも追加します。

手順2 MCC HarmonyでTIME System Serviceを追加する

そうすると下図の様にHarmony CoreとFreeRTOSを追加するかを順番に聞かれるのでCoreサービスはYesでFreeRTOSはNoを選択します。ちなみに余談ですが私の技量ではこのマイコンにFreeRTOSを組み込めませんでした。機能を削ってもコンパイラの最適化レベルを変更してもヒープメモリやスタックサイズを変えてビルドしてもスタックメモリが足りないかヒープメモリが足りないと怒られてうまくいきませんでした。このマイコンにはSRAMが4 kBあるのですがMCC Harmonyで提供されるFreeRTOSだと難しいのかもしれません。

次に追加されたTimeサービスのTMRにTMR1を接続します。ひし形のポートをドラッグすれば接続できます。その次にピン設定をするためにPluginsからPin Configurationをクリックします。

手順3 ピン割り当てを行うためPin Configurationを開く

PinTable(図3)、PinDiagram(図4)、PinSettings(図5)の三つが開くと思います。Diagramで視覚的にピンを割り当てもできればPinTableでピンごとに割り当て可能な機能を見ながら決めていくこともできます。PinTableでパッケージを変えるとピンの割り当て可能な箇所が変わるようです。また入出力やプルアップ、プルダウンはPinSettingsのみでできる様です。今回は手順4に示すようにRA2にGPIOピンを割り当ててDirectionをOutにしています。

図3 Pin Table設定 パッケージを選ぶとそのパッケージで割り当て可能なピンが変化する
図4 Pin Diagram 視覚的にピン設定を確認割り当てできる
図5 Pin Settingsの画面
手順4 Pin Configurationから任意のピンに機能を割り当てる

ピン設定からMCCのタブに切り替えてGenerateボタンを押します。そうすればMCCでコードが生成されます。

手順5 内容が良ければMCCタブのGenerateボタンをクリックしてコードを生成する

main.cやapp.cなどのプログラムを変更すると次回生成時にそのコードがそのまま出てきます。再利用可能なアプリケーションモジュールとして使っていくからそういった作りになっているのかなとは思っています。(アプリケーション名が過去に作ったものと一致するとその時のcファイルが開かれるみたいです)

MCCのデフォルト設定でコードを生成するとmain.cとapp.cファイルが生成されます。またmain.cにはSYS_TasksとSYS_Initialaize関数が、APP.CにはAPP_Initialize()とAPP_Tasks()が生成されるようです。(MCCの内容によって変わります。) APP.Cにはユーザー(開発者)がステートマシンで状態を管理するプログラムを書いていくみたいです。

※MCCでHarmony Core Serviceが読み込まれているとデフォルトでAPP.C(設定変更できます。)が生成されます。

アプリケーション名の変更方法

上図の様にCoreサービスをクリックすると右側に設定画面が表示されます。Generation Harmony Application Files内のApplication NameをAPPから好きな名前に変えることで変更できます。また複数のアプリケーションを作りたい場合はNumber of Applicationsを1から好きな数に変更すればその個数分のCファイルが生成されるようです。2個目、3個目も同様に名前も変更できます。また生成しない設定も可能でその際はGenerate Harmony Application Filesのチェックを外します。

Projectツリーから生成されたmain.cを開いて一度クリーンビルドを実行し、ビルドが成功することを確認します。

手順6 クリーンビルドの実行を行ってコード生成の結果を確認する

app.hとapp.cに下のコードを書いて、Runしました。使い方がわからない関数とか変数があればその参照しているヘッダファイルとかcファイルとかを読んでみると関数の使い方や定義などの説明が丁寧に書いてあったので、時間はかかるかもしれませんが、理解の助けになるかもしれません。

ちなみにヘッダーファイルは手順6の左上あたりにあるHeader Files内にアプリケーション名のファイルがあると思います。

下のコードは行数を抑えるために一部コメントを削除しています。またあまり良い書き方ではないかもしれないので参考程度にお願いします。

#include "app.h" //ヘッダファイルにappData(任意の名称で良い)の構造体やステート名称の定義などをする今回はapp.hだがMCC上で名称変更できます
#include "system/time/sys_time.h" //システムサービスのコールバック関数を利用するのに必要なので追記


APP_DATA appData;


// *****************************************************************************
// ****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void APP_Initialize ( void )

//時間経過フラグ
void TimeExpired(){
    appData.tmrexpired = true;
}

//初期化処理
void APP_Initialize ( void )
{
    appData.state = APP_STATE_INIT;
    appData.tmrexpired = false;  
}

    void APP_Tasks ( void )


//主な処理内容
void APP_Tasks ( void )
{

    switch ( appData.state )
    {
        /* Application's initial state. */
        case APP_STATE_INIT:
        {
            SYS_TIME_CallbackRegisterMS(TimeExpired, 0, 1000, SYS_TIME_PERIODIC); //1000ミリ秒でTimeExpired関数を呼び出す
            bool appInitialized = true;

            if (appInitialized)
            {

                appData.state = APP_STATE_SERVICE_TASKS;
            }
            break;
        }

        case APP_STATE_SERVICE_TASKS:
        {
            if(appData.tmrexpired == true){
                appData.tmrexpired = false; //時間のフラグが立った後は再度フラグをリセットしておく
                PORTAbits.RA2 = !PORTAbits.RA2;
            }
            break;
        }
           default:
        {
            break;
        }
    }
}
//APP.hの内容

#ifndef _APP_H
#define _APP_H

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "configuration.h"


typedef enum
{
    /* Application's state machine's initial state. */
    APP_STATE_INIT=0,
    APP_STATE_SERVICE_TASKS,
    /* TODO: Define states used by the application state machine. */

} APP_STATES;

typedef struct
{
    /* The application's current state */
    APP_STATES state;
    bool  tmrexpired; //追加
    /* TODO: Define any additional data used by the application. */

} APP_DATA;

void APP_Initialize ( void );

void APP_Tasks( void );

#endif /* _APP_H */

プログラムを書き込む前にPICKIT5のPower設定で3.25 Vの電圧を出力するようにしておきます。(デフォルトで3.25 Vになっているとは思いますが念のため)

実行結果

プログラムを実行すると動画のようになりました。

デバッグについて

今回、思ったような動作をしなかった時があったので原因を探るのにデバッグ機能を重宝しました。デバッグはPICKIT5のPGDとPGCをマイコン側のPGDx・PGCx(xは任意の番号)端子に接続してMCCで設定を行えばプログラムと本体の動作の確認ができました。書き込みはPGDx・PGCxの好きなポートにつなげばできるのですがデバッグは設定が必要です。図6のようにSystemをクリックしてDEVCFG0内のIn-Circuit Emmulator..(緑色のマーカー表示の箇所)をデバッグに使いたいポートに設定します。はじめはPGx1になっていてMCLRの隣にデバッグポートも持っていきたかったのでPGx3に変更しました。

図6 デバッグに使うポートの変更画面

図7の様に赤丸をクリックするとPICに書き込みをした後にそのままデバッグが始まります。

図7 デバッグを始める場合

図8の様に赤丸の部分でコードを1行ずつ進めたりデバッグを停止したり、最初からやり直したりできます。左の赤いボタンはデバッグ停止でその隣の黄色のボタン(灰色になっていますが…)は一時停止です。一時停止ボタンを押すことで紫色のリセットや緑のContinue、他ステップ実行やカーソル箇所でのプログラム実行を行えます。変数の状態は画面下側のVariablesタブなどを開くと確認することができます。

図8 デバッグ操作方法

終わりに

今回は32ビットマイコンでLチカを通してMPLAB Xのツールの使い方やプログラミング方法を確認しました。いろいろな試行錯誤を行って開発環境の使い方が多少なりともわかってきたように感じます。

32ビットマイコンになると16ビットマイコンよりも複雑でとっつきにくいですが、用途や実現したい内容によって選択ができるものが増えることは良いことだと思います。今回はLチカの動作確認だけですが、かなり苦戦したので(自分の技量の問題もありますが…)誰かの役に立てれば幸いです。ここまで読んでいただきありがとうございました。

UART通信の確認(PIC16F13145)

UARTで通信のテストを行ってみました。個人的な備忘録になります。

使用部品

MCCの設定

UART通信を行うためにMCCでUARTドライバーを追加しておきます。図1の様にAdd Component若しくはDrivers & Peripheralsをクリックし、検索欄にUARTを入力して図2の赤丸をクリックします。

図1 MCCのUART設定
図2 UARTの追加画面

UARTを追加すると図3の様にUART1が追加されるのでUART1をクリックして右側のツールバー内のInterrupt Drivenを有効にしておきます。ボーレート(設定値:9600)やデータサイズなど他の項目はデフォルトの値にしています。

図3 UART1の設定

次にピン入力設定を行います。図1の画面上にあるPinsかPin Package Viewタブから必要な割り当てを行います。今回はUARTを追加したので図3の下側にEUSART1の項目が追加されています。受信と送信の動作を確認したいのでRX1(受信用)をPORTBの5番(RB5)・TX1(送信用)をPORTBの6番(RB6)に割り当てました。また送信ボタン入力用にPORTAの0番(RA0)を入力とし、動作確認用にPORTCの0番(RC0)を出力(LED1)として割り当てています。

図4 ピンの入出力設定

設定が終わったらProject ResourceからGenerateします。

プログラム

main.cに下記のコードを記述しました。

#include <string.h>
#include "mcc_generated_files/system/system.h"
      
void sendhello();

void main(void)
{
    SYSTEM_Initialize();
    INTCONbits.GIE = 1;
    INTCONbits.PEIE = 1;
 
    uint8_t data;
 
    while(1)
    {
        if(RA0 == 1){
                sendhello(); //送信ボタンを押したときに文字列を送信する
        }
          
        if(EUSART1_IsRxReady()){
                data = EUSART1_Read(); //入力値を読み込む
            for(uint8_t i = 0 ; i < data ; i++){
                LED1_Toggle();
                __delay_ms(100); //指定回数だけLEDを点滅させる
                LED1_Toggle();
                __delay_ms(500);
            }
                if(EUSART1_IsTxReady()){
                   EUSART1_Write(data); //入力値の確認用
                }
        }
    }    
}

void sendhello(){
    char msg[] = "Hello World\r\n";
        for(uint8_t i = 0; i < strlen(msg); i++)
        {
            if(EUSART1_IsTxReady()){
                EUSART1_Write(msg[i]); //LEDを点滅させながら文字を出力
            }
            LED1_SetHigh();
            __delay_ms(100);
            LED1_SetLow();
            __delay_ms(100);
        }
}

マイコンからパソコンへのUART通信はEUSART1_Write()で実装しています。パソコンからマイコンへはEUSART1_Read()で実装しています。EUSART1_Write()やEUSART1_Read()は1バイトずつ読み書きするためHello Worldのような文字列はfor文で1文字ずつ送信しています。受信に関しては、1文字(1バイト)のみなので1度だけ実行する形になっています。またUARTの動作確認が目的のためボタンのチャタリング対策は考慮していません。EUSARTの関数は下記リンクを参考にしました。

下記はMicroChip社のリファレンスになります。

参考:4.26.2 EUSART – Enhanced USART

組み立てた回路と外観

回路実装

図5のような回路を作りました。

図5 UART実験回路 スイッチ入力端子はプルダウンさせています

完成したものは図6に示します。

図6 実験回路外観

TeraTerm設定

そのままではCH340は使用できないのでまず下記メーカーサイトからドライバーを入手してインストールします。

ZIPファイルの中のSETUP.exeを実行してINSTALLを押すとドライバーが入ります。

CH341SER.ZIP – Nanjing Qinheng Microelectronics Co., Ltd.

図7 CH340のドライバインストール画面


TeraTermを起動する前にCH340をUSB接続します。TeraTermを起動すると接続先を聞かれるので画面下側のシリアルをクリックしてCH340と表示されているポートを選択します。

図8 TeraTerm 起動時の接続先設定画面

TeraTermの設定タブからシリアルポートをクリックすると図7の画面が表示されます。マイコン側(MPLAB XのMCC)のUART設定でボーレートや他の設定を変えている場合はTeraTerm側もそれに合わせて設定を変更します。通信設定が同じでないときちんと通信ができません。

図9 TeraTermのシリアルポート設定画面

TeraTermの端末画面(黒い画面)でマイコン側に設けたボタンを押すと端末画面にHello Worldが表示されると思います。またその画面でパソコンの任意のキーボードのキーを押すとそのキーに対応したASCIIコードがシリアルポートから送信されます。今回のプログラムでは指定回数だけマイコンのLEDを点滅させる動作をさせようとしたのですが上記の仕組みから意図した点滅動作か分かりづらくなりました。ASCIIコードは1バイトのため入力したキーとASCIIコードを照らし合わせれば意図したものかは判断できますが、折角なのでマクロ機能を使用して任意の数字(16進数)を送るようにしました。

調べてみるとTeraTermのマクロ機能を利用すればASCIIコードのデータではなく任意のデータを送れることが分かりました。マクロ機能を使用するために次の文字列をメモ帳に貼付して拡張子をttlにして保存しました。このデータをマイコン側に送ればLEDは5回点滅するはずです。

send $05
setdebug 2
図10 メモ帳の画面 コマンドを記述して保存する
図11 ttl形式でファイルを保存する

TeraTermでマクロを使用するにはコントロールからマクロをクリックして先ほど作成したttlファイルを開きます。するとコマンドが実行されます。

図12 マクロの実行方法
図13 図9で保存したマクロを開く画面

TeraTermの他のコマンドは下記が参考になると思います。

参考:TTL コマンドリファレンス

動作確認

ブレッドボード上のボタンを押すとTeraTerm上にHello Worldが表示され、マクロを実行するとブレッドボード上のLEDが5回点滅した後にTeraTerm上に05が出力されていることから、マイコンとパソコンで双方向に通信ができていることを確認できました。

動画の前半の動作はHelloWorldの送信で後半の動作はデータを受信した際の動作です。図13に実行結果の画面を示します。

図13 UARTの送受信動作の実行結果

以上の実験からUARTの送受信動作と基本的な取り扱い方の確認ができました。読んでいただきありがとうございました。

MCCのClassicを使いたかったがダメだった

目的

PIC 16F13145でSDカードの読み書きをしたかったのでMCCを使ってSDカードに対応させたかった。

実装方法

他の方の事例を調べると公式のライブラリにFATFSとSD/MMCがあるのでそれを組み込んでGenerateすれば、簡単にSDカードの読み書きできそうに見えた。(思っていた)

事前認識

32ビットマイコンはMCCのHarmonyが起動し、16ビットや8ビットマイコンはMCCのMelodyかClassicを選べるものだと思っていた。公式サイトでも普通に出来そうな雰囲気で書いてあるし、他の方はClassicを使って実装してたし…

MCCの挙動を確認してみる(MCC Core バージョン5.9.1の場合)

PIC 16F13145でプロジェクトを作成するとMCC Melodyが立ち上がるがどこを探してもMCC Classicに切り替える選択肢が無かった。MCCの古いバージョンを使ってClassicを使われておられる方もいらっしゃったのだが、何となく最新版を使いたいがために躊躇っていた。

FATFSだと容量の大きなSDカードだと対応できないとかでサポートしない方向なのかと思ってこのPICで試してみることを諦めた。どうやら32ビットマイコンならSDカードを使えるようにできるらしいことは調べて分かった。

そして別なPICを使って全く違うことを試してみようと思い、試しに買ってみたPIC 10F322用にプロジェクトを作成すると、普通にMCC Classicが立ち上がった。実にあっけなかった。

ここで16/8ビットの中でも古いマイコンはClassic、新しいマイコン16/8ビットはMelodyで32ビットマイコンはHarmonyが自動で選択されるのではと思った。

10F322・16F18313・16F13145・32MX210F016BでMCCの挙動を比較してみた。

16F13145は何事もなくMCC Melodyが起動した。Finishをクリックした後にMCCが起動しそのままMCCの設定画面に遷移した。

図1 PIC16F13145の新規プロジェクト作成の最終画面
図2 16F13145のMCC設定画面

10F322は何事もなくClassicが起動した。

図3 10F322の新規プロジェクト作成の最終画面
図4 10F322のMCC設定画面

16F18313は図5でFinishをクリックした後に図6の様に最初にMelodyかClassicのどちらにするか聞いてきた。

図5 16F18313のプロジェクト作成の最終画面
図6 16F18313のMCC初回起動時の画面
図7 図6でMelodyを選択後の画面

16F18313ではMCCのMelodyかClassicかを図6の画面で選択できるようになっているようだ。

32MX210F016Bは図8のFinishをクリックすると図9の様にHarmonyが起動した。

図8 32MX210F016Bの新規プロジェクト作成の最終画面
図9 32MX210F016BのMCC Harmonyの設定画面

まとめ

32ビットマイコンはMCC Harmony、16/8ビットマイコンはMCC Melody/Classicと漠然と認識していたが、PICの世代によって起動するMCCが異なることが分かった。また勝手な認識だが新しい世代の16/8ビットマイコンはMelody一択なのかなと思った。参考までにそれぞれのPICがいつごろから存在しているか調べてみた。

読んでいただきありがとうございました。誰かの参考になれば幸いです。