没有上拉电阻,STM32上的SPI将无法工作,即使如此,其性能也很差


8

我一直在尝试使STM32F103C8(蓝色药丸板)上的SPI1 正常工作一段时间。在我刚刚开始学习ARM时,我只是在尝试将数据移至74HC595移位寄存器并对其进行锁存以点亮一个字节的LED。我没有回读任何数据,所以我只有MOSI,SCK和SS线路。

起初我什么都没有得到,但是阅读一些在线示例后,我可以解决这些第一个问题,以使通信正常进行(我需要正确设置GPIOA引脚并设置软件SS)。

现在的主要问题是,如果我在所有线路(MOSI,SCK和SS)上均未包括上拉电阻,则微控制器在任何线路上均不会输出任何内容(已通过示波器检查)。最重要的是,在添加上拉电阻之后,脉冲的上升时间非常慢,因此我不能使用太高的频率(对于10kΩ上拉电阻,我限于约250 kHz SCK,并且切换至330Ω(约4 MHz)。我正在试验板上,但是即使使用AVR和更杂乱的布线,我也可以得到一个4 MHz SPI,而无需添加任何电阻就可以正常工作,并且波形更清晰。

这是两张图片(抱歉,我的示波器屏幕处于极低状态),它们以250 kHz的时钟传输字节0b01110010。顶部轨迹为SCK,底部轨迹为MOSI。第一张图带有10kΩ上拉电阻,第二张图带有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;

你的设置是什么?您的电线如何连接?您正在使用定制板还是面包板?
塔里克·威灵

我正在使用面包板。74hc595由蓝色药丸板的3.3V电源供电(准确地说,这是一个:revspace.nl/File : Bluepill.jpg)。往返移位寄存器的唯一导线是MOSI,SCK和SS。我确信接线是正确的,我已经检查了很多次(在回答您之前,请再次确认)。
jjpprr

Answers:


12

在设置位之前,应重置要更改的引脚的值。

GPIOA_CRL的重置值为0x44444444。因此,每个引脚都用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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.