2016年10月30日日曜日

I/OエキスパンダーのMCP23S17をNucleo F401RE(mbed)で使ってみる。 その2

MCP23S17からの割込みが効かないとプログラミングに制約が出るのでもう少し。

前回割り込みが効かなかったのはプログラミングのミスだったと思う。mbedのMCP23S17用のライブラリもhttps://developer.mbed.org/users/stjo2809/code/MCP23S17/に変更して割込みのテストをしてみた。こちらのLibraryはhttps://developer.mbed.org/users/romilly/code/MCP23S17/より低レベルというかレジスタ操作のラッパーという感じだ。

配線図


割込み線(MCP23S17 -> Nucreo)をPA_14に割り当て、ResetをPA_13に割り当てた。Resetは別に使わなくてもいい。

(追記:2016.11.09)

起動時にResetを掛けておかないとMCP23S17がうまく動作しないようです。

(/追記)

mbed repository:
https://developer.mbed.org/users/ryood/code/Nucleo_MCP23S17_Test/ Revision:3

/*
 * MCP23S17 Test
 *
 * MCP23S17 Library:
 * https://developer.mbed.org/users/stjo2809/code/MCP23S17/
 *
 * mbed:  rev 121
 * mbed-rtos: rev 117
 *
 * Created: 2016.10.28
 *
 */

#include "mbed.h"
#include "rtos.h"
#include "MCP23S17.h"

SPI Spi(PC_12, PC_11, PC_10); // SPI3: mosi, miso, sclk
//SPI Spi(PA_7, PA_6, PA_5); // SPI1:  mosi, miso, sclk

InterruptIn Mcp23s17Int(PA_14);

// MCP23S17(int hardwareaddress, SPI& spi, PinName nCs, PinName nReset);
MCP23S17 Mcp23s17(0x00, Spi, PD_2, PA_13);

void dataChanged()
{
    char data = Mcp23s17.intcapb();
    wait_us(1);
    Mcp23s17.gpioa(data);
}

int main()
{
    printf("\r\n\n*** MCP23S17 Test ***\r\n");

    // Reset MCP23S17
    Mcp23s17.reset();
    
    // PORTA output
    Mcp23s17.iodira(0x00);

    // PORTB input
    Mcp23s17.iodirb(0xFF);
    // PORTB pull-up
    Mcp23s17.gppub(0xFF);
    // PORTB invert polarity
    Mcp23s17.ipolb(0xFF);
    // PORTB enable on change interrupt
    Mcp23s17.gpintenb(0xFF);
    
    // Attach the callback function
    Mcp23s17Int.rise(&dataChanged);
    
    // LED Check
    for (int i = 0; i < 8; i++) {
        Mcp23s17.gpioa(1 << i);
        wait(0.1);
    }
    Mcp23s17.gpioa(0x00);
    
    while (true) {
    }
}

SPI信号


MOSI

ch1:sck ch2:mosi

拡大

2byte目と3byte目の間で一瞬MOSIがLになっている。SPI Mode 0の場合SCKの立ち上がりで評価するので問題ないが、高速な場合誤動作するかも?

MISO

ch1:sck ch2:miso

拡大


MISOが無出力のとき、Lレベルがふらふらしているので、Pull-Downしておいた方が良さそう。

MISO 10kΩでPull-down

MISO 3.3kΩでPull-down

3.3kΩの方が多少きれい。3.3V駆動でロジック・レベルがHの時3.3V/3.3kΩ=1mA消費することになる。

CS

ch1:sck ch2:cs
char data = Mcp23s17.intcapb();
Mcp23s17.gpioa(data);
と読み込み、書き込みを連続した状態で測定。(Read:3byte、Write:3byte)誤動作の可能性があるので間にウェイトを入れた方が良さそう。

Interrupt

ch1:sck ch2:intb

Active-highに設定しているのでPinの状態に変化があった時INTBがHになり、INTCAPBを読み込んだ時Lに戻るのでこれで良さそう。

メモ:


ベースマシンはNucleo2台使いをやめてI/Oエクスパンダ―でI/Oピンを増やす方向で。SPI通信の割込みが効かなくなる原因追及に疲れたし(^q^; 細かい実験用にNucleoを1台空けたい。

mbedのクラスが使えなくなるので、タクトスイッチ(トグル動作)、ロータリーエンコーダー、キーパッドの読み取りを自前で書かないとダメか(@@;