#ifndef __SSD1306_H__
#define __SSD1306_H__
#include "stm32c0xx_hal.h"
#include <stdbool.h>
#define SSD1306_I2C_ADDR 0x3C << 1 // 左移 1 給 HAL 用
#define SSD1306_WIDTH 128
#define SSD1306_HEIGHT 64
bool ssd1306_Init(I2C_HandleTypeDef *hi2c);
void ssd1306_Fill(uint8_t color);
void ssd1306_UpdateScreen(I2C_HandleTypeDef *hi2c);
void ssd1306_SetCursor(uint8_t x, uint8_t y);
void ssd1306_WriteChar(char ch);
void ssd1306_WriteString(const char* str);
#endif
I2C_HandleTypeDef hi2c1;
void MX_I2C1_GPIO_Init(void)
{
__HAL_RCC_GPIOB_CLK_ENABLE(); // 開啟 GPIOB 時脈
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; // PB8=SCL, PB9=SDA
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // Alternate Function, Open Drain
GPIO_InitStruct.Pull = GPIO_PULLUP; // I2C 通常需上拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_I2C1; // AF6 對應到 I2C1 on PB8/PB9 (查對應資料手冊)
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x2000090E; // 針對 48MHz SYSCLK 和 100kHz I2C
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
// 處理初始化錯誤
}
/** Configure Analogue filter */
HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE);
/** Configure Digital filter */
HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0);
}
void scan_i2c_devices(void)
{
for (uint8_t addr = 1; addr < 128; addr++)
{
if (HAL_I2C_IsDeviceReady(&hi2c1, (addr << 1), 3, 10) == HAL_OK)
{
printf("I2C Device Found at 0x%02X\n", addr);
}
else
{
printf(".");
}
}
printf("\nScan done.\n");
}
void SystemClock_Config(void)
{
// 目前先不做設定,後面會補
}
#include "ssd1306.h"
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_I2C1_GPIO_Init();
MX_I2C1_Init();
printf("Start scanning...\n");
scan_i2c_devices();
printf("Init OLED...\n");
ssd1306_Init(&hi2c1);
ssd1306_Fill(1);
ssd1306_UpdateScreen(&hi2c1);
printf("Draw text...\n");
ssd1306_Fill(0);
ssd1306_SetCursor(2, 0);
ssd1306_WriteString("Hello");
ssd1306_UpdateScreen(&hi2c1);
while (1) {}
}