PR

【ワレコの電子工作】PIC32マイコン用の汎用実験基板でLEDチカチカ成功【動作確認編】

この記事は約29分で読めます。
スポンサーリンク
ワレコ
ワレコ

PIC32MKを使ってLEDチカチカ実験に成功した。

前回記事で紹介したように、PIC32MKと言う64ピンの高性能マイコン(最高周波数120MHz)用の汎用実験基板を設計した。基板製造はPCBWayさんに発注した。

前回記事(半田付け編)はこちら⤵️

前回記事ではPCBWayから届いたPIC32MK用汎用実験基板にパーツを半田付けした。

当記事では、そのPICマイコン基板を使ってLEDチカチカに成功したので、一連の試行錯誤の過程をワテの備忘録としてメモしておくことにした。

LEDチカチカだけでなく内部クロックや外部クロックの使い方、さらにPLLを組み合わせて分周や逓倍で別の周波数で動作させる手法などもある程度は理解出来た。

では、本題に入ろう。

スポンサーリンク
スポンサーリンク

PIC32MKでLEDチカチカ実験(その1)Harmony使用版

PIC18のコードを流用したらLEDチカチカしない

PICマイコンを使ったLEDチカチカ実験は、以下の記事⤵️で紹介しているようにPIC18と言う8bitマイコンでは成功している。

ワテがPICマイコンを使ったのは秋月電子で買ったこのPIC18F27J53-I/SPと言うマイコンが初めてだ。数カ月前の事だ。

そのあと、一気に難易度を上げて32bit RISCプロセッサー採用のPIC32MK1024GPK064と言うPICマイコンに挑戦したのだ。

で、PIC18でLEDチカチカに成功したCプログラム(MPLAB X IDEで作成)を流用して自己流でPIC32MKでLEDチカチカをやってみたら、全く光らない。

うんともすんとも言わないという感じ。

 

写真 PIC32MKマイコンでLEDチカチカ実験の様子(PCBWay発注基板)

ワテはデバッガ/プログラマはPICkit5を使っているのだが、プログラム自体は書き込めているようなのだが、LEDが全く光らない。光る気配すらない。

そもそも内蔵クロックで正常にPICが動作しているのかすらわからない。

ちなみに外部クロックには秋月電子で購入したMEMS発振子(48MHz)を付けているのだが、現状ではMEMS発振子のOE端子(Output Enable)はLのままなので外部発振子は停止中だ。

で、ChatGPTさんに質問してみたところ、PIC32のような高性能なマイコンのピンは幾つかの機能が多重に定義されていて、初期状態では必ずしもGPIO(汎用のデジタルIOポート)に割り当てられているとは限らない。かつ、GPIOだとしてもInなのかOutなのかも使う前に設定する必要があるとの事だ。

そこでChatGPTさんにLEDチカチカ用のサンプルコードを生成してもらい、コピーペーストでMPLAB X IDEのエディタに貼り付けて実行しても、やはりLEDがチカチカしない。

そんなやりとりをChatGPTさんと数回繰り返していると、ChatGPTさんが言うにはMPLAB X IDEにあるMCC(MPLAB Code Configurator)機能の中のHarmonyと言う機能を使えば、各ポートの設定作業をプログラムでやらなくても、事前にHarmonyの中でGUIを使って簡単に設定出来るとの事だ。

Harmonyを使ってPIC32MKでLEDチカチカ成功

で、実際にHarmonyを起動して、PIC32MKマイコンの64個のピンに初期状態で割り当てられている機能を確認する事が出来て、LEDチカチカに利用したいポートはGPIOのOutに設定する事が出来た(初期状態はInだった)。

そして「Generate」と言うボタンをクリックすると、それらの設定が有効になるように自動的にCのソースコードライブラリが生成されるのだ。

多数のCソースコードが自動生成されるのだが、例えばその中の1つである plib_gpio.c と言うソースコードは以下の通り。

/*******************************************************************************
  SYS PORTS Static Functions for PORTS System Service

  Company:
    Microchip Technology Inc.

  File Name:
    plib_gpio.c

  Summary:
    GPIO function implementations for the GPIO PLIB.

  Description:
    The GPIO PLIB provides a simple interface to manage peripheral
    input-output controller.

*******************************************************************************/

