#include "stm32l0xx_hal.h"
#include <stdio.h>
#include <string.h>
UART_HandleTypeDef huart2;
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_USART2_UART_Init(void);
void Process_Command(char *cmd);
// Global buffers for command line processing
char rx_buffer[64];
uint8_t rx_index = 0;
uint8_t led_state = 0; // 0 = OFF, 1 = ON
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
char tx_buf[128];
sprintf(tx_buf, "\r\n=== STM32 HAL UART CLI Initialized ===\r\nType 'HELP' to see available commands.\r\n\r\n> ");
HAL_UART_Transmit(&huart2, (uint8_t*)tx_buf, strlen(tx_buf), HAL_MAX_DELAY);
uint8_t rx_char;
while (1)
{
// Receive 1 byte via polling mode (non-blocking style 10ms timeout)
if (HAL_UART_Receive(&huart2, &rx_char, 1, 10) == HAL_OK)
{
// Echo the typed character back to the terminal screen
HAL_UART_Transmit(&huart2, &rx_char, 1, HAL_MAX_DELAY);
// Check for Carriage Return or Line Feed (Enter key)
if (rx_char == '\r' || rx_char == '\n')
{
if (rx_index > 0)
{
rx_buffer[rx_index] = '\0'; // Null-terminate string
// Print newline before command response
HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n", 2, HAL_MAX_DELAY);
// Parse and run the input command string
Process_Command(rx_buffer);
// Reset buffer index for next command entry
rx_index = 0;
// Print command prompt line symbol
HAL_UART_Transmit(&huart2, (uint8_t*)"> ", 2, HAL_MAX_DELAY);
}
}
// Handle backspace safely
else if (rx_char == '\b' || rx_char == 127)
{
if (rx_index > 0) rx_index--;
}
// Collect valid characters into buffer safely
else if (rx_index < sizeof(rx_buffer) - 1)
{
rx_buffer[rx_index++] = rx_char;
}
}
}
}
// Parsing function matching specified assignment requirements
void Process_Command(char *cmd)
{
char reply[128];
// 1. LED ON Command
if (strcmp(cmd, "LED ON") == 0)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
led_state = 1;
sprintf(reply, "SUCCESS: Blue LED is turned ON.\r\n");
}
// 2. LED OFF Command
else if (strcmp(cmd, "LED OFF") == 0)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
led_state = 0;
sprintf(reply, "SUCCESS: Blue LED is turned OFF.\r\n");
}
// 3. STATUS Command
else if (strcmp(cmd, "STATUS") == 0)
{
if (led_state == 1) {
sprintf(reply, "STATUS: LED state is currently [ON].\r\n");
} else {
sprintf(reply, "STATUS: LED state is currently [OFF].\r\n");
}
}
// 4. HELP Command
else if (strcmp(cmd, "HELP") == 0)
{
sprintf(reply, "Available Commands:\r\n"
" LED ON -> Turn on the indicator LED\r\n"
" LED OFF -> Turn off the indicator LED\r\n"
" STATUS -> Query current hardware state\r\n"
" HELP -> View this command list\r\n");
}
// Error handling for unrecognized inputs
else
{
sprintf(reply, "ERROR: Command '%s' not recognized. Type 'HELP'.\r\n", cmd);
}
HAL_UART_Transmit(&huart2, (uint8_t*)reply, strlen(reply), HAL_MAX_DELAY);
}
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;
HAL_UART_Init(&huart2);
}
void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
// Setup PA0 for driving the external LED output
GPIO_InitStruct.Pin = GPIO_PIN_0;
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);
// Configure PA2 (TX) and PA15 (RX) for USART2 VCP routing channel lines
GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void SystemClock_Config(void) {}