ガレスタさんのDIY日記

電子回路、Web、組み込み、自作エフェクターを語るblog

ZOOM MS50gのハードウエア構成を見てみる

僕のブログではこんなことやったりして普通の使い方と違う使い方をやっていますが・・・・・


gsmcustomeffects.hatenablog.com


今回も普通の使い方というより教材として使う的なニュアンスでみていこうと思います。

まず全体図

f:id:gsmcustomeffects:20170806152921j:plain

メイン基板と各種スイッチ基板やらがフレキシブルなやつでつながれてますね

ちなみにZFXとか書いてありますがTIのDSP(TMS320C6745)ですね。
f:id:gsmcustomeffects:20170806153024j:plain

スペックはこんなもん

f:id:gsmcustomeffects:20170806153202p:plain

次に裏面を見ていく

f:id:gsmcustomeffects:20170806153238j:plain

いくつかのICがのっている

拡大してく

f:id:gsmcustomeffects:20170806153307j:plain

ADCは現シーラスロジックのWM8782

スペックはこんなもん

f:id:gsmcustomeffects:20170806153442p:plain

DACはTIのPCM5101だが現在は新規設計に非推奨らしい・・・

f:id:gsmcustomeffects:20170806153632p:plain

その他RT9971AとかいうマルチCH電源とFIDELIXのシリアルメモリがついてる。

SDRAMはEtronTechの4M x 16 bit Synchronous DRAMがのってる。

まとめ

結構しっかりしてる・・・・・

というかこれだけのスペックで9000円ぐらいとかしゅごい

KiCadのないとりーびるどでビアが好きに打てるようになってた

こんな感じに打てる(例がくそすぎwww

f:id:gsmcustomeffects:20170727031803p:plain

メニューはここ

f:id:gsmcustomeffects:20170727031817p:plain

その他UIがモダンになってます

ぼちぼち

最近更新できてませんなんでかっていうとアニメ見てるのと本読んでるのでw

てなわけではじめてのギャル面白い

hajimete-no-gal.jp

Kinetis K64 ピン割り込み

今回は前回に引き続きなんですがGPIO関連ということでピン入力割り込みについてやって行きたいと思います。

Reference ManualのChapter11のPort Control and Interrupts (PORT)を参考資料としてつかうのでそれを用意してただいて作業をすると一段わかりやすくなっているかと思います。

ARM Cortex-M4|Kinetis K64 120 MHz 32-bit MCUs|NXP


ARMの割り込みの設定手順はだいたいこんな感じなので一個一個追って説明していく

  1. 割り込みを使いたいペリフェラル側で割り込みに関する部分を有効にする
  2. 対応する割り込みベクタ番号を調べてNVIC_SetPriorityというAPIで優先度を決定
  3. Enable_IRQというAPIで割り込みを有効
  4. 割り込みハンドラの記述

ペリフェラル側で割り込みに関する部分を有効にする

Pin Control RegisterのIRQCをセットしていく作業になる。
f:id:gsmcustomeffects:20170709010510p:plain

f:id:gsmcustomeffects:20170709011100p:plain

FRDMボードがこのようになっているのでフォーリング検出を選択する

f:id:gsmcustomeffects:20170709011523p:plain

ピン方向はInputに設定する。

f:id:gsmcustomeffects:20170709011837p:plain

PORT_SetPinInterruptConfigというAPIで割り込みの設定をします。

static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config)

なので

PORT_SetPinInterruptConfig(GPIOA, 4U, kPORT_InterruptFallingEdge);

第三引数はマクロ化されているので便利である。

NVIC_SetPriorityというAPIで優先度を決定

void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)というAPIを使って設定している。

NVIC_SetPriority(PORTA_IRQn, 4);

Enable_IRQというAPIで割り込みを有効

EnableIRQ(PORTA_IRQn);

割り込み優先度はとりあえず4にしとく

割り込みハンドラの記述

PORTA_IRQHandlerという名前で定義されているのでmainの上のほうで適当に定義してあげます。
WEAK定義なので上書きして使ってあげるということですね。

void PORTA_IRQHandler(void)
{
    /* Clear external interrupt flag. */
    GPIO_ClearPinsInterruptFlags(BOARD_SW_GPIO, 1U << BOARD_SW_GPIO_PIN);
    /* Change state of button. */
    g_ButtonPress = true;
}

GPIO_ClearPinsInterruptFlagsは割り込みのフラグ解除をしている。
f:id:gsmcustomeffects:20170709020636p:plain

