· 

ATmega328PのSPIをごりごり系で

ATmega328PのSPIをArduinoライブラリ使わずにやる。Arduinoライブラリはそりゃラクだけど、すべて自分でやり切りたい事情もあったりなかったり。まぁ興味だけってことで。

ATmega328Pのデータシートにコードがあるので、基本はそのままパクる。

たぶんIARコンパイラ用なので、その辺はうまいこと翻訳していく。

 

ちなみに、avr.jpさんのデータシートが日本語なので日本人にはやさしい。

今回は1MHzを目指します。データシートにはこうかいてある。

今回はInternal 8MHzで動作しているので、fOSC/8を選ぶ、そすと、SPI2X,SPR1,SPR0=1,0,1これらを設定するだけ。

(SPSRってステータスレジスタなのに設定を書かせるなんて、、、と文句を言ってはいけない。)

 

データシートのコードはポーリングで完了を待つ方式のようですが、欲張って(カッコつけて)割り込みでやろうと思います。なのでSPIE=1b。

 

レジスタだけ見ていたら何をトリガーにデータ送信が始まるんだろう、、、って感じましたが、

SPDRレジスタに値を書けば始まるんだぜって書いてある。それと、SS(CSN)はユーザがソフトで制御しろよって書いてある。自動でやるモードはないらしい。自動でやるモードはあまり使わないからそれはそれでいいけど。マイコンのデータシートって膨大な量があってあまり読まずに使用例とか見てデバイスを使うことってあるけど(本業の人は絶対やっちゃいかん)、こまかいところに大事なことが書いてあるなーって思う。まぁ大事なことしか書いてないので全部読むのが正解なんだろう(、本当は)。

 

ちょっと能書きにつかれてきたので、いつもの通り、いきなりこんな感じです。

#define PIN_CSN (0x04)
#define PIN_MOSI (0x08)
#define PIN_MISO (0x10)
#define PIN_SCK (0x20)

volatile uint8_t txCompleted;

ISR(SPI_STC_vect){
    txCompleted=1;
}

void SPI_MasterInit(){
    DDRB|=(PIN_MOSI|PIN_SCK);
    //DDRB&=~(PIN_MISO);/*MISO pin is set to input automatically when SPE bit is set*/
    SPCR=(_BV(SPIE)|_BV(SPE)|_BV(CPOL)|_BV(MSTR)|_BV(SPR0));
    SPSR|=(_BV(SPI2X));
}
void SPI_MasterDeInit(void){
    SPCR&=~(_BV(SPIE)|_BV(SPE));
}

uint8_t txdata[]={0x55,0x00,0xAA,0xFF};
uint8_t byte_pos;
void setup(void){
    DDRB|=PIN_CSN;
    PORTB|=PIN_CSN;
    byte_pos=0;
}

void loop(void){
    SPI_MasterInit();
    txCompleted=0;
    PORTB&=~(PIN_CSN);
    SPDR=txdata[byte_pos&0x03];
    while(txCompleted==0){
        //
    }
    PORTB|=(PIN_CSN);
    SPI_MasterDeInit();
    byte_pos++;
}

狙い通りにできています。ちょー簡単!ぜんぜんごりごり系じゃない。