#include "stm32c0xx_hal.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
// Configuração do KEYPAD
#define ROWS (GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3)
#define COLS (GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7)
char read_keypad(void);//Lê o teclado matricial e retorna o caractere correspondente à tecla pressionada.
static void config_GPIOB(void);// Configura os PINOS DO KEYPAD
// Configuração do LCD
#define PINO_RS GPIO_PIN_0// Define o pino RS (Register Select) do LCD como GPIO_PIN_0.
#define PINO_RW GPIO_PIN_1// Define o pino RW (Read/Write) do LCD como GPIO_PIN_1.
#define PINO_E GPIO_PIN_2// Define o pino E (Enable) do LCD como GPIO_PIN_2.
#define DATA GPIOA// Define que os pinos de dados do LCD estão conectados à porta GPIOA.
#define CMD GPIOD// Define que os pinos de controle (RS, RW, E) estão conectados à porta GPIOD.
#define LCD_WIDTH 16 // Define a largura do LCD
int config_osc(); // Configuração do oscilador
int config_clk(); // Configuração do clock
void config_GPIOA(); // Pinos de dados LCD
void config_GPIOD(); // Pinos de controle LCD
void LCD_command(uint8_t cmd); // Função que comanda o LCD
void LCD_data(uint8_t data); // Função que envia dados para o LCD
void LCD_init(); // Função que inicializa o LCD
void LCD_goto_XY(uint8_t row, uint8_t col); //Posicionamento do cursor no LCD
int main(void)
{
HAL_Init();
config_GPIOB();
config_osc();
config_clk();
config_GPIOA();
config_GPIOD();
LCD_init();
while (1)
{
char key = read_keypad();
if (key != 0)
{
if (key == '1')
{
LCD_clear();
LCD_write_string("ARYELSON");
}
else if (key == '2')
{
LCD_clear();
LCD_write_string("GONCALVES");
} else if (key == 'A') {
LCD_clear();
LCD_write_string("ARYELSON GONCALVES");
}
else
{
LCD_clear();
LCD_write_string("Teclas validas: 1, 2 ou A");
}
}
}
}
/* INICIO DAS FUNÇÔES RESPONSÁVEIS PELO CONTROLE DO LCD */
int config_osc() {
// Struct para inicialização do Oscilador
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
//Chamada da Função de Configuração
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
return -1;
}
return 1;
}
int config_clk() {
// Struct para inicialização do Clock
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/*
Config Clock
[1] Ligando Clock do Sistema e do Barramento AHB
[2] High Speed Internal referenciando acima
[3] Sem divisão
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
//Chamada da Função de Configuração
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
return -1;
}
return 1;
}
void config_GPIOA() {
// Estrutura para configuração do GPIOA
GPIO_InitTypeDef GPIO_InitStructA = {0};
GPIO_InitStructA.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
GPIO_InitStructA.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructA.Pull = GPIO_NOPULL;
GPIO_InitStructA.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructA);
}
void config_GPIOD() {
// Estrutura para configuração do GPIOD
GPIO_InitTypeDef GPIO_InitStructD = {0};
GPIO_InitStructD.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2;
GPIO_InitStructD.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructD.Pull = GPIO_NOPULL;
GPIO_InitStructD.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStructD);
}
void LCD_command(uint8_t cmd) {
HAL_Delay(1);
// RS = 0 Seleciona o registrador de comando
HAL_GPIO_WritePin(CMD, PINO_RS, GPIO_PIN_RESET);
// RW = 0 para escrever
HAL_GPIO_WritePin(CMD, PINO_RW, GPIO_PIN_RESET);
//Reseta todas as portas de dados
HAL_GPIO_WritePin(DATA, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 |
GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7,
GPIO_PIN_RESET);
//Manda o comando binário para o LCD
HAL_GPIO_WritePin(DATA, cmd, GPIO_PIN_SET);
HAL_Delay(1); // Aguarda pelo menos 270ns
HAL_GPIO_WritePin(CMD, PINO_E, GPIO_PIN_SET); // E = 1
HAL_Delay(1); // Aguarda pelo menos 270ns
HAL_GPIO_WritePin(CMD, PINO_E, GPIO_PIN_RESET); // E = 0
HAL_Delay(2); // Aguarda pelo menos 270ns
}
void LCD_data(uint8_t data) {
HAL_Delay(1);
// RS = 1 Seleciona o registrador de dados
HAL_GPIO_WritePin(CMD, PINO_RS, GPIO_PIN_SET);
// RW = 0 para escrever
HAL_GPIO_WritePin(CMD, PINO_RW, GPIO_PIN_RESET);
//Reseta todas as portas de dados
HAL_GPIO_WritePin(DATA, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 |
GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7,
GPIO_PIN_RESET);
HAL_GPIO_WritePin(DATA, data, GPIO_PIN_SET); // Envia dados em ASCII
HAL_Delay(1); // Aguarda pelo menos 270ns
HAL_GPIO_WritePin(CMD, PINO_E, GPIO_PIN_SET); // E = 1
HAL_Delay(1); // Aguarda pelo menos 270ns
HAL_GPIO_WritePin(CMD, PINO_E, GPIO_PIN_RESET); // E = 0
HAL_Delay(2); // Aguarda pelo menos 270ns
}
void LCD_goto_XY(uint8_t row, uint8_t col) {
uint8_t pos;
if (row == 0) {
pos = 0x80 + col;
} else {
pos = 0xC0 + col;
}
LCD_command(pos);
}
void LCD_init() {
//DL=1 (uso de 8 bits); N=1(uso das duas linhas); F=0(tamanho da fonte)
LCD_command(0x38);
//D=1 (Ligar o display); C=0(Desligar o cursor); B=0(Desligar o blink)
LCD_command(0x0C);
// Clear no display
LCD_command(0x01);
HAL_Delay(2); // Espera 2ms para o comando de clear
// I/D=1(incremento de 1); S=0(Sem inversão)
LCD_command(0x06);
}
void LCD_clear(void) {
LCD_command(0x01); // Envia o comando para limpar o display
HAL_Delay(2); // Aguarda pelo menos 2 ms
}
void LCD_write_string(const char *str) {
uint8_t col = 0; // Inicializa a coluna atual
uint8_t row = 0; // Inicializa a linha atual
LCD_goto_XY(row, col); // Move o cursor para a linha 0, coluna 0
while (*str) {
if (col >= LCD_WIDTH) {
// Se a coluna exceder a largura, vá para a linha abaixo
col = 0; // Reinicia a coluna
row++; // Move para a próxima linha
if (row >= 2) {
// Se já estiver na última linha, interrompe
break;
}
LCD_goto_XY(row, col); // Move o cursor para a nova linha, coluna 0
}
LCD_data(*str++); // Envia o caractere atual e move para o próximo
col++; // Move para a próxima coluna
HAL_Delay(1); // Pode ajudar a garantir que o LCD tenha tempo suficiente para processar os dados
}
}
/* FINAL DAS FUNÇÔES RESPONSÁVEIS PELO CONTROLE DO LCD */
/* INICIO DAS FUNÇÔES RESPONSÁVEIS PELO CONTROLE DO KEYPAD */
char read_keypad(void)
{
// Define uma matriz que mapeia as teclas do teclado 4x4 para caracteres
char keys[4][4] = {{'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'}};
// Loop através de cada linha do teclado
for (int row = 0; row < 4; row++)
{
/* Configura todas as linhas como alta */
// Configura todos os pinos das linhas como alta para garantir que apenas a linha corrente seja verificada
HAL_GPIO_WritePin(GPIOB, ROWS, GPIO_PIN_SET);
/* Configura a linha atual como baixa */
// Configura o pino da linha corrente como baixa para ativar a linha e verificar suas colunas
HAL_GPIO_WritePin(GPIOB, (1 << row), GPIO_PIN_RESET);
// Loop através de cada coluna do teclado
for (int col = 0; col < 4; col++)
{
// Verifica se o pino da coluna corrente está baixo (indicando que uma tecla na linha e coluna atuais está pressionada)
if (HAL_GPIO_ReadPin(GPIOB, (1 << (col + 4))) == GPIO_PIN_RESET)
{
// Espera até que a tecla seja liberada (não pressionada mais)
while (HAL_GPIO_ReadPin(GPIOB, (1 << (col + 4))) == GPIO_PIN_RESET);
// Retorna o caractere correspondente à tecla pressionada
return keys[row][col];
}
}
}
// Retorna 0 se nenhuma tecla for detectada como pressionada
return 0;
}
static void config_GPIOB(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Habilita o clock para o GPIOB */
__HAL_RCC_GPIOB_CLK_ENABLE();
/* Configura os pinos PA0-PA3 como saídas para as linhas do teclado */
GPIO_InitStruct.Pin = ROWS;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Configura os pinos PA4-PA7 como entradas para as colunas do teclado */
GPIO_InitStruct.Pin = COLS;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* FINAL DAS FUNÇÔES RESPONSÁVEIS PELO CONTROLE DO KEYPAD */