Pular para o conteúdo principal

Laboratório 11

Documentação de Apoio para Atividade de Laboratório

A documentação desta atividade de laboratório é complementar a documentação principal da disciplina.

Utilize como base a descrição apresentada no Moodle da disciplina.

TarefaTemplateInícioFimConteúdo
LAB11TPL1108-Jun-202615-Jun-2026Introdução ao Display OLED SSD1306;

Conteúdo​

Code for OLED and LCD display using stm32f411ceu6

Uso do display OLED SSD1306​

Display OLED 0.96″ 128×64 I2C Azul

Instruções do LAB​

Esta atividade de laboratório tem como objetivo configurar o display OLED SSD1306. Cada item equivale a 10% da nota.

  • Crie um repositório (LAB11) via template (https://github.com/ELT73A-LAB-TPL/LAB11) na organização e clone;
  • Importe e compile o código da pasta TEMPSENSORI2C
  • Verifique a configuração dos periféricos;
  • Configure o executável e probes no STM32CubeMonitor;
  • Deploy e Dashboard no STM32CubeMonitor;
  • Configure o SQLite no Node-RED;
  • Teste de injeção de dados no SQLite;
  • Leitura do ADC e injeção de dados no SQLite;
  • Commit e push do Node-RED export flow;
  • Envie o link do repositório no GitHub (hyperlink);

Avaliação​

  • Uso do template e código - 20%
  • Configuração do STM32CubeMonitor - 20%
  • Configuração e teste do SQLite - 20%
  • Leitura do ADC e injeção de dados no SQLite - 20%
  • Commit e push do Node-RED export flow - 20%
  • Link do repositório no GitHub (hyperlink) - 10%

Verifique o seu ambiente de desenvolvimento​

Git is the most widely used source-code management tool among professional developers.

  • Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
winget install --id Git.Git -e --source winget

Configurações do git:

git config --list --show-origin

Configure o nome de usuário para todos os repositórios locais ligados às suas transações de commit:

git config --global user.name "Your Name"

Configure o email de usuário para todos os repositórios locais ligados às suas transações de commit:

git config --global user.email "you@example.com"

É recomendado verificar se a instalação do seu Git não está realizando nenhuma transformação entre LFs e CRLFs.

git config --global core.autocrlf false

Configure o git para usar o Visual Studio Code como editor padrão para tarefas como escrever mensagens de commit ou rebases interativos

git config --global core.editor "code --wait"

Habilite a coloração automática da saída da linha de comando do Git:

git config --global color.ui auto

Configura o Git para usar main como o nome do branch padrão sempre que você inicializar um novo repositório localmente:

git config --global init.defaultBranch main

Liste as configurações aplicadas:

git config --list --show-origin

Crie um novo repositório com base no template do LAB11​

Escolha o Grupo e entre com o comando abaixo para criar o repositório no GitHub:

Cole o comando abaixo no prompt aberto na pasta de trabalho!

Use o comando abaixo para criar o repositório no GitHub com base no template do laboratório LAB11:

gh repo create ELT73A-S22-2026-2-A/LAB11 --private -p ELT73A-LAB-TPL/LAB11 -c

Visualize o repositório:

gh repo view ELT73A-S22-2026-2-A/LAB11 --web

Abra o repositório clonado no VS Code:

code LAB11 --profile "STM32"
Como fazer commit da atualizações

Verifique o status do repositório:

git status

Adicione os arquivos modificados:

git add .

Realize o commit das alterações:

git commit -m "Descrição breve das alterações realizadas!"

Envie para o repositório remoto (GitHub):

git push

Vizualize o log de alterações:

git log

Vizualize no GitHub:

gh repo view --web

Diagrama de pinos do STM32F4x1​


STM32F4x1 microcontroller pinout diagram;

O debugger ST-LINK/V2 possue um conector IDC de 10 pinos. A pinagem é descrita na figura a seguir.

ST-LINK/V2 Clone


SSD1306 files​

STM32 library for working with OLEDs based on SSD1306, SH1106, SH1107 and SSD1309, supports I2C and SPI

CMakeLists.txt
# Add sources to executable
target_sources(${CMAKE_PROJECT_NAME} PRIVATE
# Add user sources here
${CMAKE_CURRENT_SOURCE_DIR}/Drivers/ssd1306/ssd1306.c
${CMAKE_CURRENT_SOURCE_DIR}/Drivers/ssd1306/ssd1306_fonts.c
${CMAKE_CURRENT_SOURCE_DIR}/Drivers/ssd1306/ssd1306_tests.c
)

# Add include paths
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
# Add user defined include paths
${CMAKE_CURRENT_SOURCE_DIR}/Drivers/ssd1306
)
Src/main.c
/* USER CODE BEGIN Includes */
#include "ssd1306.h"
#include "ssd1306_fonts.h" // Include the fonts header file located at
#include "ssd1306_tests.h"
/* USER CODE END Includes */
Src/main.c
/* USER CODE BEGIN 1 */
char myText[] = "Hello, SSD1306!";
char retVal;
/* USER CODE END 1 */
Src/main.c
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
ssd1306_Init();
// ssd1306_Fill(White);
// ssd1306_UpdateScreen();

