2018-03-16 04:10 AM
Hi
I am still learning on the STM32, and currently working on the Nucleo-64 (STM32L073RZT6) board. I am currently trying to get the SPI to work, I am simply trying to send a byte out so I can capture it on my logic analyser to confirm its sending, just to confirm I have it correct, then can move onto proer communication with it. I am using SPI1, with pins PA5-CLK PA6-MISO PA7-MOSI PA8-CS. I have an SPI memory chip connected to these pins, which I use on another processor so I have used it for many years. My code is below, on my logic analyser I see the chip select drop , but there is nothing else, all other pins are low. Im not worried about timing at the moment, just want to see the output first...
Mnay thanks
Scott
void SPI()
{
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;//enable GPIO port A clock
GPIOA->MODER &= ~GPIO_MODER_MODE8; //PA8 as output
GPIOA->MODER |= GPIO_MODER_MODE8_0;
GPIOA->BSRR |=GPIO_BSRR_BR_8;
GPIOA->BRR|=GPIO_BRR_BR_8; GPIOA->ODR |= GPIO_ODR_OD8; //cs highGPIOA->MODER &= ~GPIO_MODER_MODE5; //PA5 Alternate Function
GPIOA->MODER |= GPIO_MODER_MODE5_1;GPIOA->MODER &= ~GPIO_MODER_MODE6; //PA6 Alternate FunctionGPIOA->MODER |= GPIO_MODER_MODE6_1;GPIOA->MODER &= ~GPIO_MODER_MODE7; //PA7 Alternate FunctionGPIOA->MODER |= GPIO_MODER_MODE7_1;//set alternate function AF0
GPIOB->AFR[1] &= ~GPIO_AFRL_AFRL5; //PA5-CLK GPIOB->AFR[1] &= ~GPIO_AFRL_AFRL6; //PA6-MISO GPIOB->AFR[1] &= ~GPIO_AFRL_AFRL7; //PA7-MOSI RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //enable SPI1 clock RCC->APB2RSTR |= RCC_APB2RSTR_SPI1RST; //reset SPI1 RCC->APB2RSTR &= ~RCC_APB2RSTR_SPI1RST; //reset SPI1SPI1->CR1 &= ~SPI_CR1_SPE; //disable SPI
SPI1->CR1 &= ~SPI_CR1_RXONLY; //full duplex SPI1->CR1 &= ~SPI_CR1_BIDIMODE; //bidirectional SPI1->CR1 &= ~SPI_CR1_BIDIOE; //output disabled , received mode only SPI1->CR1 &= ~SPI_CR1_DFF; //8 bit Data frame format SPI1->CR1 &= ~SPI_CR1_LSBFIRST; //lsb first SPI1->CR1 &= ~SPI_CR1_CPHA; //1st edge SPI1->CR1 &= ~SPI_CR1_CPOL; //polarity low SPI1->CR1 &= ~SPI_CR1_BR; //baud rate to clk/2 SPI1->CR1 &= ~SPI_CR1_CRCEN;//crc disabled SPI1->CR2 &= ~SPI_CR2_FRF; //motorola mode SPI1->CR1 |= SPI_CR1_MSTR; //set as masterSPI1->CR1 |= SPI_CR1_SPE; //enable SPI
unsigned char Tmp[5];Tmp[0]=0x55;
SPI_Write(&Tmp[0],1); //send 1 byte only....
}
void SPI_Write(unsigned char *txBuffer,int Size)
{ unsigned char dummy; int i;GPIOA->ODR &= ~GPIO_ODR_OD8; //cs low
for(i=0;i<Size;i++)
{ //wait for txe while((SPI1->SR & SPI_SR_TXE) != SPI_SR_TXE); SPI1->DR = txBuffer[i]; //wait for rxne while((SPI1->SR & SPI_SR_RXNE) != SPI_SR_RXNE); dummy=SPI1->DR; }//wait for BSY flag cleared
while((SPI1->SR & SPI_SR_BSY) != SPI_SR_BSY); //<<sticks here//delay GPIOA->ODR |= GPIO_ODR_OD8; //cs high}2018-03-16 04:13 AM
//wait for BSY flag cleared
while((SPI1->SR & SPI_SR_BSY) != SPI_SR_BSY); //<<sticks hereThis is waiting for BSY flag set.
JW
2018-03-16 05:37 AM
I never noticed that, should have been ==
It gets stuck wating for the character, placed the //<<sticks here in the wrong place, sorry...
gets stuck here..
while((SPI1->SR & SPI_SR_RXNE) != SPI_SR_RXNE); <<<<
I only see the CS pin going low on my logic analyser, other pins dont change.
Scott
2018-03-16 05:55 AM
This seems to work for me.
unsigned char SPI_t::transfer_receive(unsigned short data) {
char RxSPI;
// clear old data from receiver
while ((hspi1.Instance->SR & SPI_FLAG_RXNE))
RxSPI = hspi1.Instance->DR;Clear_SPI1_nSS_Out();
while (!(hspi1.Instance->SR & SPI_FLAG_TXE))
;*((__IO uint8_t *)&hspi1.Instance->DR) = data; // force the SPI to transceive 8 bit
while (!(hspi1.Instance->SR & SPI_FLAG_TXE)) ; while ((hspi1.Instance->SR & SPI_FLAG_BSY)) ; RxSPI = hspi1.Instance->DR; take the byte. Set_SPI1_nSS_Out(); return RxSPI;}2018-03-16 07:32 AM
Hi TJ
I dont use the NSS pin, I use a seperate IO (PA8). I dont understand why nothing is coming out of the SPI pins, is there something in the setup of IO I am doing wrong? I tried your extra lines, i.e read byte before sending, and waiting for the TXE to become empty, but still the same.
Scott
2018-03-16 09:07 AM
Hi
I managed to fix the issue. I had to add:
SPI1->CR1 |= SPI_CR1_SSI;// manage nss software
SPI1->CR1 |= SPI_CR1_SSM; //software slave management enabled
As I use an IO pin for CS, I originally had them set to 0.
Thanks for all your info.
Scott