//DOM-IGNORE-BEGIN
/*******************************************************************************
* Copyright (C) 2019 Microchip Technology Inc. and its subsidiaries.
*
* Subject to your compliance with these terms, you may use Microchip software
* and any derivatives exclusively with Microchip products. It is your
* responsibility to comply with third party license terms applicable to your
* use of third party software (including open source software) that may
* accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
* INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
* WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
* BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
* FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
* ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*******************************************************************************/
//DOM-IGNORE-END

#include "plib_gpio.h"
#include "interrupts.h"




/******************************************************************************
  Function:
    GPIO_Initialize ( void )

  Summary:
    Initialize the GPIO library.

  Remarks:
    See plib_gpio.h for more details.
*/
void GPIO_Initialize ( void )
{

    /* PORTA Initialization */
    /* PORTB Initialization */
    /* PORTC Initialization */
    LATC = 0x0U; /* Initial Latch Value */
    TRISCCLR = 0x200U; /* Direction Control */
    /* PORTD Initialization */
    /* PORTE Initialization */
    /* PORTF Initialization */
    /* PORTG Initialization */


    /* PPS Input Remapping */

    /* PPS Output Remapping */


}

// *****************************************************************************
// *****************************************************************************
// Section: GPIO APIs which operates on multiple pins of a port
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Function:
    uint32_t GPIO_PortRead ( GPIO_PORT port )

  Summary:
    Read all the I/O lines of the selected port.

  Description:
    This function reads the live data values on all the I/O lines of the
    selected port.  Bit values returned in each position indicate corresponding
    pin levels.
    1 = Pin is high.
    0 = Pin is low.

    This function reads the value regardless of pin configuration, whether it is
    set as as an input, driven by the GPIO Controller, or driven by a peripheral.

  Remarks:
    If the port has less than 32-bits, unimplemented pins will read as
    low (0).
    Implemented pins are Right aligned in the 32-bit return value.
*/
uint32_t GPIO_PortRead(GPIO_PORT port)
{
    return (*(volatile uint32_t *)(&PORTA + (port * 0x40U)));
}

// *****************************************************************************
/* Function:
    void GPIO_PortWrite (GPIO_PORT port, uint32_t mask, uint32_t value);

  Summary:
    Write the value on the masked I/O lines of the selected port.

  Remarks:
    See plib_gpio.h for more details.
*/
void GPIO_PortWrite(GPIO_PORT port, uint32_t mask, uint32_t value)
{
    *(volatile uint32_t *)(&LATA + (port * 0x40U)) = (*(volatile uint32_t *)(&LATA + (port * 0x40U)) & (~mask)) | (mask & value);
}

// *****************************************************************************
/* Function:
    uint32_t GPIO_PortLatchRead ( GPIO_PORT port )

  Summary:
    Read the latched value on all the I/O lines of the selected port.

  Remarks:
    See plib_gpio.h for more details.
*/
uint32_t GPIO_PortLatchRead(GPIO_PORT port)
{
    return (*(volatile uint32_t *)(&LATA + (port * 0x40U)));
}

// *****************************************************************************
/* Function:
    void GPIO_PortSet ( GPIO_PORT port, uint32_t mask )

  Summary:
    Set the selected IO pins of a port.

  Remarks:
    See plib_gpio.h for more details.
*/
void GPIO_PortSet(GPIO_PORT port, uint32_t mask)
{
    *(volatile uint32_t *)(&LATASET + (port * 0x40U)) = mask;
}

// *****************************************************************************
/* Function:
    void GPIO_PortClear ( GPIO_PORT port, uint32_t mask )

  Summary:
    Clear the selected IO pins of a port.

  Remarks:
    See plib_gpio.h for more details.
*/
void GPIO_PortClear(GPIO_PORT port, uint32_t mask)
{
    *(volatile uint32_t *)(&LATACLR + (port * 0x40U)) = mask;
}

// *****************************************************************************
/* Function:
    void GPIO_PortToggle ( GPIO_PORT port, uint32_t mask )

  Summary:
    Toggles the selected IO pins of a port.

  Remarks:
    See plib_gpio.h for more details.
*/
void GPIO_PortToggle(GPIO_PORT port, uint32_t mask)
{
    *(volatile uint32_t *)(&LATAINV + (port * 0x40U))= mask;
}

