Pular para o conteúdo

Firmware

Código que usa HAL, em Core/Inc e Core/Src (fora de pds/).

ParteResponsávelEstado
Leitura do MAX30102 (I2C1, FIFO, INT no PB5)Joãoa fazer
Serial pro PC (USART1 a 921600 com DMA, adaptador USB-serial)Joãoconfigurada no .ioc
Fonte falsa (PhysioNet em flash)Andréa fazer
Timer, filas e laço principal (TIM2 a 100 Hz já configurado)Andréa fazer
Display OLED (I2C3)Celsoa fazer
SinalPino
Sensor SCL / SDA (I2C1)PB6 / PB7
Sensor INT (EXTI5)PB5
Display SCL / SDA (I2C3)PA8 / PB4
Serial TX / RX (USART1)PA9 / PA10 (TX da placa → RX do adaptador)
Cristal HSE 25 MHzPH0 / PH1 (já soldado na Black Pill)

HSE 25 MHz → PLL (/25, ×192, /2) → SYSCLK 96 MHz. APB1 a 48 MHz (timers a 96 MHz), APB2 a 96 MHz. O TIM2 gera a interrupção de 100 Hz: 96 MHz ÷ 9600 ÷ 100.

InterrupçãoPra quê
EXTI9_5 (PB5, borda de descida, pull-up)INT do MAX30102: FIFO com amostras
TIM2 (100 Hz)processamento periódico da cadeia
DMA2 Stream 7 + USART1envio pela serial sem travar a CPU

O que está no sensor-ppg.ioc e por quê. Quem mexer no .ioc confere esta lista antes de gerar o código.

Primeiro, em System Core → RCC: High Speed Clock (HSE) = Crystal/Ceramic Resonator. Os pinos PH0/PH1 ficam reservados pro cristal de 25 MHz, que já vem soldado na placa: não ligar nada neles.

CampoValorPor quê
Input frequency (HSE)25cristal da Black Pill
PLL Source MuxHSEo oscilador interno (HSI) é impreciso
/M251 MHz na entrada do PLL
×N192192 MHz no VCO
/P2SYSCLK 96 MHz: folga pro PDS (FFT, filtros)
System Clock MuxPLLCLK
AHB/1HCLK 96 MHz
APB1/248 MHz (o limite do APB1 é 50); timers do APB1 a 96 MHz
APB2/196 MHz (USART1 fica aqui)

Se o clock mudar, o baud rate da USART1 e o TIM2 mudam junto: recalcular.

CampoValorPor quê
ModeAsynchronous
PinosPA9 = TX, PA10 = RXTX da placa no RX do adaptador USB-serial, GND em comum
Baud rate921600, 8N1400 Hz × 2 canais em texto não cabe em 115200. A 96 MHz o erro é 0,16%; a 16 MHz seria 2,12% (perde bytes)
DMAUSART1_TX, DMA2 Stream 7, Memory To Peripheral, Normal, incremento só na memória, Byte/Byteo DMA envia o buffer e a CPU segue lendo o sensor e rodando o PDS
NVICUSART1 global interruptavisa o fim do envio por DMA
CampoValorPor quê
ModeExternal Interrupt, Falling edgeo INT do sensor é ativo em nível baixo
PullPull-upo INT é dreno aberto
NVICEXTI line[9:5] interrupts
CampoValorPor quê
Clock SourceInternal Clock
Prescaler959996 MHz ÷ 9600 = 10 kHz
Counter Period9910 kHz ÷ 100 = 100 Hz (PPG_FS_HZ)
NVICTIM2 global interrupt

Triângulo amarelo em I2C1, USART1, RCC, TIM1, TIM4, SDIO, SPI3 é esperado: algum modo alternativo daquele periférico usa um pino já ocupado (ex.: o alerta SMBus do I2C1 é o PB5). Só é problema se ficar vermelho ou se o modo de um periférico em uso mudar sozinho.

Toolchain CMake. O código nosso fica fora de Core/*/pds/ ou dentro dos blocos USER CODE, que o CubeMX preserva.

  • Um PR de cada vez mexe no .ioc.
  • Depois de regenerar no CubeMX, conferir que nada em Core/*/pds/ mudou.