Test SPI with two 74HC595 shift registers

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
This commit is contained in:
2025-10-05 17:03:08 +02:00
parent 42a7a915a6
commit 07ef92ab3d

View File

@@ -1,30 +1,105 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright (c) 2024-2025 Matthias Blankertz <matthias@blankertz.org> // Copyright (c) 2024-2025 Matthias Blankertz <matthias@blankertz.org>
#include <stdbool.h>
#include <stm32f1xx.h> #include <stm32f1xx.h>
#include <stm32f1xx_ll_bus.h> #include <stm32f1xx_ll_bus.h>
#include <stm32f1xx_ll_gpio.h> #include <stm32f1xx_ll_gpio.h>
#include <stm32f1xx_ll_rcc.h>
#include <stm32f1xx_ll_spi.h>
#include <stm32f1xx_ll_system.h>
#include <stm32f1xx_ll_utils.h> #include <stm32f1xx_ll_utils.h>
static void HALClockConfig(void)
{
// Two wait states required for sysclk > 48 MHz
LL_FLASH_SetLatency(LL_FLASH_LATENCY_2);
while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) {
}
LL_RCC_HSE_Enable();
/* Wait till HSE is ready */
while (LL_RCC_HSE_IsReady() != 1) {
}
// HSE clock = 16 MHz, SysClk = 16 MHz / 2 * 9 = 72 MHz
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE_DIV_2, LL_RCC_PLL_MUL_9);
LL_RCC_PLL_Enable();
/* Wait till PLL is ready */
while (LL_RCC_PLL_IsReady() != 1) {
}
// AHB clock = SysClk = 72 MHz
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
// APB1 clock = AHB clock / 2 = 36 MHz
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
// APB2 clock = AHB clock = 72 MHz
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
/* Wait till System clock is ready */
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {
}
LL_Init1msTick(72000000);
LL_SetSystemCoreClock(72000000);
}
static void HALInit(void) static void HALInit(void)
{ {
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO | LL_APB2_GRP1_PERIPH_GPIOA); LL_FLASH_EnablePrefetch();
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO | LL_APB2_GRP1_PERIPH_GPIOA | LL_APB2_GRP1_PERIPH_SPI1);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
// No JTAG, only SWD // No JTAG, only SWD
LL_GPIO_AF_Remap_SWJ_NOJTAG(); LL_GPIO_AF_Remap_SWJ_NOJTAG();
HALClockConfig();
// LED is on PA8
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_8, LL_GPIO_MODE_OUTPUT); LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_8, LL_GPIO_MODE_OUTPUT);
LL_Init1msTick(8000000); // SPI1 on PA4 - CS, PA5 - SCK, PA7 - MOSI
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_4, LL_GPIO_MODE_OUTPUT);
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_5, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_7, LL_GPIO_MODE_ALTERNATE);
// APB2 clock = 72 MHz, SPI rate = 72 MHz / 4 = 18 MHz
LL_SPI_SetBaudRatePrescaler(SPI1, LL_SPI_BAUDRATEPRESCALER_DIV4);
// CPOL = CPHA = 0 is default
// Set 16 bit data width
LL_SPI_SetDataWidth(SPI1, LL_SPI_DATAWIDTH_16BIT);
// MSB transmitted first is default
LL_SPI_SetNSSMode(SPI1, LL_SPI_NSS_SOFT);
LL_SPI_SetMode(SPI1, LL_SPI_MODE_MASTER);
LL_SPI_Enable(SPI1);
}
static void spi_send(uint8_t data)
{
LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_4);
// LL_SPI_TransmitData8(SPI1, data);
LL_SPI_TransmitData16(SPI1, (((uint16_t)data) << 8) | data);
// Wait for xfer to start
while (!LL_SPI_IsActiveFlag_TXE(SPI1)) {
}
// Wait for xfer to end
while (LL_SPI_IsActiveFlag_BSY(SPI1)) {
}
LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_4);
} }
int main(void) int main(void)
{ {
HALInit(); HALInit();
bool spi_led_state = true;
while (1) { while (1) {
LL_GPIO_TogglePin(GPIOA, LL_GPIO_PIN_8); LL_GPIO_TogglePin(GPIOA, LL_GPIO_PIN_8);
spi_send(spi_led_state ? 0x1 : 0x0);
spi_led_state = !spi_led_state;
LL_mDelay(1000); LL_mDelay(1000);
} }
} }