// *****************************************************************************
/* Function:
    void GPIO_PortInputEnable ( GPIO_PORT port, uint32_t mask )

  Summary:
    Enables selected IO pins of a port as input.

  Remarks:
    See plib_gpio.h for more details.
*/
void GPIO_PortInputEnable(GPIO_PORT port, uint32_t mask)
{
    *(volatile uint32_t *)(&TRISASET + (port * 0x40U)) = mask;
}

// *****************************************************************************
/* Function:
    void GPIO_PortOutputEnable ( GPIO_PORT port, uint32_t mask )

  Summary:
    Enables selected IO pins of a port as output(s).

  Remarks:
    See plib_gpio.h for more details.
*/
void GPIO_PortOutputEnable(GPIO_PORT port, uint32_t mask)
{
    *(volatile uint32_t *)(&TRISACLR + (port * 0x40U)) = mask;
}




/*******************************************************************************
 End of File
*/

Cソースコード Harmonyが自動生成したGPIO Port制御用の各種の関数

上のソースコードの中には、GPIOポートを初期化してくれる関数GPIO_Initializeだけでなく、GPIO_PortToggleと言うまさにLEDチカチカにすぐ使える関数すら自動生成されるのだ。

その結果、LEDチカチカ成功には成功した!(ChatGPTさんによるHarmony版プロジェクト)

デバッグ実行でプログラムが動作しない問題発覚

ところがこのプロジェクトは通常実行(=デバッグ無し実行)すると正常動作するのだが、なぜかデバッグ実行するとmainにすら来ない。つまりmainに置いたブレークポイントまですら来ないのだ。

原因は不明だ。

この点に関してもChatGPTさんに相談して数時間悪戦苦闘したのだが、結局未解決。

そこで改めてChatGPTさんと会話していたら、LEDチカチカをやるなら必ずしもHarmonyは使わなくても良いとの事だ。

なのでこのあとでHarmonyを使わずにLEDチカチカ実験をやったのだが、その前に内蔵クロックに関しても気になるので調査してみた。

内部クロックが何MHz動作しているのか確認したが謎の症状発覚

ChatGPTさんに内部クロックの発振周波数をオシロスコープで観察したいので、どこかのピンに出力したいのだがどうしたら良いか質問してみた。

その結果、PIC32MK1024GPK064の場合には、クロック関連のピンは以下の2つがあるが、内部クロックを40番ピン(RC15)に出力して観察すれば良いとの事だ。

40番ピン OSC2/CLKO/RPC15/RC15
39番ピン OSC1/CLKI/AN49/RPC12/RC12

そこで、内部クロックをOSC2/CLKO/RC15に出力してオシロスコープで観察したのだが、オシロの画面上にはいちおうは方形波が出力されている。

写真 内部クロックを観察した例(40番ピンOSC2、2MHz=1周期500ns)

ただし、上写真のように綺麗な方形波では無く、強いリンギングがある。

周波数は約2MHzなのだが、この周波数はどこの何の周波数なのかすら分からない。

かつ振幅は期待していた0-3.3Vではなく、なぜか0-100mVくらいしか無いのだ。

なぜ振幅が3.3Vにならないのか不明。

おかしい。

この点に関してもChatGPTさんに色々質問しながら調査したが未解決。

その後、2MHzに関しては解明できた。
ChatGPTさんによると以下の通り。

PIC32MKでは:
 OSC2/CLKO ピンは
 OSCIOFNCビットに依存
さらに
 CLKOは SYSCLK/4 が出ます

つまり内部クロックは8MHzなのでその1/4の2MHzが観察されたのだ。

 

外部クロック(MEMS48MHz)が動作するか実験した

では外部クロックが正常動作するか実験してみることにした。

秋月で買った48MHz MEMS発振子のOE端子は43番ピン(RB5)に接続している。

43番ピン PGD2/RPB5/SDA3/USBID1/RB5

そこで外部クロックを試す為に43番ピン(RB5)をHにしてMEMS発振子OEを有効化した。

