2017-06-09 02:23 AM
Hello,
I have a
weird
behavior with STM32F091RCT6 SPI Peripheral on Nucleo Evaluation Board.I want to interface with a 25LC640 SPI eeprom with 8 bits data mode
When i want to send a byte, i see On Oscilloscope 16 clocks pulse instead of 8 !!
I have tested several setting, i have the good number of pulses for 9 bits data size and more .
Context :
STM32F091RCT6
HAL library 1.6
Keil IDE & compiler : 5.06
SPI2 Peripheral on Port B Pin 13,14,15 Master Mode without NSS pin
SPI setup like this :
void MX_SPI2_Init(void)
{hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER; hspi2.Init.Direction = SPI_DIRECTION_2LINES; hspi2.Init.DataSize = SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; hspi2.Init.NSS = SPI_NSS_SOFT; hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi2.Init.CRCPolynomial = 8; hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; if (HAL_SPI_Init(&hspi2) != HAL_OK) { Error_Handler(); }}
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_SPI_ENABLE(spiHandle); /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO PB15 ------> SPI2_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF0_SPI2; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);Sending function :
static uint8_t eep_SpiSendByte (uint8_t data)
{while (( EE_SPI->SR & SPI_SR_TXE_Msk) == RESET); // Wait for empty transmit buffer
EE_SPI->DR = data;while (( EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET); // Wait for received buffer with new data
return (uint8_t)EE_SPI->DR;}
Thanks
#stm32f091-spi-spi_datasize_8bit #hal-v1.6Solved! Go to Solution.
2017-06-16 04:47 AM
while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)
You want to put a semicolon ; or an empty compound statement {} after this statement.
JW
2017-06-09 02:33 AM
*(volatile uint8_t*)&EE_SPI->DR = data;
2017-06-09 02:45 AM
Or perhaps this:
while (( EE_SPI->SR & SPI_SR_TXE_Msk) == RESET); // Wait for empty transmit buffer
The TXE flag set does not mean the send finished, only the send data are moved to the hardware send reg.
I fell into this trap some time ago ...
2017-06-09 03:08 AM
@ Avatar,
tanks for your suggestion, but i have yet the datasize problem on the fisrt byte !
When I send read instruction to 25LC640, it is the first byte after starting execution of program !
2017-06-09 04:52 AM
Perhaps, but it's more likely it's the 'data packing' feature, see RM0090 'data packing' subchapter of the SPI chapter.
A recurring issue here ever since the 'enhanced' SPIs appeared, first with 'F0.
JW
2017-06-09 05:02 AM
I think the above is the correct answer.
2017-06-14 03:42 AM
2017-06-14 05:24 AM
@ Krall
Tanks for your reply :)
But i need to send one byte separately, and in 8 bits mode I have allways two bytes 16 pulses on Clock pin.
I can't use the data packing
Our driver work like this :
uint8_t eep_ReadByte (uint32_t adress)
{volatile uint8_t tmpRead; /* For Trace
EEP_CS_ENABLE;
delayUS(5); eep_SpiSendByte(0x03); /* Commande de lecture */#if (defined EEP_25LC010) || (defined EEP_25LC020)
eep_SpiSendByte((uint8_t)adress); /* Adresse à lire */#elif defined EEP_25LC040 #error 'code non ecrit' /* Autres instruction */#elif defined EEP_25LC160 || (defined EEP_25LC320) || (defined EEP_25LC640) || (defined EEP_25LC256) || (defined EEP_25LC512) eep_SpiSendByte((uint8_t) adress >> 8);eep_SpiSendByte((uint8_t) adress);
#endiftmpRead = eep_SpiReceiveByte();
TmpReadDebug = tmpRead ; // for trace delayUS(5); EEP_CS_DISABLE;return tmpRead;
}
I have several other functions to managed a 25LCxxx witch are based on the following function :
Complementary eep_SpiSendByte and eep_SpiReceivedByte.
I didn't use HAL library because its too heavy and too slow in small STM32 for our product. (only for valid chip initialisation).
The 25LCxx Frame is divided in three part
instruction 8 bits
Adress 16 bits
Data 8 bits and more if need more data.
how i can now when one byte or two nibbles are receveid in RxFifo ?
while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET); // Waiting Reception of Low Nibble
Or
while ((EE_SPI->SR & 0x0600) != 0x0400 ) // Waiting Two data In Fifo
2017-06-14 06:40 AM
But you don't have to use the 4 bit mode ! Have you tried the solution
Waclawek.Jan
gave you in the first reply ?He even explained why you have this behavior, i.e. the data packing feature.
With his solution you want have to do all that stuff you do...
2017-06-14 07:36 AM
You didn't read carefully my answer, or didn't understand it completely.
Your function to send a byte is
static uint8_t eep_SpiSendByte (uint8_t data){ while (( EE_SPI->SR & SPI_SR_TXE_Msk) == RESET);// Wait for empty transmit buffer EE_SPI->DR = data; while (( EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET);// Wait for received buffer with new data return (uint8_t)EE_SPI->DR;}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
And
told you that you should in fact write it like thisstatic uint8_t eep_SpiSendByte (uint8_t data){ while (( EE_SPI->SR & SPI_SR_TXE_Msk) == RESET);// Wait for empty transmit buffer *(volatile uint8_t*)&EE_SPI->DR = data; while (( EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET);// Wait for received buffer with new data return (uint8_t)EE_SPI->DR;}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
The only difference is at line 4, it will force an 8-bit access to the data register of the SPI peripheral and it will send only 8 bits. No need to change to 4 bits mode at all. Try it and you will see by yourself.
Edit: why is this being moderated ? Syntax highlighter ?