Reputation: 507
I've been stuck with this one for a while. I've followed a few examples online, but with no success. I cannot get it working with my STM32F4Discovery. I have an external chip (SX1272 from Semtech to be more specific) with whom I try to have an SPI communication. It is all kids games when doing it via Arduino, but no luck with ST product. I've used oscilloscope and it showed that the MOSI command is sent, but there is no MISO going out. (With Arduino it's good). Here's my code:
#include "main.h"
void init_SPI1(void){
GPIO_InitTypeDef GPIO_InitStruct;
SPI_InitTypeDef SPI_InitStruct;
// enable clock for used IO pins
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* configure pins used by SPI1
* PA5 = SCK
* PA6 = MISO
* PA7 = MOSI
*/
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// connect SPI1 pins to SPI alternate function
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
// enable clock for used IO pins
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
/* Configure the chip select pin
in this case we will use PE7 */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOE, &GPIO_InitStruct);
GPIO_SetBits(GPIOE, GPIO_Pin_7); // set PE7 high
// enable peripheral clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
/* configure SPI1 in Mode 0
* CPOL = 0 --> clock is low when idle
* CPHA = 0 --> data is sampled at the first edge
*/
SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
SPI_InitStruct.SPI_Mode = SPI_Mode_Master; // transmit in master mode, NSS pin has to be always high
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide
SPI_InitStruct.SPI_CPOL = SPI_CPOL_High; // clock is low when idle
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; // data sampled at first edge
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; // SPI frequency is APB2 frequency / 4
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; // data is transmitted MSB first
SPI_Init(SPI1, &SPI_InitStruct);
SPI_Cmd(SPI1, ENABLE); // enable SPI1
}
/* This funtion is used to transmit and receive data
* with SPI1
* data --> data to be transmitted
* returns received value
*/
uint8_t SPI1_read(uint8_t data){
GPIO_ResetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) low
SPI1->DR = data; // write data to be transmitted to the SPI data register
while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete
while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore
GPIO_SetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) high
uint8_t ret = SPI1->DR;
return ret; // return received data from SPI data register
}
void SPI1_write(uint8_t address, uint8_t data){
uint16_t comb = (address << 8) | data;
GPIO_ResetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) low
SPI1->DR = address; // write data to be transmitted to the SPI data register
while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete
//while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore
SPI1->DR = data; // write data to be transmitted to the SPI data register
while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete
while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore
GPIO_SetBits(GPIOE, GPIO_Pin_7); // set PE7 (CS) high
}
int main(void){
init_SPI1();
while(1){
SPI1_read(0x01);
}
}
All I get from MOSI is a random ~1.5V peak, which is out of sync.
Upvotes: 1
Views: 2533
Reputation: 2580
Have you tried using the ST configuration tool STM32Cube to generate the initialisation and communications interface code. I used it to generate the clock setup USART, I2C and SPI comms interfaces using DMA transfers in about an hour. It includes a pre-defined configuration for the F4 discovery board. All I had to do was clear the CS line when the transfer was loaded into the DMA and set it again in the transfer complete interrupt callback function.
Upvotes: 0
Reputation: 40407
/* configure pins used by SPI1
* PA5 = SCK
* PA6 = MISO
* PA7 = MOSI
*/
This suggests that your MISO (master in, slave out) signal is on PA6
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStruct);
But this configures PA6 as an output.
Configure PA6 as an input, and try again. If it still doesn't work try injecting a level there through a 1K or so resistor and see if you can get both the voltage to change on the scope and the received value to reflect that at all.
Upvotes: 1