外部クロック出力信号は39番ピン(OSC1)に入力しているので、オシロでそのピンを観察した。

39番ピン OSC1/CLKI/AN49/RPC12/RC12

その結果、全く発振していない。あかんがな。

で、色々調査していたら判明したのは、OEを有効化するためにHにしたはずの43番ピン(RB5)がなぜかH=3.3Vではなく0.3Vくらいなのだ。なのでMEMS発振子は動かない。

では、43番ピンの近所にある47番ピン(RC13)をHにしてみたがそこも0.5Vと言うおかしな値なのだ。

47番ピン SOSCI/RPC13/RC13

で、その後の調査で分かったのは47番ピン=0.5Vの原因は47番ピンは入力専用なので出力には使えないからと判明した。

しかし依然として43番ピンが0.3Vの理由は不明。

もう訳わからん。

そこでMEMS発振子のOE端子にはVDD(3.3V)を直接接続して、電源ON直後から動作するように配線してみた。

その結果、オシロ計測で48MHzくらいで発振している事が確認出来た(下写真)。振幅も -1~+5Vくらいある。本来は0~3.3Vの方形波になるべきだが、測定系のケーブルなどのRLC成分がフィルター回路を構成してしまい、エッジが丸まっているんだろう。

写真 外部クロック(MEMS発振子48MHz)は48.14MHzで発振している

と言う事で、とりあえず外部クロックは正常動作しているようなので一安心。

ただし、ここまでの状況をまとめると以下の通り。

  • Harmonyを使うとLEDチカチカ成功
  • Harmonyを使うとDebug実行が失敗する(原因不明)
  • 内部クロック波形をOSC2/CLKO/RC15に出力すると2MHz(0-100mV)になる
  • 48MHz MEMS発振子のOE端子に接続している43番ピン(RB5)がHでも0.3V
  • 48MHz MEMS発振子のOE端子にVDD(3.3V)与えると正常に発振した。

と言う事で、一応はLEDチカチカには成功したが、未解決な問題が山積み。

しかしこんなことではへこたれないワテである。

PIC32MKでLEDチカチカ実験(その2)Harmony無し版

MPLAB X IDEで新たにプロジェクトを作成して、Harmony無しでLEDチカチカをやってみた。

ここでもChatGPTさんに教えてもらいながらCコードを試したら、案外簡単にLEDチカチカに成功したのだ。

な~んだ、Harmonyなんか使わなくてもLEDチカチカ出来るやん。

さらに、デバッグ実行も難なく成功。

ブレークポイントでも止まるし。

止まったあとはF5(Continue)を押すと継続実行も出来るし。

と言う事で、前節のHarmony版では動作しなかったDebug実行が正常動作するようになったのは大きな進展だ。

再びHarmony版を新規作成したらDebug実行成功

そこで、改めて新規にプロジェクトを作成して再びHarmony版のLEDチカチカのCコードを試してみた。

その結果、なぜかHarmony版でもDebug実行が正常動作するようになったのだ。

う~ん、訳わからんけれども良い方向に向かっている。

最初のHarmonyプロジェクトでDebugが動かない件で一つ思い当たる節があるのは、そのプロジェクトはHarmonyを採用するまでにHarmony無しでLEDチカチカをやろうとしていて、幾つかのCソースファイルやヘッダーファイルを追加したり削除したり、色々と試行錯誤した過程で何らかの設定を初期値から変更しているなどの可能性もあった。

つまりプロジェクトの中に何らかの「ゴミ」みたいなのが残っていた可能性は有り得ると思う。

この点に関してChatGPTさんの意見を聞いたところ、最初のプロジェクトでDebug実行が正常動作しなかった原因としてそのような「ゴミ」が関係している可能性は有り得るとの見解だった。

さらに40番ピンOSC2/CLKO/RPC15/RC15が約2MHz(0-100mV)だったり、43番ピン(RB5)Hでも0.3Vだった問題も解決していて、どちらも振幅は3.3Vくらいの出力なのだ。

と言う事で、ここまでのまとめとしては以下の通り。

  • Harmony有りでも無しでもLEDチカチカ成功し、Debug実行も成功
  • GPIO端子をHに設定しても3.3Vではなく0.1Vなどの症状も解決
  • ただし内部クロックをOSC2/CLKO/RC15に出力すると2MHzだがこれは何なのか不明(注:上記説明の通り解明済)