ISFに1を書き込むとフラグ解除される。

実行とデバッグ

割り込みハンドラ内でブレークポイントを設定しボード上のボタンを押すとブレークするのが確認できる。
f:id:gsmcustomeffects:20170709213351p:plain

対応する割り込みベクタ番号について

これについてはMK64F12.hに記述されている。コードのアブストにはCMSIS Peripheral Access Layer for MK64F12とあるので一応CMSIS関連のファイルだと思う。

f:id:gsmcustomeffects:20170708235114p:plain

このように今回はPORTAを使いたいので59という番号をNVICのAPIに投げてやる必要がある。
んで毎回調べるのも面倒な場合はPORTAまで打って補完に頼るのもいいかもしれない

f:id:gsmcustomeffects:20170708235414p:plain

ソースコード

最後に参考までにソースコードを貼っていく。

#include "fsl_debug_console.h"
#include "fsl_port.h"
#include "fsl_gpio.h"
#include "fsl_common.h"
#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define BOARD_LED_GPIO BOARD_LED_RED_GPIO
#define BOARD_LED_GPIO_PIN BOARD_LED_RED_GPIO_PIN

#define BOARD_SW_GPIO BOARD_SW3_GPIO
#define BOARD_SW_PORT BOARD_SW3_PORT
#define BOARD_SW_GPIO_PIN BOARD_SW3_GPIO_PIN
#define BOARD_SW_IRQ BOARD_SW3_IRQ
#define BOARD_SW_NAME BOARD_SW3_NAME

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/
/* Whether the SW button is pressed */
volatile bool g_ButtonPress = false;

/*******************************************************************************
 * Code
 ******************************************************************************/
/*!
 * @brief Interrupt service fuction of switch.
 *
 * This function toggles the LED
 */
void PORTA_IRQHandler(void)
{
    /* Clear external interrupt flag. */
    GPIO_ClearPinsInterruptFlags(BOARD_SW_GPIO, 1U << BOARD_SW_GPIO_PIN);
    /* Change state of button. */
    g_ButtonPress = true;
}

/*!
 * @brief Main function
 */
int main(void)
{
    /* Define the init structure for the input switch pin */
    gpio_pin_config_t sw_config = {
        kGPIO_DigitalInput, 0,
    };

    /* Define the init structure for the output LED pin */
    gpio_pin_config_t led_config = {
        kGPIO_DigitalOutput, 0,
    };

    BOARD_InitPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();

    /* Print a note to terminal. */
    //PRINTF("\r\n GPIO Driver example\r\n");
    //PRINTF("\r\n Press %s to turn on/off a LED \r\n", BOARD_SW_NAME);

    /* Init input switch GPIO. */
    PORT_SetPinInterruptConfig(BOARD_SW3_PORT, 4U, kPORT_InterruptFallingEdge);
    NVIC_SetPriority(PORTA_IRQn, 4);
    EnableIRQ(PORTA_IRQn);
    GPIO_PinInit(BOARD_SW_GPIO, BOARD_SW_GPIO_PIN, &sw_config);

    /* Init output LED GPIO. */
    GPIO_PinInit(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, &led_config);

    while (1)
    {
        if (g_ButtonPress)
        {
            //PRINTF(" %s is pressed \r\n", BOARD_SW_NAME);
            /* Toggle LED. */
            GPIO_TogglePinsOutput(BOARD_LED_GPIO, 1U << BOARD_LED_GPIO_PIN);
            /* Reset state of button. */
            g_ButtonPress = false;
        }
    }
}

余談だけどこんな記事読まなくてもMCUXpressoの機能からSampleインポートでこいつ読めば動くので何も考えず行ける
f:id:gsmcustomeffects:20170709022029p:plain

ちなみにサンプルはマクロ使いまくっててわかりにくかったのでこうやって色々書いただけ・・・・・あと割り込み優先度を設定してない公式サンプル・・・・・

Kinetis K64 GPIOメモ

GPIOいじるときにすぐ忘れるのでメモしておこうとおもった。

KSDK V2を使った場合で説明する

流れとしては

  1. PORTにクロック供給
  2. PINMUXの設定(GPIOへ設定)
  3. ピン方向の設定(構造体の定義)
  4. ピン方向の設定(InitAPIのコール)
  5. ピン操作APIのコール

こうなる。
さっそく見ていこうと思う

クロック供給

