以下是基于 STM32F103 HAL 库的 OLED 显示屏 IIC 驱动代码,供参考:
```c
#include "stm32f1xx_hal.h"
#include "fonts.h"
#define OLED_I2C_ADDR 0x78 // OLED I2C 地址
#define OLED_WIDTH 128 // OLED 宽度
#define OLED_HEIGHT 64 // OLED 高度
I2C_HandleTypeDef hi2c1;
void OLED_Init(void)
{
uint8_t data[] = {
0xAE, // 关闭显示
0xD5, 0x80, // 设置时钟分频因子,震荡频率
0xA8, 0x3F, // 设置驱动路数
0xD3, 0x00, // 设置显示偏移
0x40, // 设置起始行
0x8D, 0x14, // 使能电荷泵
0x20, 0x00, // 水平寻址模式
0xA1, // 设置段重定向
0xC8, // 设置行重定向
0xDA, 0x12, // 设置 COM 硬件引脚配置
0x81, 0xCF, // 设置对比度
0xD9, 0xF1, // 设置预充电周期
0xDB, 0x40, // 设置 VCOMH 电压倍率
0xA4, // 全局显示开启
0xA6, // 设置显示方式,正常显示
0xAF // 开启显示
};
HAL_I2C_Mem_Write(&hi2c1, OLED_I2C_ADDR, 0x00, 1, data, sizeof(data), 1000);
}
void OLED_Clear(void)
{
uint8_t data[OLED_WIDTH * OLED_HEIGHT / 8] = {0};
HAL_I2C_Mem_Write(&hi2c1, OLED_I2C_ADDR, 0x40, 1, data, sizeof(data), 1000);
}
void OLED_SetPos(uint8_t x, uint8_t y)
{
uint8_t data[] = {
0x00 + x % 16, // 设置列低位地址
0x10 + x / 16, // 设置列高位地址
0xB0 + y, // 设置页地址
};
HAL_I2C_Mem_Write(&hi2c1, OLED_I2C_ADDR, 0x00, 1, data, sizeof(data), 1000);
}
void OLED_DrawPixel(uint8_t x, uint8_t y, uint8_t color)
{
OLED_SetPos(x, y);
uint8_t data[] = {color};
HAL_I2C_Mem_Write(&hi2c1, OLED_I2C_ADDR, 0x40, 1, data, 1, 1000);
}
void OLED_DrawChar(uint8_t x, uint8_t y, uint8_t ch, uint8_t size, uint8_t color)
{
uint8_t i, j;
uint8_t data[size * size];
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
if (size == 12) {
data[i * size + j] = pgm_read_byte(&font1206[(ch - 32) * 12 + i]) & (1 << (11 - j)) ? color : 0;
} else {
data[i * size + j] = pgm_read_byte(&font1608[(ch - 32) * 16 + i]) & (1 << (15 - j)) ? color : 0;
}
}
}
OLED_SetPos(x, y);
HAL_I2C_Mem_Write(&hi2c1, OLED_I2C_ADDR, 0x40, 1, data, size * size, 1000);
}
void OLED_DrawString(uint8_t x, uint8_t y, char *str, uint8_t size, uint8_t color)
{
while (*str) {
OLED_DrawChar(x, y, *str++, size, color);
x += size / 2;
}
}
int main(void)
{
HAL_Init();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_I2C1_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 400000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
HAL_I2C_Init(&hi2c1);
OLED_Init();
OLED_Clear();
OLED_DrawString(0, 0, "Hello World!", 12, 1);
while (1) {
HAL_Delay(1000);
}
}
```
需要注意的是,上述代码中使用了一个 `fonts.h` 文件,它包含了 OLED 显示屏所需的字体数据。可以根据需要更换字体文件。