i2c-oled.c

STM32F4DISCOVERY (kit Discovery STM32F407VGT6) · Fichier : i2c-oled.c · Langage : C · Usage : Écrire sur un écran OLED SSD1306 en I2C avec la HAL

Le protocole I2C du SSD1306 tient en deux octets de contrôle : 0x00 pour une commande, 0x40 pour des données. Ce programme envoie la séquence d'initialisation puis une image de test, sans bibliothèque — le meilleur moyen de comprendre l'I2C maître.

Matériel requis

Une STM32F407G-DISC1 (Discovery F4, Cortex-M4 @ 168 MHz) avec ST-LINK integre, broches 3,3 V. 1 module OLED SSD1306 I2C (0x3C), alimentation 3,3 V.

Câblage

SDA sur PB7, SCL sur PB6 (broches I2C1 typiques des Nucleo, à confirmer dans le .ioc), VCC 3,3 V, GND.

Fonctionnement

Chaque trame I2C commence par l'octet d'adresse 0x78 puis le byte de contrôle. La séquence configure la pompe de charge et le balayage ; 0xAF allume la dalle, puis la trame 1024 octets remplit la GDDRAM.

Exécution

Projet STM32CubeIDE « STM32F407G-DISC1 » : coller le code dans main.c, configurer le .ioc, Run. La carte dispose de 4 LED (PD12-PD15) et du bouton USER sur PA0.

Variantes

Ajouter une police 5x7 pour afficher des chaînes (printf → bitmap), ou passer en DMA I2C pour libérer le CPU pendant le rafraîchissement.

i2c-oled.c

// OLED SSD1306 (0x3C) : envoi de commandes/data en I2C HAL.
#include "main.h"
#include <string.h>

extern I2C_HandleTypeDef hi2c1;

#define SSD1306_ADDR 0x78 // 0x3C << 1 (format HAL)

static void cmd(uint8_t c) {
  uint8_t d[2] = { 0x00, c };        // 0x00 = byte de commande
  HAL_I2C_Master_Transmit(&hi2c1, SSD1306_ADDR, d, 2, 10);
}
static void data(const uint8_t *p, uint16_t n) {
  uint8_t buf[129];
  buf[0] = 0x40;                       // 0x40 = byte de donnees
  memcpy(buf + 1, p, n);
  HAL_I2C_Master_Transmit(&hi2c1, SSD1306_ADDR, buf, n + 1, 100);
}
static void init(void) {
  const uint8_t seq[] = { 0xAE, 0xD5, 0x80, 0xA8, 0x3F, 0xD3, 0x00,
                          0x40, 0x8D, 0x14, 0x20, 0x00, 0xA1, 0xC8,
                          0xDA, 0x12, 0x81, 0xFF, 0xD9, 0xF1, 0xDB,
                          0x40, 0xA4, 0xA6, 0xAF };                 // AF = on
  for (unsigned i = 0; i < sizeof(seq); i++) cmd(seq[i]);
}

int main(void) {
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_I2C1_Init();   // SCL/PB6, SDA/PB7 dans le .ioc (400 kHz)
  init();
  uint8_t trame[1024];
  memset(trame, 0xAA, sizeof(trame)); // damier de test 128x64
  data(trame, sizeof(trame));
  for (;;);
}

← Retour à la fiche