2015年12月23日水曜日

SPIの速度を変更する

STM32F1のSPIはCR1のBRに設定する。これはStdPerphLibではSPI_Initのみで変更できる。ということで自前で関数を作る必要がある。
static uint16_t SPI_Baud = 0;

static void SPI_BaudLow(void) {
    SPI_Baud = SPI1->CR1 & 0x0038;

    SPI_Cmd(SPI1, DISABLE);
    SPI1->CR1 = (SPI1->CR1 & 0xFFC7) | 0x0038;
    SPI_Cmd(SPI1, ENABLE);
}

static void SPI_BaudHigh(void) {
    SPI_Cmd(SPI1, DISABLE);
    SPI1->CR1 = (SPI1->CR1 & 0xFFC7) | SPI_Baud;
    SPI_Cmd(SPI1, ENABLE);
}

SPI_BaudLowではSPIを最低の速度で駆動する。72MHzなら281.25kHzとなる。またSPI_Baudに速度をバックアップする。
SPI_BaudHighではバックアップされたボーレートをレジスタに書き戻す。これはSPI_Initで設定した値になる。またSPI_BaudLowを呼ばれていない場合はSPI_Baudには0が入っており、これは分周比2となる。

それとボーレートの設定は通信中に変更してはいけないらしいのでSPI_Cmdでペリフェラルを終了させている。
ちなみにSPI_Cmdの中ではCR1のSPEを変更するだけなので、本来のSPI停止方法ではない。STM32F1のリファレンスマニュアルによると、RXバッファに値が入るまで待つ→RXバッファを読む→TXバッファが空になるまで待つ→ビジー状態でなくなるまで待つ→SPIを無効にする、という手順を踏む必要がある。ただこの方法は結構手間なのと、そもそも通信中にSPIを停止させるための手段なので、非通信時に変更したいのでSPI_Cmdだけで問題ないと判断した。

SDカードをSPIで使用するには、初期化時には100-400kbaudにする必要があるらしい。とりあえず36MHzでも問題なく初期化できているが、どうせ初期化するには200msecほどかかるので280kbaudでも36Mbaudでも大して変わりはない。

0 件のコメント:

コメントを投稿