I’m running a master-slave communication with the boards: Nucleo STM32-F746ZG (master) and F103RB (slave).
Now, when I set spi.frecuency() below 1.125MHz, I actually get a frequency of ~ 0.56MHz, if I set it higher, I get ~ 1.12MHz. Why are there only two modes, why can’t I “tune” it to the frequency I want (0.8MHz)?
I looked at the spi.frequency implementation code and it looks like this:
void spi_frequency(spi_t *obj, int hz)
{
ssp_disable(obj);
uint32_t PCLK = SystemCoreClock;
int prescaler;
for (prescaler = 2; prescaler <= 254; prescaler += 2) {
int prescale_hz = PCLK / prescaler;
// calculate the divider
int divider = floor(((float)prescale_hz / (float)hz) + 0.5f);
// check we can support the divider
if (divider < 256) {
// prescaler
obj->spi->CPSR = prescaler;
// divider
obj->spi->CR0 &= ~(0xFFFF << 8);
obj->spi->CR0 |= (divider - 1) << 8;
ssp_enable(obj);
return;
}
}
error("Couldn't setup requested SPI frequency");
}
Can anyone help me understand the reason why the frequency in reality seems to shift between two different values when I set it below and above a certain threshold?
More details about my setup:
*The slave code uses the low level HAL functions, but the master uses the normal mbed spi API
*The two boards are connected through isoSPI interface boards on each side
Many thanks in advance to whoever can give me any input on this,
Julia
#if ((CLOCK_SOURCE) & USE_PLL_HSI) // <-- we are using USE_PLL_HSI
// [...]
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // 54 MHz
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // 108 MHz
// [...]
Clock
PCKL1
PCKL2
SPI
SPI_1, SPI_4, SPI_5, SPI_6
SPI_2, SPI_3
Base Clock
54 MHz
108 MHz
Scalar
PCKL1
PCKL2
2
27 MHz
54 MHz
4
13.5 MHz
27 MHz
8
6.75 MHz
13.5 MHz
16
3.38 MHz
6.75 MHz
32
1.69 MHz
3.38 MHz
64
843.75 kHz
1.69 MHz
128
421.88 kHz
843.75 kHz
256
210.94 kHz
421.88 kHz
Now if you want to have a SPI output frequency around 1.5 MHz, you will need to pass a value above 1.69 MHz and below 3.38 MHz when you call the SPI frequency method.
SPI mydevice(SPI_MOSI, SPI_MISO, SPI_SCK);
mydevice.frequency(1800000); // real value = 1.69 MHz
The frequency setting is limited by the hardware, the divider is 2 ^n. On other controllers, e. g. NXP LPC, it can be a decimal value and you get a finer graduation.
Some STM controllers have also the choice of a different clock source, but this is not handled by the default SPI class.