2020-06-21 11:20 PM
Trying to receive data on MCU (L432KC) configured as SPI slave. I have tried using interrupt and DMA, but no luck.
I have set up the circuit like this : 1 MCU acts as master sending 1,2,3 every 500ms interval (I hooked up master lines to scope and the signals are generated correctly). On the other MCU configured as slave, I've connected a RGB led, which is supposed to react to 1,2,3.
Here's my code (interrupt handler commented)
#include "stm32l4xx.h" // Device header
//RGB led is common anode
#define RED_ON (GPIOB->ODR &=~(1<<1))
#define RED_OFF (GPIOB->ODR |=1<<1)
#define BLUE_ON (GPIOB->ODR &=~(1<<6))
#define BLUE_OFF (GPIOB->ODR |= 1<<6)
#define GREEN_ON (GPIOB->ODR &=~(1<<7))
#define GREEN_OFF (GPIOB->ODR |= 1<<7);
void SPI1_Slave_init(void);
void delayms(int count);
int SPI1_read(void);
void SPI1rx_DMA_init(int c);
int main()
{
int c=1;
SPI1_Slave_init();
SPI1rx_DMA_init(c);
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;
GPIOB->MODER &=~(3<<2 | 3<<12 | 3<<14);
GPIOB->MODER |= 1<<2 | 1<<12 | 1<<14;
GPIOB->ODR |= (1<<1 | 1<<6 | 1<<7);
//NVIC_EnableIRQ(SPI1_IRQn);
while(1)
{
DMA1_Channel2->CCR |= DMA_CCR_EN; //enable channel
while(!(DMA1->ISR & DMA_ISR_TCIF2)); //wait till channel 2 transfer is complete
switch(c)
{
case 1: GREEN_OFF;
BLUE_OFF;
RED_ON;
break;
case 2: RED_OFF;
BLUE_OFF;
GREEN_ON;
break;
case 3: RED_OFF;
GREEN_OFF;
BLUE_ON;
break;
}
DMA1->IFCR |= DMA_IFCR_CTCIF2;
DMA1_Channel2->CCR &=~ (DMA_CCR_EN); //disable channel
}
}
void SPI1_Slave_init(void)
{
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
GPIOA->MODER &=~(3<<8 | 3<<10 | 3<<12 | 3<<14);
GPIOA->MODER |= (2<<8 | 2<<10 | 2<<12 | 2<<14); //set as AF
GPIOA->AFR[0] &=~(0xF<<16 | 0XF<<20 | 0xF<<24 | 0xF<<28);
GPIOA->AFR[0] |= (5<<16 | 5<<20 | 5<<24 | 5<<28); //AF5
SPI1->CR1 &=~ (SPI_CR1_SPE); //disable SPI
SPI1->CR1 &=~ (SPI_CR1_SSI | SPI_CR1_SSM | SPI_CR1_MSTR); //slave
SPI1->CR1 |= (1<<3); // 1MHz baud rate
SPI1->CR2 &= ~(0xF<<8);
SPI1->CR2 |= 7<<8; //8 bit data
//SPI1->CR2 |= SPI_CR2_RXNEIE; //enable RXNE interrupt
SPI1->CR1 |= SPI_CR1_SPE;
}
void SPI1rx_DMA_init(int c)
{
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
//DMA channel config
DMA1_Channel2->CCR &=~(DMA_CCR_EN);
DMA1_Channel2->CCR &=~(DMA_CCR_DIR);
DMA1_Channel2->CNDTR = 1;
DMA1_Channel2->CPAR = (uint32_t)&SPI1->DR;
DMA1_Channel2->CMAR = (uint32_t)c;
DMA1_CSELR->CSELR |= 1<<4; //DMA1 Channel 2 mapped to request no 2 (SPI1_RX)
SPI1->CR2 |= SPI_CR2_RXDMAEN;
}
/*
void SPI1_IRQHandler(void)
{
uint8_t c;
if(SPI1->SR & SPI_SR_RXNE)
{
c = *(__IO uint8_t *)&SPI1->DR;
switch(c)
{
case 1: GREEN_OFF;
BLUE_OFF;
RED_ON;
break;
case 2: RED_OFF;
BLUE_OFF;
GREEN_ON;
break;
case 3: RED_OFF;
GREEN_OFF;
BLUE_ON;
break;
}
}
}
*/
I've tested the LED part of code separately, blinking R,G and B and it also works fine.
Again, tested interrupt and DMA separately, so ignore one while considering the other in the code. I've tested it with a normal receive subroutine too, but I had not much hope with it anyway.
Just failing to receive data on slave. What am I doing wrong?
EDIT : Here are the waveforms on scope. When disconnected from slave, the waveforms are perfect. However when I connect the master to slave, there is some noise and the SCL line has a amplitude of 900mV.
Solved! Go to Solution.
2020-06-22 11:54 AM
> I checked user manual to see if PA5 was connected to something and don't really see anything.
Hummm...
In a minimal program, try only setting PA5 as GPIO Input with pulldown, and measure.
JW
2020-06-22 12:26 PM
No, I use barebone gdb which is not the easiest thing to use; but Keil should be usable for it.
JW
2020-06-22 12:37 PM
> My slave in this program is a Nucleo L432KC.
> I checked user manual to see if PA5 was connected to something and don't really see anything.
Which user manual did you check?
JW