なので、このあとは内部クロックや外部クロックに関して重点的に調査することにした。

PIC32マイコンではクロックの与え方が複数ある

ChatGPTさんによるとPICマイコンでクロックを使う場合には幾つかの種類があるとの事だ。

例えばPIC32MXのようなMKより古いPICでは以下の通りらしい。

#pragma config FNOSC = FRC     // 内部FRCクロック(通常8MHz程度)使用、PLL使わない
#pragma config FNOSC = POSC    // 外部クロックを使用、PLLは使わない
#pragma config FNOSC = FRCPLL  // 内部FRCクロック + PLLを使用
#pragma config FNOSC = POSCPLL // 外部クロック + PLLを使用
//説明 
// FRC = Fast RC Oscillator(内部RCクロック)
// POSC = Primary Oscillator(外部クリスタルや発振器)

一方、PIC32MK系では以下のようにするらしい。

#pragma config FNOSC = FRC   // 内部FRCクロック(通常8MHz程度)使う
#pragma config FNOSC = POSC  // 外部クロックを使う
#pragma config FNOSC = SPLL  // System PLLを使う

ネット検索するとPIC32MKやPIC32MZの使用例は多く、サンプルコードも若干は見つかるのだが、PIC32MKは情報が少ない。

その結果、ChatGPTさんですらMXやMZ関する情報をゲットしてワテに教えてくれるので、その通りプログラムを書いてもビルドエラーや実行できても期待した結果にならない事が多い。

そんな試行錯誤を暫く続けた結果、最終的には外部クロックや内部クロックでPIC32MKを動作させたり、あるいはさらにそこにPLLを組み合わて目的の周波数でPIC32MKを動作させる事が出来た。

PIC32MKを内部クロック8MHzとPLLで120MHz動作させる方法

まずはPIC32MKを内部クロックで動作させる。かつPLLを組み合わせて最高周波数120MHzで動作させる設定だ。

#pragma config FNOSC = SPLL      // System PLLを使う
#pragma config POSCMOD = OFF     // 外部クロック(External Clock)使わない 
#pragma config FPLLIDIV = DIV_1  // PLL入力分周比:入力クロック8MHzを1で割る(そのままPLLに入力) 
#pragma config FPLLMULT = MUL_30 // PLL逓倍比:PLLで入力クロックを30倍する(240MHz) 
#pragma config FPLLODIV = DIV_2  // PLL出力分周比:PLL出力を2で割ってSYSCLKにする)(120MHz) 

ChatGPTさんによる補足

  • SYSCLK = PLL 出力 ÷ FPLLODIV で決まる
  • VCO 周波数 = (PLL入力 ÷ FPLLIDIV) × FPLLMULT
  • 安定した PLL 動作のためには PLL入力が規定範囲内 にあることが重要
  • REFOx を観測する場合、低周波や高分周では波形にジッターが見えることがあるが、CPU内部の SYSCLK は安定している

実際に上記設定でやったら期待通りに120Mhz動作に成功した(下写真)。

写真 PIC32MKを内部クロック8MHzとPLLで120MHz動作させた

なお上記オシロ画面では周波数は60MHzと計測されているが、その理由は120MHzをPIC32MK1024GPK064の51番ピン(TRD0/RPC7/RC7)から出力したのだが、120MHzのままだと信号が速すぎるようで、オシロ観察された波形はほぼ0V付近だった。

なので、出力段階で1/2の60MHzに落として出力したら無事に観察出来たのだ。でも内蔵クロックは正しく120MHzで動作している。

クロック信号を外部出力しても乱れた波形が観察される場合もある

ちなみに例えば内部クロック8MHzからPLLを使って24MHzを作るには、幾つかのパラメータの組み合わせが考えられる。

そこで以下の二通りの実験をした結果、パラメータの組み合わせによっては出力波形が安定しているが、場合によっては波形が乱れているものもある。

