STM32のSPIはプルアップ抵抗がないと機能せず、パフォーマンスも低下します


8

しばらくの間、STM32F103C8(Blue Pillボード)のSPI1が正しく機能するように努めています。ARMの学習を始めたばかりなので、データを74HC595シフトレジスタにシフトし、それをラッチして1バイトのLEDを点灯させようとしています。データを読み取っていないので、MOSI、SCK、SSのラインしかありません。

最初は何も出力されませんでしたが、オンラインの例を読んで、これらの最初の問題を修正して通信を開始することができました(GPIOAピンを正しく設定し、ソフトウェアSSを設定する必要がありました)。

現在の主な問題は、すべてのライン(MOSI、SCK、SS)にプルアップ抵抗を含めないと、マイクロコントローラーがラインに何も出力しないことです(スコープで確認)。これに加えて、プルアップ抵抗を追加した後、パルスの立ち上がり時間が非常に遅いため、あまりにも高い周波数を使用できません(10kΩのプルアップ抵抗を使用すると、約250 kHz SCKに制限され、スイッチング約330 MHzに約4 MHz)。私はブレッドボードで作業していますが、それでもAVRとより複雑な配線を使用しても、抵抗を追加せずに4 MHz SPIが問題なく動作し、波形はきれいでした。

これは、250 kHzクロックでバイト0b01110010を送信している2つの画像(スコープ画面のひどい状態の場合は申し訳ありません)です。上のトレースはSCKで、下のトレースはMOSIです。最初の画像は10kΩプルアップ抵抗で、2番目の画像は波形をより良くする330Ωプルアップ抵抗です(ただし、それらは必要ありません)。

何が起こっているのかを理解するための助けをいただければ幸いです。

10kΩプルアップ抵抗と250 kHzクロック

330Ωのプルアップ抵抗と250 kHzにより、波形が非常に良くなります

私のコードの関連部分は:

#define SS_LOW        GPIOA->BSRR |= 1 << 4 + 16;
#define SS_HIGH        GPIOA->BSRR |= 1 << 4;

// SPI GPIO configuration
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
GPIOA->CRL |= 0b0011 << 4 * 4;    // Set pin A4 as PP out 50mHz for SS
GPIOA->CRL |= 0b1011 << 5 * 4;    // Set pin A5 AltFunc PP out 50mHz for SCK
GPIOA->CRL |= 0b1011 << 7 * 4;    // Set pin A7 AltFunc PP out 50mHz for MOSI
SS_HIGH;

// SPI1 configuration
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;        // Enable SPI1 clock
SPI1->CR1 |= SPI_CR1_SSM;        // Software SS
SPI1->CR1 |= SPI_CR1_SSI;
SPI1->CR1 |= SPI_CR1_BR_0;        // Set prescaler
SPI1->CR1 |= SPI_CR1_BR_1;
SPI1->CR1 |= SPI_CR1_BR_2;
SPI1->CR1 |= SPI_CR1_MSTR;        // Master mode
SPI1->CR1 |= SPI_CR1_SPE;        // Enable SPI

// Transmit byte
SS_LOW;
SPI1->DR = 0b01110010;
while(!(SPI1->SR & SPI_SR_TXE));
while(SPI1->SR & SPI_SR_BSY);
SS_HIGH;

あなたのセットアップは何ですか?ワイヤーはどのように接続されていますか?カスタムボードまたはブレッドボードを使用していますか?
Tarick Welling、

ブレッドボードを使用しています。74hc595は3.3Vの青いピルボードから電力を供給されます(これは正確にはrevspace.nl/File:Bluepill.jpgです)。シフトレジスタとの間の配線は、MOSI、SCK、SSのみです。配線が正しいと確信しています。何度も確認しました(回答する前にもう一度確認しました)。
jjpprr

回答:


12

ビットを設定する前に、変更するピンの値をリセットする必要があります。

GPIOA_CRLのリセット値は0x4444 4444です。したがって、各ピンは0b0100で初期化されます。| = 0b0011を実行すると、最終的にオープンドレイン出力である0b0111になります。0b1011と同様に0b1111になり、これは代替機能のオープンドレインです。

だからあなたはこのようなことをする必要があります:

// Reset pin configuration
GPIOA->CRL &= ~(0b1111 << 4 * 4);  // Reset Pin A4
GPIOA->CRL &= ~(0b1111 << 5 * 4);  // Reset Pin A5
GPIOA->CRL &= ~(0b1111 << 7 * 4);  // Reset Pin A7
GPIOA->CRL |= 0b0011 << 4 * 4;  // Set pin A4 as PP out 50mHz for SS
GPIOA->CRL |= 0b1011 << 5 * 4;  // Set pin A5 AltFunc PP out 50mHz for SCK
GPIOA->CRL |= 0b1011 << 7 * 4;  // Set pin A7 AltFunc PP out 50mHz for MOSI

これでした!本当にありがとうございました。とてもシンプルなものになると思いました。データシートのGPIOA_CRLの最初の行を読んでいたはずですが、リセット値はすべてゼロであると思いました。それは今魅力を働かせます。
jjpprr

@jjpprrよく実現するのに少し時間がかかりました:-)助けてくれてうれしいです。F103でI²Cを使用する場合、ラフなライドの準備をしてください。恐ろしいことを覚えています。
アーセナル

:Oはそれを考慮に入れます。USARTを起動して実行すると、I2Cの順番になります。ヘッドアップをありがとう。
jjpprr

私の状態マシンをめちゃくちゃにする割り込みソースなしで私が得ていた割り込みで最も目立つもの。結局、I²C割り込みをまったく使用しない(ただし、送信の最後にDMA割り込みを使用する)アプローチを採用し、I²Cビットをポーリングして開始やその他の処理を行っただけですが、アプリケーションはI²Cが完了するまで待機する必要がありました。 、それで私はとにかく割り込みで時間を稼いでいませんでした。
アーセナル

これはF103または他のstm32チップのみでしたか?私の計画は、stm32 ICのコツをつかむためだけにそれを使用することでしたが、その後、小規模なプロジェクトではF091に、より要求の厳しいものにはF446に移動しました。
jjpprr
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.