// ssd1306_SetCursor(5, 5);
// retVal = ssd1306_WriteString(myText, Font_7x10, White);
// ssd1306_UpdateScreen();

// Run tests
//ssd1306_TestAll();

// ssd1306_TestBorder();
// ssd1306_TestFonts1();
// ssd1306_TestFonts2();
// ssd1306_TestFPS();
// ssd1306_TestLine();
// ssd1306_TestRectangle();
// ssd1306_TestRectangleFill();
// ssd1306_TestRectangleInvert();
// ssd1306_TestCircle();
// ssd1306_TestArc();
// ssd1306_TestPolyline();
// ssd1306_TestDrawBitmap();
/* USER CODE END 2 */

STM32 Internal Temperature Sensor Reading​

Seguem algumas referências para leitura do sensor de temperatura interna do STM32F4x1:

Abra o projeto gerado no VS Code:

code TEMPSENSORI2C --profile="STM32"

Src/main.c​

Implemente a lógica para acionar o LED azul via flag BLUELED:

Src/main.c
/* USER CODE BEGIN Includes */
#include <stdbool.h>
/* USER CODE END Includes */
Src/main.c
/* USER CODE BEGIN PD */
#define AVG_SLOPE 2.5f // mV/°C
#define V_AT_25C 0.76f // Volts
#define V_REF_INT 1.21f // Internal reference voltage
/* USER CODE END PD */
Src/main.c
/* USER CODE BEGIN PV */
bool BLUELED = 0;
uint32_t AD_RES_BUFFER[3];
uint16_t ADC1IN1,TEMPSENSOR,VREFINT;
float voltage1,v_ref,v_sense,temp;
/* USER CODE END PV */

Inicialize o Timer 2 com suporte a rotina de interrupção e saída PWM no canal 1:

Src/main.c
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM2_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start_IT(&htim2,TIM_CHANNEL_1);
/* USER CODE END 2 */

Toggle no LED interno via interrupção do User Key:

Scr/main.c
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// Verify BLUELED Flag
if (BLUELED)
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); // LED ON
else
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET); // LED OFF
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}
/* USER CODE END 3 */

Src/stm32f4xx_it.c​

Src/stm32f4xx_it.c
/* USER CODE BEGIN Includes */
#include <stdbool.h>
/* USER CODE END Includes */
Src/stm32f4xx_it.c
/* USER CODE BEGIN PV */
extern bool BLUELED;
extern uint32_t AD_RES_BUFFER[3];
extern uint16_t ADC1IN1,TEMPSENSOR,VREFINT;
extern float voltage1,v_ref,v_sense,temp;
/* USER CODE END PV */
Src/stm32f4xx_it.c
void EXTI0_IRQHandler(void)
{
/* USER CODE BEGIN EXTI0_IRQn 0 */
// Toggle BLUELED FLAG
BLUELED = !BLUELED;
/* USER CODE END EXTI0_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(User_KEY_EXTI0_Pin);
/* USER CODE BEGIN EXTI0_IRQn 1 */

/* USER CODE END EXTI0_IRQn 1 */
}

Inicie o ADC1 na interrupção do Timer 2:

Src/stm32f4xx_it.c
void TIM2_IRQHandler(void)
{
/* USER CODE BEGIN TIM2_IRQn 0 */

/* USER CODE END TIM2_IRQn 0 */
HAL_TIM_IRQHandler(&htim2);
/* USER CODE BEGIN TIM2_IRQn 1 */
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_RES_BUFFER, 3);
/* USER CODE END TIM2_IRQn 1 */
}
  • HAL_ADC_ConvCpltCallback() é uma função de alto nível fornecida pela ST (STMicroelectronics) para facilitar a vida do desenvolvedor. Ela é chamada automaticamente quando uma conversão ADC é concluída e os dados estão prontos para serem processados. O uso dessa função é recomendado porque ela abstrai a complexidade de lidar diretamente com as interrupções de ADC e o gerenciamento de buffers, permitindo que o desenvolvedor se concentre na lógica de aplicação em vez de detalhes de baixo nível.