24MHz動作、安定波形

  • FPLLIDIV = DIV_1 //入力クロック8MHzを1で割る(8MHz)
  • FPLLMULT = MUL_12 //PLLで12倍(96MHz)
  • FPLLODIV = DIV_4 // PLL出力を4で割ってSYSCLKにする(24MHz)

注:上写真で12MHzとの計測値は、24MHz出力を1/2にして出力しているから

24MHz動作、波形が不安定

  • FPLLIDIV = DIV_1 // 入力クロック8MHzを1で割る(8MHz)
  • FPLLMULT = MUL_6 // PLLで6倍(48MHz)
  • FPLLODIV = DIV_2 // PLL出力を2で割ってSYSCLKにする(24MHz)

この点に関してはChatGPTさんの見解は以下の通り。

💡 要点

REFOx → RPCx 出力はあくまで「観察用」で、内部クロックそのものの安定性とは直接比例しない
SYSCLK / CoreTimer / LED 点滅の安定性が正常なら、PLL は正しく動作していると考えて問題なし

まあこの説明を信じるなら、オシロ波形が乱れていても内部クロックでは正常動作しているとの事だ。

実際、LEDチカチカはどちらの場合も正常にチカチカする。

PIC32MKを外部クロックとPLLで動作させる方法

次にPIC32MKを外部クロック(MEMS発振子48MHzを取り付けている)で動作させる実験をやってみた。

この場合もPLLを組み合わせて色んな周波数で試したのだが、当初は上手く行かなかったのだが最終的には成功した。

PIC32MKを外部クロックとPLLで動作させるには以下の記述をやれば良い(これもChatGPTさん情報だ)。

#pragma config FNOSC = SPLL      // System PLLを使う
#pragma config POSCMOD = EC      // 外部クロック(External Clock)を使う
#pragma config FPLLIDIV = DIV_x  // PLL入力分周比:入力クロックをxで割る
#pragma config FPLLMULT = MUL_x  // PLL逓倍比:PLLで入力クロックをx倍する
#pragma config FPLLODIV = DIV_x  // PLL出力分周比:PLL出力をxで割ってSYSCLKにする

注意点(ChatGPTさんによる)

  • 外部クロックが PLL の入力仕様範囲を超えないようにする
  • PIC32MK の場合、PLL入力は概ね 4〜8MHz 推奨
  • 外部48MHzのままでは PLL に入力できない → 分周して 8MHz 以下にする必要あり

例: 16MHz 外部クロックを DIV_2 → PLL 入力 8MHz

→ MUL_15 → 120MHz

→ DIV_1 → SYSCLK = 120MHz

このChatGPTさんの注意点にある「PIC32MKの場合はPLL入力は概ね 4〜8MHz 推奨」とのことだが、そのような情報はデータシートには明記されていないようなのだ。

で、ワテの場合は秋月電子で買った48MHzのMEMS発振子を半田付けして外部クロックとして使っている。

外部クロック48MHzの場合、以下のようにしたら上手く行った。

#pragma config FPLLIDIV = DIV_6  // PLL入力分周比:入力クロックを6で割る(8MHz)
#pragma config FPLLMULT = MUL_30  // PLL逓倍比:PLLで入力クロックを30倍する(240MHz)
#pragma config FPLLODIV = DIV_2  // PLL出力分周比:PLL出力を2で割ってSYSCLKにする(120Mhz)

ChatGPTさんが正しいならば、48MHz ÷ DIV_6 で得られる8MHzはPLL入力周波数としては推奨範囲(4〜8MHz)のギリギリ上限だ。DIV_8もあるのでそれを使えば6MHzを得られる。なおDIV_10以上は定義されていない。

当初は右も左も分からない状態でこれらの実験をやりながら、システムクロックをPICのピンに出力してオシロで観察するなどの作業をやっていた。最初から正常にLEDチカチカする訳もないし。

そんなこんなで泥沼状態になっていたのだが、上記のDIV_6、MUL_30、DIV_2やこれら以外の色んな組み合わせで実験していたら、最終的には上記値で無事に120MHz安定動作させる事が出来た。

なお、外部クロック48MHzをPLL入力分周で1/6の8MHzに落として、それをPLL逓倍比MUL_40で320MHzにしてからDIV_2して得られる160MHzで動作するか試してみたら、これも恐らく正常に動作しているようなのだが本当なのかな?

