#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stm32c0xx_hal.h>
//#include "menu_DWIN.c"
// ST Nucleo Green user LED (PA5)
#define LED_PORT GPIOA
#define LED_PIN GPIO_PIN_5
// Rows defines
#define ROWS_PORT GPIOB
#define ROWS_PINS 4
#define ROW_A_PIN GPIO_PIN_4
#define ROW_B_PIN GPIO_PIN_5
#define ROW_C_PIN GPIO_PIN_6
#define ROW_D_PIN GPIO_PIN_7
// Columns defines
#define COLS_PORT GPIOD
#define COLS_PINS 3
#define COL1_PIN GPIO_PIN_0
#define COL2_PIN GPIO_PIN_1
#define COL3_PIN GPIO_PIN_2
#define COL4_PIN GPIO_PIN_3
#define LED_PORT_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE
#define ROWS_PORT_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE
#define COLS_PORT_CLK_ENABLE __HAL_RCC_GPIOD_CLK_ENABLE
// Keypad Dimension
const uint8_t ROWS = ROWS_PINS; // Realy I need this? :))
const uint8_t COLS = COLS_PINS; // Realy I need this? :))
const uint8_t KeyPushedErrorTicksCount = 3; // contact error ticks counter (must be 2 .. 255)
const uint8_t KeypadScanPeriod = 10; // Period of Keypad Scaning (in miliseconds)
// Scan (char) codes array
const char ScanKeys[ROWS_PINS][COLS_PINS] = {
{ '1', '2', '3' },
{ '4', '5', '6' },
{ '7', '8', '9' },
{ '*', '0', '#' }
};
UART_HandleTypeDef huart2; //UART handler
volatile uint8_t counterCOLS = 0;
volatile uint8_t PinSCode = 0; // Pin Pad Scan Code
// Cycles counter for each key
volatile uint8_t CountKeys[ROWS_PINS][COLS_PINS] = {{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0}};
void SystemClock_Config(void);
static void MX_USART2_UART_Init(void);
void DeCodePushedRow (uint8_t PushedRow, uint8_t Col){
if (CountKeys[PushedRow][Col] < KeyPushedErrorTicksCount){
// We desided that this key is pushed enough
// printf("Pushed Pin on Col:%u, Row:%u, Value:%c\n", Col, PushedRow, ScanKeys[PushedRow][Col]);
CountKeys[PushedRow][Col]++;
};
}
void DeCodeReleasedRow (uint8_t ReleasedRow, uint8_t Col){
if (CountKeys[ReleasedRow][Col] >= KeyPushedErrorTicksCount){
// printf("Pushed '%c' (Col:%u, Row:%u)\n", ScanKeys[ReleasedRow][Col], Col+1, ReleasedRow+1);
MenuItemSwitch((uint8_t)(ScanKeys[ReleasedRow][Col]-'0'));
};
CountKeys[ReleasedRow][Col]=0;
}
void ReadRows (uint8_t ColIndex){
// Read ALL Rows and check for pushed or relased condition
if( HAL_GPIO_ReadPin(ROWS_PORT, ROW_A_PIN) == GPIO_PIN_SET ){
DeCodePushedRow(0,ColIndex);
} else DeCodeReleasedRow(0,ColIndex);
if( HAL_GPIO_ReadPin(ROWS_PORT, ROW_B_PIN) == GPIO_PIN_SET ){
DeCodePushedRow(1,ColIndex);
} else DeCodeReleasedRow(1,ColIndex);
if( HAL_GPIO_ReadPin(ROWS_PORT, ROW_C_PIN) == GPIO_PIN_SET ){
DeCodePushedRow(2,ColIndex);
} else DeCodeReleasedRow(2,ColIndex);
if( HAL_GPIO_ReadPin(ROWS_PORT, ROW_D_PIN) == GPIO_PIN_SET ){
DeCodePushedRow(3,ColIndex);
} else DeCodeReleasedRow(3,ColIndex);
}
void TimerCallAnalogue (void){
// GPIO_PinState ReadedState = GPIO_PIN_RESET;
HAL_GPIO_WritePin(COLS_PORT, COL1_PIN|COL2_PIN|COL3_PIN, GPIO_PIN_RESET); // Pins reset
switch (counterCOLS % COLS_PINS)
{
case 0:
HAL_GPIO_WritePin(COLS_PORT, COL1_PIN, GPIO_PIN_SET);
ReadRows(0);
break;
case 1:
HAL_GPIO_WritePin(COLS_PORT, COL2_PIN, GPIO_PIN_SET);
ReadRows(1);
break;
case 2:
HAL_GPIO_WritePin(COLS_PORT, COL3_PIN, GPIO_PIN_SET);
ReadRows(2);
break;
default:
printf("Wrong Counter pins! \n");
};
counterCOLS++;
}
void osSystickHandler(void)
{
if ((HAL_GetTick() % 1000) == 0) // 1 Hz blinking:
{
HAL_GPIO_TogglePin(LED_PORT, LED_PIN);
}
if ((HAL_GetTick() % KeypadScanPeriod) == 0)
{
TimerCallAnalogue(); //Аналог функции вызова таймера опроса клавиатуры.
}
}
void initGPIO()
{
GPIO_InitTypeDef GPIO_Config; // LED pin
GPIO_Config.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Config.Pull = GPIO_NOPULL;
GPIO_Config.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_Config.Pin = LED_PIN; // LED pin
HAL_GPIO_Init(LED_PORT, &GPIO_Config);
// __HAL_RCC_GPIOA_CLK_ENABLE(); //
LED_PORT_CLK_ENABLE();
GPIO_Config.Pin = COL1_PIN|COL2_PIN|COL3_PIN|COL4_PIN; // Columns pins
HAL_GPIO_Init(COLS_PORT, &GPIO_Config);
COLS_PORT_CLK_ENABLE(); // Columns PORT Clock enable
GPIO_Config.Mode = GPIO_MODE_INPUT;
GPIO_Config.Pull = GPIO_PULLDOWN;
GPIO_Config.Pin = ROW_A_PIN|ROW_B_PIN|ROW_C_PIN|ROW_D_PIN; // Rows pins
HAL_GPIO_Init(ROWS_PORT, &GPIO_Config);
ROWS_PORT_CLK_ENABLE(); // Rows PORT Clock enable
}
void KeyPad_Init(void){
uint8_t i,j;
// Array must be zero inited
for ( i=0 ; i++ ; i <= ROWS ){
for ( j=0 ; j++ ; j <= ROWS ){
CountKeys[i][j]=0;
}
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
initGPIO();
MX_USART2_UART_Init();
KeyPad_Init();
InitProcedure(); // from Menu_DWIN
printf("Hello, %s!\n", "Wokwi");
HAL_GPIO_TogglePin(LED_PORT, LED_PIN);
//HAL_GPIO_TogglePin(COLS_PORT, COL1_PIN);
while (1);
return 0;
}
// @brief System Clock Configuration
// @retval None
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
// @brief USART2 Initialization Function
// @param None
// @retval None
static void MX_USART2_UART_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
// PA2 ------> USART2_TX
// PA3 ------> USART2_RX
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_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.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
}
void Error_Handler(void)
{
/* User can add his own implementation to report the HAL error return state */
}
// The following makes printf() write to USART2:
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
int _write(int file, uint8_t *ptr, int len)
{
switch (file)
{
case STDOUT_FILENO:
HAL_UART_Transmit(&huart2, ptr, len, HAL_MAX_DELAY);
break;
case STDERR_FILENO:
HAL_UART_Transmit(&huart2, ptr, len, HAL_MAX_DELAY);
break;
default:
return -1;
}
return len;
}