Src/stm32f4xx_it.c
/* USER CODE BEGIN 1 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
// Conversion Complete & DMA Transfer Complete As Well
ADC1IN1 = AD_RES_BUFFER[0];
TEMPSENSOR = AD_RES_BUFFER[1];
VREFINT = AD_RES_BUFFER[2];
voltage1 = (ADC1IN1 * 3.3) / 4095;
// 1. Calculate the actual VREF (VDDA)
// This compensates for power supply fluctuations
v_ref = (V_REF_INT * 4095.0f) / (float)VREFINT;

// 2. Convert raw temperature sensor value to voltage
v_sense = ((float)TEMPSENSOR * v_ref) / 4095.0f;

// 3. Final Temperature in Celsius
// Note: Some datasheets use (V_sense - V_25) / Slope + 25.
// Check your specific RM; usually, if Slope is positive, it's (V_sense - V_at_25).
temp = ((v_sense - V_AT_25C) * 1000.0f / AVG_SLOPE) + 25.0f;
TIM2->CCR1 = ADC1IN1; // PWM CH1 duty cycle update based on ADC1IN1
}
/* USER CODE END 1 */

You need to enable float support for printf/snprintf in your linker flags.

cmake/gcc-arm-none-eabi.cmake
set(CMAKE_EXE_LINKER_FLAGS "${TARGET_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T \"${CMAKE_SOURCE_DIR}/STM32F411XX_FLASH.ld\"")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nano.specs -u _printf_float")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--print-memory-usage")
set(TOOLCHAIN_LINK_LIBRARIES "m")
Src/main.c
char line1[32];
char line2[32];

while (1)
{
snprintf(line1, sizeof(line1), "Volt: %.2f V", voltage1);
snprintf(line2, sizeof(line2), "Temp: %.1f C", temp);

ssd1306_Fill(Black);

ssd1306_SetCursor(0, 0);
ssd1306_WriteString(line1, Font_7x10, White);

ssd1306_SetCursor(0, 16);
ssd1306_WriteString(line2, Font_7x10, White);

ssd1306_UpdateScreen();

HAL_Delay(200);
}
Src/main.c
#include <stdio.h>
float temperature = 25.7f;
char tempchar[16];

snprintf(tempchar, sizeof(tempchar), "%.1f C", temperature);

ssd1306_SetCursor(0,0);
ssd1306_WriteString(tempchar, Font_7x10, White);
ssd1306_UpdateScreen();


#include <stdio.h>

float temperature = 25.7f;
char buffer[20];

// Format temperature string
snprintf(buffer, sizeof(buffer), "Temp: %.1f C", temperature);

// Clear display
ssd1306_Fill(Black);

// Set cursor position
ssd1306_SetCursor(0, 0);

// Write text
ssd1306_WriteString(buffer, Font_7x10, White);

// Update OLED
ssd1306_UpdateScreen();

VS Code Terminal Configuration​

Configure Git Bash como terminal integrado do Visual Studio Code para evitar problemas de formatação de texto e comandos:

.vscode/settings.json
{
"editor.formatOnSave": true,
"terminal.integrated.defaultProfile.windows": "Git Bash",
"editor.formatOnPaste": true
}

Crie um gh alias para deploy-debug​

gh alias set deploy-debug 'tag="$1"; cp ./build/Debug/*.elf ./firmware-debug.elf && gh release create "$tag" ./firmware-debug.elf --generate-notes && rm ./firmware-debug.elf' --shell

Como funciona:

  • Considera a etiqueta de lançamento como $1.
  • Copia o ELF de ./build/Debug/*.elf → ./firmware-debug.elf.
  • Executa gh release create com o arquivo renomeado.
  • Limpa removendo o arquivo renomeado temporário.

Uso:

gh deploy-debug v1.0.0

Rápida verificação do upload​

Assim que o comando terminar, você poderá verificar o upload diretamente em seu terminal usando:

gh release view v1.0.0 --web

Referências​

Recursos OLED SSD1306​

Uso do stm32-i2c-lcd-1602​

STM32: LCD 1602 w/ I2C adapter usage example