AVRのSPIモジュール / MISOでとにかく何かを受けてみる / 熱電対 & MAX31855

pp.339ff.
SPIで何かを読み出してみる / K型熱電対とMAX31855 (5V版) / MAX31855内部で線形変換した温度を読む -」で使った温度センサーから熱接点温度をMISOで受けてみる。

MAX31855はセレクトされればクロックに同期して勝手にデータを送り返してくれるが、AVR側のシフトレジスタを空ける必要があるためAVR側でダミーデータの転送処理をする。MOSIの配線はないので実際は何も転送されない。
f:id:ti-nspire:20200110150054p:plain:w670
f:id:ti-nspire:20200110151014p:plain:h205 f:id:ti-nspire:20200110151122p:plain:h205
氷に塩をまぶして氷点下の温度を得た。

#include <avr/io.h>
#include <util/delay.h>
extern "C" {
    #include "USART.h"
}

int main(){
    DDRB  |= (1 << PB2); // PB2を!SS端子(OUT)として使う。
    PORTB |= (1 << PB2); // 最初はスレーブセレクトを解除しておく(Hを出力しておく)。
    DDRB  |= (1 << PB3); // PB3をMOSI端子(OUT)として使う。
    PORTB |= (1 << PB4); // PB4をMISO端子(IN)として使う。内部プルアップしておく。
    DDRB  |= (1 << PB5); // PB5をSCK端子(OUT)として使う。

    //SPCR &= ~(1 << CPOL | 1 << CPHA);           // mode(0,0)。デフォルト。CPOL、CPHAのCはclock。
    //SPCR &= ~(1 << CPOL); SPCR |=  (1 << CPHA); // mode(0,1)
    //SPCR |=  (1 << CPOL); SPCR &= ~(1 << CPHA); // mode(1,0)
    //SPCR |=  (1 << CPOL | 1 << CPHA);           // mode(1,1)

    //SPCR &= ~(1 << DORD); // MSBファーストで転送する。デフォルト。
    //SPCR |=  (1 << DORD); // LSBファーストで転送する。

    SPCR |= (1 << SPR1 | 1 << SPR0); // SPIのクロック周波数。ここでは8MHzを128分周した(62.5kHz)。SPRのRはRate。
    SPCR |= (1 << MSTR);             // AVRをマスターにする。
    SPCR |= (1 << SPE);              // SPIを有効化する。

    /***********************************/
    /* ためしにMISOで何かを受信してみる */
    /***********************************/
    initUSART();
    int16_t sute;
    float   temp;
    while(1){
        PORTB &= ~(1 << PB2);              // スレーブをセレクトして、

        SPDR = 0x00;                       // 1バイトぶんのダミーデータを転送して、
        loop_until_bit_is_set(SPSR, SPIF); // 転送処理の終わるのを待って、
        sute = SPDR << 8;                  // 受信した8ビットを16ビットの上位にはめ込んで、

        SPDR = 0x00;                       // また1バイトぶんのダミーデータを転送して、
        loop_until_bit_is_set(SPSR, SPIF); // 転送処理の終わるのを待って、
        sute |= SPDR;                      // 受信した8ビットを16ビットの下位にはめ込んで、

        PORTB |= (1 << PB2);               // スレーブセレクトを解除して、

        sute &= 0xfffc;                    // 下位2ビットはここでは無関係なので消して、
        temp = (float)sute / 16.0;         // 摂氏に換算して、
        printFloat(temp);printString("\n");// USART経由で表示する。

        _delay_ms(500);
    }
  
    return 0;
}

f:id:ti-nspire:20200110145831p:plain