PIC32MK1024GPK064の最高周波数120MHzを超えているのだが。

まあとにかく内部クロックや外部クロックのどちらの場合でもPIC32MK1024GPK064でLEDチカチカに成功した。かつ、PLLを組み合わせて各種周波数での動作も出来るようになったのだ。

ここまで来るのに週末など延べ十数時間試行錯誤した。

下写真はLチカ実験の様子を示す。

写真 PIC32MK1024GPK064でLチカ実験の様子(PCBWay発注基板)

下動画ではLEDチカチカに成功した様子を撮影したものだ。

動画 PIC32MK1024GPK064でLEDチカチカに成功した様子を撮影(音声無し)

と言うことで、どうにか自力で(でも本当はChatGPTさんにほぼ100%頼りながら)、無事にLEDチカチカに成功したのだ。

まとめ

ワレコ
ワレコ

PICマイコン初心者のワテであるが、行き成り高性能な32ビットPICに挑戦して上手く行か不安が有ったが、実際にやってみるとどうにかなるもんだなあと再確認出来た。

当記事ではPIC32MK1024GPK064と言う32ビットMIPS RISCアーキテクチャ採用の高性能マイコンを使って、LEDチカチカ実験が無事に完了するまでの作業を紹介した。

まず初めにやったのがHarmonyと言う便利なツールを使う手法だ。Harmonyはワテの理解ではMPLAB X IDEに組み込まれているMCC(MPLAB Code Configurator)の一部であり、Harmonyを使うとPICマイコンに対する各種のポート設定とかレジスタ設定などをGUIを使いながら出来るのだ。

もちろんHarmonyはそれ以外にも色んな機能が有りそうなのだが、今回ワテが覚えたのはポート設定くらいだ。

Harmonyを使ったら、簡単にLEDチカチカに成功した。

ところがDebug実行するとmain関数にすら到着しない問題が発生したが、その原因は結局未解決だが、新規プロジェクトでやり直したら、再現性は無くDebug実行も全く問題なく動いた。

次にHarmonyを使わない方式でもLEDチカチカに成功した。

この時点までは内部クロックでPICを動作させている。

そこで内部クロックや外部クロックの使い方や、あるいはPLLを組み合わせる手法を調査した。

クロックに関しては、設定した周波数でPICが動作しているのかどうかを見極めるのが難しい。

そこでワテの場合は、特定のピンにシステムクロック(SYSCLK)を出力してオシロスコープで観察する手法で発振周波数を確認しながらやった。

当初は泥沼状態で訳わからなくなったのだが、色んな組み合わせを試しているうちに、コツを掴むことが出来て、最終的には内部クロック8MHzをPLLで120MHzまで上げて動作させることに成功した。

次に外部クロックに関しても、48MHz MEMS発振子で発生させた48MHzを分周や逓倍を行い80MHz、100MHz、120MHz、160MHzなどの周波数で安定動作させることが出来た。160MHzに関しては眉唾物かも知れないが、ワテの直感では確かに160MHzで動作しているように思う。

この件は引き続き調査したい。

今後の予定としては、SPI制御式の液晶ディスプレイに文字や絵柄を表示させる実験を予定している。

ChatGPTさんに相談したところ、液晶ディスプレイに文字や絵柄を表示するならLegato Graphics Composerライブラリとか言うのがHarmonyの中にあるとの事だ。

でもワテとしてはHarmonyは使わずにやりたい。

それで暫く調査していたらLegato Graphics Composerライブラリはかなり高性能なライブラリのようで、文字表示だけでなく液晶ディスプレイ用にGUIを作成するような高性能ライブラリのようだ。

ワテの用途ではそんなに高性能なものは不要で、取り敢えず文字が出せれば良い。その条件で調査していたら、PIC32マイコン用の文字出力ライブラリの軽いやつはGithubなどに幾つかあるとの事だ。

なので、まずはそのライブラリの調査から始める予定だ。

(続く)

スポンサーリンク
コメント募集

この記事に関して何か質問とか補足など有りましたら、このページ下部にあるコメント欄からお知らせ下さい。

PIC
スポンサーリンク
シェアする
warekoをフォローする
スポンサーリンク

コメント