/* main.c */
#include "stm32l0xx_hal.h"
#include <string.h>
/* Handles générés par CubeMX */
SPI_HandleTypeDef hspi1;
UART_HandleTypeDef huart2;
/* --- Broches pour 74HC165 bit-banging --- */
#define SPI1_SS_Port GPIOA
#define SPI1_SS_Pin GPIO_PIN_4 // SH/LD (parallel-load)
#define CLK_GPIO_Port GPIOA
#define CLK_Pin GPIO_PIN_5 // SCK
#define DATA_GPIO_Port GPIOA
#define DATA_Pin GPIO_PIN_6 // QH final
#define NB_165 2
#define PULSE_COUNT 200 // ajustez pour obtenir environ 10 µs
/* Prototypes */
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
static void MX_USART2_UART_Init(void);
void SoftDelay(void);
uint8_t ReadOne165(void);
uint32_t ReadAll165(void);
void PrintChanges(uint32_t newS, uint32_t oldS);
static uint32_t oldState = 0;
/* -------------------------------------------------- */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
MX_USART2_UART_Init();
HAL_UART_Transmit(&huart2,
(uint8_t*)"\r\n--- Nucleo-L031K6 : 2×74HC165 ---\r\n",
34, HAL_MAX_DELAY);
while (1) {
uint32_t state = ReadAll165();
PrintChanges(state, oldState);
oldState = state;
HAL_Delay(25);
}
}
/* Boucle pour quelques µs approximatifs */
void SoftDelay(void)
{
for (volatile int i = 0; i < PULSE_COUNT; i++);
}
/* Lit 8 bits d’un 74HC165 */
uint8_t ReadOne165(void)
{
uint8_t val = 0;
for (int i = 7; i >= 0; i--) {
if (HAL_GPIO_ReadPin(DATA_GPIO_Port, DATA_Pin) == GPIO_PIN_SET)
val |= (1 << i);
HAL_GPIO_WritePin(CLK_GPIO_Port, CLK_Pin, GPIO_PIN_SET);
SoftDelay();
HAL_GPIO_WritePin(CLK_GPIO_Port, CLK_Pin, GPIO_PIN_RESET);
SoftDelay();
}
return val;
}
/* Lit NB_165 registres en cascade et renvoie un mot 16 bits */
uint32_t ReadAll165(void)
{
// Latch parallèle (SH/LD)
HAL_GPIO_WritePin(SPI1_SS_Port, SPI1_SS_Pin, GPIO_PIN_RESET);
SoftDelay();
HAL_GPIO_WritePin(SPI1_SS_Port, SPI1_SS_Pin, GPIO_PIN_SET);
uint32_t res = 0;
for (int shift = (NB_165 - 1) * 8; shift >= 0; shift -= 8) {
uint8_t b = ReadOne165();
res |= ((uint32_t)b << shift);
}
return res;
}
/* Affiche sur la console les switches qui ont changé */
void PrintChanges(uint32_t newS, uint32_t oldS)
{
char line[48];
for (int i = 0; i < NB_165 * 8; i++) {
uint32_t mask = 1u << i;
if ((newS & mask) != (oldS & mask)) {
int n = snprintf(line, sizeof(line),
"Switch %2d -> %s\r\n",
i,
(newS & mask) ? "UP ↑" : "DOWN ↓");
HAL_UART_Transmit(&huart2, (uint8_t*)line, n, HAL_MAX_DELAY);
}
}
}
/* -------------------------------------------------- */
static void MX_SPI1_Init(void)
{
__HAL_RCC_SPI1_CLK_ENABLE();
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT; // NSS software
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // /16 pour simulation lente
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
HAL_SPI_Init(&hspi1);
}
/* -------------------------------------------------- */
static void MX_USART2_UART_Init(void)
{
__HAL_RCC_USART2_CLK_ENABLE();
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart2);
}
/* -------------------------------------------------- */
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
// PA15 en sortie pour NSS
HAL_GPIO_WritePin(SPI1_SS_Port, SPI1_SS_Pin, GPIO_PIN_SET);
GPIO_InitStruct.Pin = SPI1_SS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(SPI1_SS_Port, &GPIO_InitStruct);
// SPI1 pins PA5=SCK, PA6=MISO, PA7=MOSI en AF
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// UART2 pins PA2=TX, PA3=RX en AF
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Alternate = GPIO_AF4_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/* -------------------------------------------------- */
void SystemClock_Config(void)
{
// HSE 8MHz -> PLL x2 -> SYSCLK=16MHz
RCC_OscInitTypeDef osc = {0};
RCC_ClkInitTypeDef clk = {0};
osc.OscillatorType = RCC_OSCILLATORTYPE_HSE;
osc.HSEState = RCC_HSE_ON;
osc.PLL.PLLState = RCC_PLL_ON;
osc.PLL.PLLSource = RCC_PLLSOURCE_HSE;
// osc.PLL.PLLMUL = RCC_PLL_MUL2;
// osc.PLL.PREDIV = RCC_PREDIV_DIV1;
HAL_RCC_OscConfig(&osc);
clk.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1;
clk.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
clk.AHBCLKDivider = RCC_SYSCLK_DIV1;
clk.APB1CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_0);
}
Loading
st-nucleo-l031k6
st-nucleo-l031k6