#include <stdio.h>
// This line includes the standard input/output library, which provides functions like printf().
#include <stdint.h>
// This line includes the standard integer types library, which defines portable integer types like uint32_t.
#include <string.h>
// This line includes the string library, which provides functions for manipulating strings.
#include <stm32l0xx_hal.h>
// This line includes the HAL (Hardware Abstraction Layer) library for the STM32L0xx series of microcontrollers.
// The HAL provides a standardized interface for interacting with the microcontroller's peripherals.
#define PORT_A GPIOA
#define PORT_B GPIOB
// This line defines a macro named LED_PORT that represents the GPIO port to which the LED is connected (GPIOB).
#define GREEN_LED_PIN GPIO_PIN_5
// Define the GPIO pin connected to the green LED
#define YELLOW_LED_PIN GPIO_PIN_4
// Define the GPIO pin connected to the yellow LED
#define RED_LED_PIN GPIO_PIN_3
// Define the GPIO pin connected to the red LED
#define Push_Button_PIN GPIO_PIN_11
#define LED_PORT_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE
// This line defines a macro named LED_PORT_CLK_ENABLE that enables the clock for the GPIO port of the LED (GPIOB).
// __HAL_RCC_GPIOB_CLK_ENABLE is a HAL macro that enables the clock for GPIOB.
#define VCP_TX_Pin GPIO_PIN_2
// Define the GPIO pin connected to the Virtual COM Port TX pin
#define VCP_RX_Pin GPIO_PIN_15
// Define the GPIO pin connected to the Virtual COM Port RX pin
UART_HandleTypeDef huart2;
// This line declares a variable named huart2 of type UART_HandleTypeDef.
// This variable will be used to store the configuration and state of the USART2 peripheral.
void SystemClock_Config(void);
// This line declares a function named SystemClock_Config that configures the system clock.
static void MX_USART2_UART_Init(void);
// This line declares a function named MX_USART2_UART_Init that initializes the USART2 peripheral.
void osSystickHandler(void)
{
// 1 Hz blinking:
// if ((HAL_GetTick() % 500) == 0)
// {
// HAL_GPIO_TogglePin(GPIOB, GREEN_LED_PIN);
// HAL_GPIO_TogglePin(GPIOB, YELLOW_LED_PIN);
// HAL_GPIO_TogglePin(LED_PORT, RED_LED_PIN);
// }
}
// This is the systick interrupt handler, which is called every 1ms.
// It toggles the LED every 500ms, resulting in a 1Hz blinking frequency.
// HAL_GetTick() returns the number of milliseconds that have elapsed since the program started.
// HAL_GPIO_TogglePin() toggles the state of the specified GPIO pin.
void initGPIO()
{
GPIO_InitTypeDef GPIO_Config;
// Declare a GPIO_InitTypeDef struct to hold the configuration for the GPIO pin.
GPIO_Config.Mode = GPIO_MODE_OUTPUT_PP;
// Set the GPIO pin to output mode with push-pull configuration.
GPIO_Config.Pull = GPIO_NOPULL;
// Disable pull-up and pull-down resistors for the GPIO pin.
//GPIO_Config.Speed = GPIO_SPEED_FREQ_HIGH;
// Set the GPIO pin speed to high.
//LED_PORT_CLK_ENABLE();
// Enable the clock for the GPIO port (GPIOB).
GPIO_Config.Pin = GREEN_LED_PIN;
HAL_GPIO_Init(PORT_B, &GPIO_Config);
GPIO_Config.Pin = YELLOW_LED_PIN;
HAL_GPIO_Init(PORT_B, &GPIO_Config);
GPIO_Config.Pin = RED_LED_PIN;
HAL_GPIO_Init(PORT_B, &GPIO_Config);
// Initialize the GPIO pin for the LED.
GPIO_Config.Mode = GPIO_MODE_INPUT;
GPIO_Config.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(PORT_A, &GPIO_Config);
}
int main(void)
{
HAL_Init();
// This line initializes the HAL library.
SystemClock_Config();
// This line calls the SystemClock_Config function to configure the system clock.
initGPIO();
// This line calls the initGPIO function to initialize the GPIO pin.
MX_USART2_UART_Init();
// This line calls the MX_USART2_UART_Init function to initialize the USART2 peripheral.
int temp = 0;
printf("Hello, %s | %d!\n", "Welcome to EEE 175 / CPE 185 Part 2",temp);
while (1) // This line creates an infinite loop, which prevents the program from exiting.
{
if(HAL_GPIO_ReadPin(PORT_A, Push_Button_PIN)){
printf("Button pushed!\n");
HAL_GPIO_TogglePin(PORT_B, GREEN_LED_PIN);
HAL_GPIO_TogglePin(PORT_B, YELLOW_LED_PIN);
HAL_GPIO_TogglePin(PORT_B, RED_LED_PIN);
temp++;
}
//delay(1000);
//delay for 1 second
}
return 0;
// This line returns 0 to the operating system, indicating that the program executed successfully.
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
// Declare a RCC_OscInitTypeDef struct to hold the configuration for the oscillator.
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// Declare a RCC_ClkInitTypeDef struct to hold the configuration for the clock.
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
// Declare a RCC_PeriphCLKInitTypeDef struct to hold the configuration for the peripheral clock.
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
// Configure the voltage scaling for the power regulator.
/** Initializes the RCC Oscillators according to the specified parameters
in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
// Set the oscillator type to HSI (High-Speed Internal).
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
// Enable the HSI oscillator.
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
// Set the HSI calibration value to the default value.
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
// Enable the PLL (Phase-Locked Loop).
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
// Set the PLL source to HSI.
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
// Set the PLL multiplication factor to 4.
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
// Set the PLL division factor to 2.
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
// If the oscillator configuration fails, call the Error_Handler function.
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
// Set the clock type to HCLK, SYSCLK, PCLK1, and PCLK2.
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
// Set the system clock source to PLLCLK.
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
// Set the AHB clock divider to 1.
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
// Set the APB1 clock divider to 1.
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
// Set the APB2 clock divider to 1.
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
// If the clock configuration fails, call the Error_Handler function.
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
// Select USART2 peripheral clock
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
// Select PCLK1 as USART2 clock source
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
// If the peripheral clock configuration fails, call the Error_Handler function.
Error_Handler();
}
}
/**
@brief USART2 Initialization Function
@param None
@retval None
*/
static void MX_USART2_UART_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA15 ------> USART2_RX
*/
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = VCP_TX_Pin | VCP_RX_Pin;
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);
// Enable the clock for GPIOA.
// Declare a GPIO_InitTypeDef struct to hold the configuration for the GPIO pin.
// Set the GPIO pin to alternate function mode with push-pull configuration.
// Disable pull-up and pull-down resistors for the GPIO pin.
// Set the GPIO pin speed to very high.
// Set the alternate function to USART2.
// Initialize the GPIO pin with the configuration.
huart2.Instance = USART2;
// Set the USART2 instance.
huart2.Init.BaudRate = 115200;
// Set the baud rate to 115200.
huart2.Init.WordLength = UART_WORDLENGTH_8B;
// Set the word length to 8 bits.
huart2.Init.StopBits = UART_STOPBITS_1;
// Set the number of stop bits to 1.
huart2.Init.Parity = UART_PARITY_NONE;
// Disable parity.
huart2.Init.Mode = UART_MODE_TX_RX;
// Set the mode to TX and RX.
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
// Disable hardware flow control.
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
// Set the oversampling to 16.
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
// Disable one-bit sampling.
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
// Disable advanced features.
if (HAL_UART_Init(&huart2) != HAL_OK)
{
// If the UART initialization fails, call the Error_Handler function.
Error_Handler();
}
__HAL_RCC_USART2_CLK_ENABLE();
// Enable the clock for USART2.
}
void Error_Handler(void)
{
/* User can add his own implementation to report the HAL error return state */
}
// This function is called when an error occurs.
// The user can add his own implementation to report the error.
// The following makes printf() write to USART2:
#define STDOUT_FILENO 1
// Define the standard output file descriptor.
#define STDERR_FILENO 2
// Define the standard error file descriptor.
int _write(int file, uint8_t *ptr, int len)
{
switch (file)
{
case STDOUT_FILENO:
HAL_UART_Transmit(&huart2, ptr, len, HAL_MAX_DELAY);
break;
// If the file descriptor is STDOUT_FILENO, transmit the data via USART2.
case STDERR_FILENO:
HAL_UART_Transmit(&huart2, ptr, len, HAL_MAX_DELAY);
break;
// If the file descriptor is STDERR_FILENO, transmit the data via USART2.
default:
return -1;
}
return len;
}
// This function is called by printf() to write data to a file.
// It redirects the standard output and standard error to the USART2 peripheral.
// HAL_UART_Transmit() transmits the data via USART2.