#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stm32l0xx_hal.h>
// led1 (red) -> D2 -> PA12
#define LED_RCAR_PORT GPIOA
#define LED_RCAR_PIN GPIO_PIN_12
// led2 (yellow) -> D12 -> PB4
#define LED_YCAR_PORT GPIOB
#define LED_YCAR_PIN GPIO_PIN_4
// led3 (limegreen)-> D11 -> PB5
#define LED_GCAR_PORT GPIOB
#define LED_GCAR_PIN GPIO_PIN_5
// led4 (GREEN) -> D8 -> PA8 (у вас PA11)
#define LED_GPED_PORT GPIOA
#define LED_GPED_PIN GPIO_PIN_11
// led5 (red) -> D9 -> PA9 (у вас PA8)
#define LED_RPED_PORT GPIOA
#define LED_RPED_PIN GPIO_PIN_8
// Пищалка -> A5 -> PA5 (у вас PA6)
#define BUZZ_PIN GPIO_PIN_6
#define BUZZ_PORT GPIOA
// Кнопка -> D4 -> PB7
#define BUT_PORT GPIOB
#define BUT_PIN GPIO_PIN_7
// Потенциометр -> A2 -> PA2 (у вас PA3)
#define POT_PORT GPIOA
#define POT_PIN GPIO_PIN_3
UART_HandleTypeDef huart2;
ADC_HandleTypeDef hadc;
void SystemClock_Config(void);
static void MX_USART2_UART_Init(void);
void initGPIO(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
// Сбрасываем светодиоды в 0
HAL_GPIO_WritePin(GPIOA, LED_RCAR_PIN | LED_RPED_PIN | LED_GPED_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, LED_YCAR_PIN | LED_GCAR_PIN, GPIO_PIN_RESET);
// Светодиоды на GPIOA
GPIO_InitStruct.Pin = LED_RCAR_PIN | LED_RPED_PIN | LED_GPED_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Светодиоды на GPIOB
GPIO_InitStruct.Pin = LED_YCAR_PIN | LED_GCAR_PIN;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// Пищалка — выход
GPIO_InitStruct.Pin = BUZZ_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(BUZZ_PORT, &GPIO_InitStruct);
// Кнопка PB7 — вход с pull-up
GPIO_InitStruct.Pin = BUT_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(BUT_PORT, &GPIO_InitStruct);
// Потенциометр — аналоговый вход
GPIO_InitStruct.Pin = POT_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(POT_PORT, &GPIO_InitStruct);
}
static void initADC(void)
{
__HAL_RCC_ADC1_CLK_ENABLE();
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc.Init.Resolution = ADC_RESOLUTION_10B;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc.Init.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
if (HAL_ADC_Init(&hadc) != HAL_OK) Error_Handler();
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) Error_Handler();
}
// Программный тон для пищалки
static void buzzTone(uint32_t freq_hz, uint32_t duration_ms)
{
if (freq_hz == 0) return;
uint32_t half_us = 500000UL / freq_hz;
uint32_t cycles = (duration_ms * 1000UL) / (half_us * 2UL);
for (uint32_t i = 0; i < cycles; i++)
{
HAL_GPIO_WritePin(BUZZ_PORT, BUZZ_PIN, GPIO_PIN_SET);
for (volatile uint32_t d = 0; d < half_us / 10; d++) { __NOP(); }
HAL_GPIO_WritePin(BUZZ_PORT, BUZZ_PIN, GPIO_PIN_RESET);
for (volatile uint32_t d = 0; d < half_us / 10; d++) { __NOP(); }
}
}
static volatile bool requestCross = false;
// Ожидание с опросом кнопки и антидребезгом
static void waitWithButton(uint32_t ms)
{
const uint16_t step = 20;
uint32_t t0 = HAL_GetTick();
while (HAL_GetTick() - t0 < ms)
{
if (HAL_GPIO_ReadPin(BUT_PORT, BUT_PIN) == GPIO_PIN_RESET)
{
HAL_Delay(20);
if (HAL_GPIO_ReadPin(BUT_PORT, BUT_PIN) == GPIO_PIN_RESET)
{
requestCross = true;
printf("BUTTON PRESSED -> requestCross = 1\r\n");
while (HAL_GPIO_ReadPin(BUT_PORT, BUT_PIN) == GPIO_PIN_RESET) { }
printf("BUTTON RELEASED\r\n");
}
}
HAL_Delay(step);
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_USART2_UART_Init();
initGPIO();
initADC();
while (1)
{
// Читаем потенциометр -> длительность пешеходной фазы 3000..10000 мс
HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
uint32_t pot = HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop(&hadc);
uint32_t cross_ms = 3000 + (pot * 7000) / 1023;
// 1. Машинам зелёный, пешеходам красный — 5 секунд с опросом кнопки
HAL_GPIO_WritePin(LED_RCAR_PORT, LED_RCAR_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_YCAR_PORT, LED_YCAR_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_GCAR_PORT, LED_GCAR_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_RPED_PORT, LED_RPED_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GPED_PORT, LED_GPED_PIN, GPIO_PIN_RESET);
waitWithButton(5000); // <-- вместо HAL_Delay(5000)
// 2. Машинам жёлтый — 1 секунда
HAL_GPIO_WritePin(LED_RCAR_PORT, LED_RCAR_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_YCAR_PORT, LED_YCAR_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GCAR_PORT, LED_GCAR_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_RPED_PORT, LED_RPED_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GPED_PORT, LED_GPED_PIN, GPIO_PIN_RESET);
HAL_Delay(1000);
// 3. Машинам красный, пешеходам зелёный
HAL_GPIO_WritePin(LED_RCAR_PORT, LED_RCAR_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_YCAR_PORT, LED_YCAR_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_GCAR_PORT, LED_GCAR_PIN, GPIO_PIN_RESET);
if (requestCross)
{
// Есть заявка — пешеходная фаза с пищалкой и миганием
HAL_GPIO_WritePin(LED_RPED_PORT, LED_RPED_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_GPED_PORT, LED_GPED_PIN, GPIO_PIN_SET);
uint32_t t0 = HAL_GetTick();
while (HAL_GetTick() - t0 < cross_ms)
{
uint32_t elapsed = HAL_GetTick() - t0;
uint32_t remain = (cross_ms > elapsed) ? (cross_ms - elapsed) : 0;
// Писк: каждые 500 мс — 120 мс тона ~1000 Гц
if ((elapsed % 500) < 120)
buzzTone(1000, 100);
// Последние 2 секунды — мигаем зелёным
if (remain <= 2000)
HAL_GPIO_WritePin(LED_GPED_PORT, LED_GPED_PIN,
((HAL_GetTick() / 200) % 2) ? GPIO_PIN_SET : GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(LED_GPED_PORT, LED_GPED_PIN, GPIO_PIN_SET);
HAL_Delay(20);
}
requestCross = false;
}
else
{
// Заявки нет — пешеходам красный, пауза 2 секунды
HAL_GPIO_WritePin(LED_RPED_PORT, LED_RPED_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GPED_PORT, LED_GPED_PIN, GPIO_PIN_RESET);
HAL_Delay(2000);
}
// 4. Пешеходам красный, машинам жёлтый — 1 секунда
HAL_GPIO_WritePin(LED_RCAR_PORT, LED_RCAR_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_YCAR_PORT, LED_YCAR_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GCAR_PORT, LED_GCAR_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_RPED_PORT, LED_RPED_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GPED_PORT, LED_GPED_PIN, GPIO_PIN_RESET);
HAL_Delay(1000);
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) Error_Handler();
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) Error_Handler();
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) Error_Handler();
}
static void MX_USART2_UART_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
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;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK) Error_Handler();
__HAL_RCC_USART2_CLK_ENABLE();
}
void Error_Handler(void)
{
}
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
int _write(int file, uint8_t *ptr, int len)
{
switch (file)
{
case STDOUT_FILENO:
case STDERR_FILENO:
HAL_UART_Transmit(&huart2, ptr, len, HAL_MAX_DELAY);
break;
default:
return -1;
}
return len;
}Loading
st-nucleo-l031k6
st-nucleo-l031k6