0
\$\begingroup\$

I am trying to connect blue pill board(master) to arduino nano(slave) over SPI and read what I have sent on serial monitor. However I haven't been able to get SPI working. I run a timer to generate an interrupt every second and send the character at interrupt. On the Arduino side I expect to see some stuff when SPI interrupt fires but I don't see anything. Here is how I configure my SPI peripheral on blue pill and my interrupt handler:

void cfgSPI1(void)
{
  //Initialize SPI peripheral
  RCC -> APB2ENR |= RCC_APB2ENR_SPI1EN;
  //Set baud rate to fclk/128
  SPI1 -> CR1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1;
  SPI1 -> CR1 |= SPI_CR1_SSM | SPI_CR1_SSI;
  //Set it as master
  SPI1 -> CR1 |= SPI_CR1_MSTR;
  SPI1 -> CR1 |= SPI_CR1_SPE;

  //Enable GPIOA peripheral clock and configure GPIO pins
  RCC -> APB2ENR |= RCC_APB2ENR_IOPAEN;
  //NSS
  GPIOA -> CRL |= GPIO_CRL_CNF4_1;
  //SCK
  GPIOA -> CRL |= GPIO_CRL_MODE5_1 | GPIO_CRL_MODE5_0;
  GPIOA -> CRL |= GPIO_CRL_CNF5_1;
  //MISO
  GPIOA -> CRL |= GPIO_CRL_MODE6_1 | GPIO_CRL_MODE6_0;
  GPIOA -> CRL |= GPIO_CRL_CNF6_1;
  //MOSI
  GPIOA -> CRL |= GPIO_CRL_MODE7_1 | GPIO_CRL_MODE7_0;
  GPIOA -> CRL |= GPIO_CRL_CNF7_1;
}

void TIM2_IRQHandler(void)
{
    TIM2->SR &= ~(TIM_SR_UIF);
    //Set slave select to low
    GPIOA -> ODR &= GPIO_ODR_ODR4;
    //Transfer 1 over SPI
    SPI1 -> DR |= 1;
    //Wait until transfer is completed
    while (!(SPI1->SR & (SPI_SR_TXE)));
    // Wait until receive complete
    while (!(SPI1->SR & (SPI_SR_RXNE)));
    // Wait until SPI is not busy anymore
    while (SPI1->SR & (SPI_SR_BSY));
    int i = SPI1 -> DR;
    GPIOA -> ODR |= GPIO_ODR_ODR4;
    // Toggle the LED output pin.
    GPIOC->ODR ^= GPIO_ODR_ODR13 ;
}

And this is the code on arduino side:

#include "Arduino.h"

ISR(SPI_STC_vect)
{
    uint8_t data_byte = SPDR;
    Serial.print(data_byte);
    Serial.print("test")
}

void setup()
{
    Serial.begin(9600);
    // Set MISO pin as output
    pinMode(MISO, OUTPUT);
    // Turn on SPI in slave mode
    SPCR |= (1 << SPE);
    // Turn on interrupt
    interrupts();
    SPCR |= (1 << SPIE);
}

void loop()
{
}
\$\endgroup\$
  • \$\begingroup\$ I'm too lazy to look -- but isn't there a global SPI enable bit in the STM32F103? IIRC for any stateful peripherals (just about everything except GPIO) you need to enable the clock to the peripheral, and then you need to tell the peripheral itself to please turn on. \$\endgroup\$ – TimWescott Jan 18 at 0:35
  • \$\begingroup\$ Well I think I figured out the problem(s). I did enable SPI clock and did enable SPI as a peripheral. Apperently you also have to enable alternate function GPIO clock. But my main issue was not these but the fact that my arduino nano did not accept 3.3V as logic high. Now that I put some comparators to shift them up to 5V I will test it again. \$\endgroup\$ – bobku123 Jan 19 at 15:03
  • \$\begingroup\$ Yay! The more complicated the set of peripherals, the more likely it is there's one @#$% bit that you haven't set. If you're using actual comparators, i.e. LM393's or something, you might want to consider using some plain old 74HCT buffers -- HCT logic was designed for TTL input and CMOS output, but work so well for 3.3V to 5V translators that no one ever bothered to make a line of logic specifically for that task. \$\endgroup\$ – TimWescott Jan 19 at 17:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.