static inline void CLOCK_EnableClock(clock_ip_name_t name)っていうAPIがそれに値します。

引数としてnameが渡されますがそれはマクロで定義されています。

f:id:gsmcustomeffects:20170706002952p:plain

なので使う際は以下のように記述します。

CLOCK_EnableClock(kCLOCK_PortB);

PINMUXについて

最近のマイコンでは定番ですがピンの機能設定をします。
だいたいのマイコンでは初期がGPIOなので問題ないですがこいつの場合見ての通りデフォがADCとかDisableとかになってるんで設定してあげます。

f:id:gsmcustomeffects:20170706003658p:plain

K64の評価ボードではRGBLEDがついているんですがREDを使いたいのでPORTBの22番目を設定してあげることになります。
f:id:gsmcustomeffects:20170706003937p:plain


実際にはstatic inline void PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux)というAPIでPINMUXを設定できます。

PORT_SetPinMux(PORTB, PIN22_IDX, kPORT_MuxAsGpio);

のように書くとピン機能の設定ができます。
第一引数と第二引数でPTB22を指定してます。

第三引数はALTファンクションなのでデータシート見て決めます

f:id:gsmcustomeffects:20170706004529p:plain

このようにALT1がそれにあたるのでマクロでもそのようになっています。

f:id:gsmcustomeffects:20170706004614p:plain

べたでやるならPin Control Resistorをセットしていく作業になります。

f:id:gsmcustomeffects:20170706005014p:plain

MUXフィールドに001をアサインする

f:id:gsmcustomeffects:20170706005133p:plain

ピン方向の設定(構造体の定義)

この作業についてはAPIリファレンスのGPIO項目にかかれています。
struct gpio_pin_config_tという構造体がそれにあたるんですがこれはリファレンスの説明が一番わかりやすくていいです

f:id:gsmcustomeffects:20170706005443p:plain

このようにOutputにしたい場合はkGpioDigitalOutputって定義してLogic部分は0でも1でもいいと思います。
尚構造体定義は以下のようになっています
f:id:gsmcustomeffects:20170706005739p:plain

ピン方向の設定(APIコール)

void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)っていうAPIをコールしてあげるだけです。

GPIO_PinInit(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN, &led_config);

こう書けばいいんですがもっとわかりやすく書けば

GPIO_PinInit(GPIOB, 22U, &led_config);

GPIOBがポインタ型で渡されてなくない?って思った方のために
f:id:gsmcustomeffects:20170706010141p:plain

第三引数は先ほど作った構造体を投げるだけです。

ここでいじってるレジスタはPORT DATA Direction Resistorです

f:id:gsmcustomeffects:20170706010437p:plain

中身を見るとINかOUTかで判断してPDDRを操作してるだけ。
f:id:gsmcustomeffects:20170706011253p:plain

ピン操作APIのコール

ここまで来たらあとは以下のどれかを呼ぶだけです

f:id:gsmcustomeffects:20170706010701p:plain

反転専用レジスタがあるのでこれでもLチカは行けるw

GPIOB->PTOR = 1u << 22U;

f:id:gsmcustomeffects:20170706011010p:plain

ソース

int main(void)
{
    /* Define the init structure for the output LED pin*/
    gpio_pin_config_t led_config = {
        kGPIO_DigitalOutput, 0,
    };

   //GPIO_Type GPIOB;

    /* Board pin, clock, debug console init */
    BOARD_InitPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();

    /* Print a note to terminal. */

    /* Init output LED GPIO. */
    GPIO_PinInit(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN, &led_config);

    while (1)
    {
        delay();
       // GPIO_TogglePinsOutput(BOARD_LED_RED_GPIO, 1u << BOARD_LED_RED_GPIO_PIN);
        GPIOB->PTOR = 1u << 22U;

    }
}

まとめ

KinetisマイコンのGPIOについて紹介した。
一応かなり噛み砕いたけどわかりにくかったらコメントしてくれれば!

自分用メモ Kinetisやる際によむとこ

SDK内のフォルダのDocの中のこれ

f:id:gsmcustomeffects:20170705025103p:plain

DriverExampleのReadme

リファレンスマニュアル

f:id:gsmcustomeffects:20170705025354p:plain

SDKのGettingStartおよびファイル構造解説

f:id:gsmcustomeffects:20170705025514p:plain

基本ここ読めばだいたいのコツはつかめる。
あとはInit系のAPIはマクロ化でウザったいので注意