2013-05-10 04:02 AM
I've been struggling to get the SPI working on my STM32F3 Discovery, even just to communicate with the onboard rate sensor or work in loop-back mode. I got hold of a scope today, and realised that there's no output on my SPI1 SCLK/MOSI pins (PA5, PA7) and I have no idea why.
I've followed the set up guidelines in the peripheral manual, and as far as I can see SPI has been configured right. Unless I've forgotten to configure something else, I have no idea what's going on. Unfortunately the firmware available for the board has no SPI example either, as far as I can see. My code is really simple too, I'm not even trying to use interrupts right now at all. At this point I'd even just like to see data on the MOSI pin. I'd be really grateful if someone could check out my code and tell me if I've missed something./* Includes ------------------------------------------------------------------*/
#include ''main.h''
/* variables ---------------------------------------------------------*/
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
/* function prototypes -----------------------------------------------*/
void
delay_us(
int
us);
void
SPI_GPIO_init(
void
);
void
SPI_cfg(
void
);
uint8_t SPI1_read8bit(uint8_t addr);
int
main(
void
)
{
// read | addr of status register
uint8_t test_data = 0x80 | 0x0F;
int
rxbuf = 0;
SPI_GPIO_init();
SPI_cfg();
while
(1){
// Assert /CS followed by delay
GPIO_ResetBits(GPIOE, GPIO_Pin_3);
delay_us(10);
// Send data byte
rxbuf = SPI1_read8bit(test_data);
// Deassert /CS after delay
delay_us(10);
GPIO_SetBits(GPIOE, GPIO_Pin_3);
delay_us(50);
// wait 50us
}
}
// very roughly a 1us delay
void
delay_us(
int
us){
int
i,k;
for
(k=0;k<us;k++){
for
(i=0; i<8; i++);
}
}
/* Set up GPIO for SPI */
void
SPI_GPIO_init(){
//Disable SPI
//SPI_I2S_DeInit(SPI1);
// Enable clock for SPI 1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
// Enable Clock for SPI GPIOA/E
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
// Configure GPIO Alternate function as SPI1
GPIO_PinAFConfig(GPIOA, GPIO_Pin_5, GPIO_AF_5);
// SPI1 SCLK
GPIO_PinAFConfig(GPIOA, GPIO_Pin_6, GPIO_AF_5);
// SPI1 MISO
GPIO_PinAFConfig(GPIOA, GPIO_Pin_7, GPIO_AF_5);
// SPI1 MOSI
// Set up SCLK, MISO and MOSI pins
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
// Set as AF mode
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// SCLK
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// MISO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// MOSI
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Set up CS pin
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// OType, Speed and PuPd are the same
GPIO_Init(GPIOE, &GPIO_InitStructure);
// Set CS high to begin
GPIO_SetBits(GPIOE, GPIO_Pin_3);
}
/* Set up SPI and related parameters */
void
SPI_cfg(){
// Configure SPI
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
/* Configure the RX FIFO Threshold */
SPI_RxFIFOThresholdConfig(SPI1, SPI_RxFIFOThreshold_QF);
// Enable SPI1
SPI_Cmd(SPI1, ENABLE);
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);
}
uint8_t SPI1_read8bit(uint8_t addr){
while
(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE == 0) );
// Wait for TX buffer to be not empty. ie data loaded
SPI_SendData8(SPI1, addr);
// Send data
while
(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE == 0) );
// Wait for TX buffer to be not empty. ie data loaded
return
SPI_ReceiveData8(SPI1);
// Return received data
}
#stm32f3-stm32-spi-spi1-config
2013-05-10 04:39 AM
GPIO_PinAFConfig
() uses PinSource not Pin parameters.
Duplicate Thread [DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Discovery/SPI%20loop-back%20test%20-%20STM32F3&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&TopicsView=https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/AllItems.aspx¤tviews=13]https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fSTM32Discovery%2fSPI%20loop%2dback%20test%20%2d%20STM32F3&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&TopicsView=https%3A%2F%2Fmy%2Est%2Ecom%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32Discovery%2FAllItems%2Easpx¤tviews=13
2013-05-10 04:50 AM
Ah, I knew I must have missed something stupid, thanks! Seems like a really strange firmware quirk to not just use pin parameters.
For anyone who finds this thread in future, I just had to change GPIO_PinAFConfig(GPIOA, GPIO_Pin_X, GPIO_AF_5); to GPIO_PinAFConfig(GPIOA, GPIO_PinSourceX, GPIO_AF_5);