思路
代码分块
include
#include <stdio.h>
#include <driver/i2c.h>
#include <string.h>
I2C初始化
此处SDA引脚为GPIO4,SCL引脚为GPIO5
void i2c_init()
{
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = 4,
.scl_io_num = 5,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 400000};
i2c_param_config(0, &conf);
i2c_driver_install(0, I2C_MODE_MASTER, 0, 0, 0);
}
SSD1306初始化
void ssd1306_init(uint8_t *buffer)
{
uint8_t init_data[] = {
0xae, // 熄屏
0x20, 0x00, // 水平寻址
0x40, // 显示起始行地址
0xa1, // 正常列扫描
0xa8, 0x3f, // 复用率
0xc8, // 正常行扫描
0xd3, 0x00, // 设置COM偏移量,即屏幕像上偏移的行数
0xda, 0x12, // 使用备选引脚配置,并禁用左右反置
0xd5, 0x80, // 设置分频因子与振荡频率
0xd9, 0x22, // 设置vcomh电压为0.83*Vcc
0xdb, 0x40, //
0x81, 0xff, // 亮度最大
0x8d, 0x14, // 关闭电荷泵
0xa6,
0x2e, // 禁止滚动
0xaf}; // 开屏
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, 0x78, true);
i2c_master_write_byte(cmd, 0x00, true);
i2c_master_write(cmd, init_data, 25, true);
i2c_master_stop(cmd);
i2c_master_cmd_begin(0, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
clear_screen(buffer);
};
清屏
void clear_screen(uint8_t *buffer)
{
memset(buffer, 0, 1024);
};
画一个像素点
void pixel(uint8_t *buffer, int x, int y)
{
buffer[y / 8 * 128 + x] |= (1 << (y % 8));
}
画横线
void horizontal_line(uint8_t *buffer, int x, int y, int l)
{
for (int i = 0; i < l; i++)
pixel(buffer, x + i, y);
};
画竖线
void vertical_line(uint8_t *buffer, int x, int y, int l)
{
for (int i = 0; i < l; i++)
pixel(buffer, x, y + i);
};
画矩形
void rectangle(uint8_t *buffer, int x, int y, int w, int h)
{
horizontal_line(buffer, x, y, w);
horizontal_line(buffer, x, y + h - 1, w);
vertical_line(buffer, x, y, h);
vertical_line(buffer, x + w - 1, y, h);
};
画16*16像素图
void pictrue16(uint8_t *buffer, uint8_t *pictrue, int x, int y)
{
for (int i = 0; i < 32; i++)
{
if (i < 16)
buffer[y / 8 * 128 + x + i] = pictrue[i];
else
buffer[y / 8 * 128 + x + 128 - 16 + i] = pictrue[i];
};
};
画32*32像素图
void pictrue32(uint8_t *buffer, uint8_t *pictrue, int x, int y)
{
for (int i = 0; i < 32; i++)
buffer[y / 8 * 128 + x + i] = pictrue[i];
for (int i = 32; i < 64; i++)
buffer[y / 8 * 128 + x + 128 + i-32] = pictrue[i];
for (int i = 64; i < 96; i++)
buffer[y / 8 * 128 + x + 256 + i-64] = pictrue[i];
for (int i = 96; i < 128; i++)
buffer[y / 8 * 128 + x + 384 + i-96] = pictrue[i];
};
画128*64像素图
void pictrue128_64(uint8_t *buffer,uint8_t *pictrue){
for(int i=0;i<1024;i++){
buffer[i]=pictrue[i];
};
}
画5*8像素图
void pictrue8_5(uint8_t *buffer,uint8_t *pictrue,int x,int y){
for(int i=0;i<5;i++){
buffer[y/8*128+x+i]=pictrue[i];
};
};
刷新显示函数
void show(uint8_t *buffer)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, 0x78, true);
i2c_master_write_byte(cmd, 0x40, true);
i2c_master_write(cmd, buffer, 1024, true);
i2c_master_stop(cmd);
i2c_master_cmd_begin(0, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
};
全代码
#include <stdio.h>
#include <driver/i2c.h>
#include <string.h>
uint8_t a[5]={0x18,0x24,0x24,0x1c,0x20};
uint8_t b[5]={0x7E,0x48,0x48,0x30,0x00};
uint8_t c[5]={0x00,0x38,0x44,0x44,0x44};
uint8_t d[5]={0x30,0x48,0x48,0x7F,0x00};
uint8_t e[5]={0x1C,0x2A,0x2A,0x2C,0x00};
uint8_t f[5]={0x04,0x04,0x7F,0x05,0x04};
uint8_t g[5]={0x66,0x89,0x89,0x7E,0x00};
uint8_t h[5]={0x7F,0x08,0x08,0x70,0x00};
uint8_t i[5]={0x00,0x00,0x7A,0x00,0x00};
uint8_t j[5]={0x40,0x80,0x80,0x7D,0x00};
uint8_t k[5]={0x7E,0x18,0x24,0x40,0x00};
uint8_t l[5]={0x00,0x80,0xFF,0x00,0x00};
uint8_t m[5]={0x38,0x04,0x38,0x04,0x38};
uint8_t n[5]={0x00,0x3C,0x04,0x38,0x00};
uint8_t o[5]={0x18,0x24,0x24,0x18,0x00};
uint8_t p[5]={0x7E,0x12,0x12,0x0C,0x00};
uint8_t q[5]={0x0C,0x12,0x12,0xFE,0x00};
uint8_t r[5]={0x7E,0x08,0x04,0x04,0x00};
uint8_t s[5]={0x04,0x04,0x7F,0x44,0x44};
uint8_t t[5]={0x04,0x04,0x7F,0x44,0x44};
uint8_t u[5]={0x3C,0x40,0x40,0x3C,0x40};
uint8_t v[5]={0x0C,0x30,0x40,0x30,0x0C};
uint8_t w[5]={0x1C,0x20,0x1C,0x20,0x1C};
uint8_t x[5]={0x44,0x28,0x10,0x28,0x44};
uint8_t y[5]={0x9E,0x90,0x90,0xFE,0x00};
uint8_t z[5]={0x42,0x62,0x52,0x4A,0x46};
void i2c_init()
{
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = 4,
.scl_io_num = 5,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 400000};
i2c_param_config(0, &conf);
i2c_driver_install(0, I2C_MODE_MASTER, 0, 0, 0);
}
void clear_screen(uint8_t *buffer)
{
memset(buffer, 0, 1024);
};
void pixel(uint8_t *buffer, int x, int y)
{
buffer[y / 8 * 128 + x] |= (1 << (y % 8));
}
void ssd1306_init(uint8_t *buffer)
{
uint8_t init_data[] = {
0xae, // 熄屏
0x20, 0x00, // 水平寻址
0x40, // 显示起始行地址
0xa1, // 正常列扫描
0xa8, 0x3f, // 复用率
0xc8, // 正常行扫描
0xd3, 0x00, // 设置COM偏移量,即屏幕像上偏移的行数
0xda, 0x12, // 使用备选引脚配置,并禁用左右反置
0xd5, 0x80, // 设置分频因子与振荡频率
0xd9, 0x22, // 设置vcomh电压为0.83*Vcc
0xdb, 0x40, //
0x81, 0xff, // 亮度最大
0x8d, 0x14, // 关闭电荷泵
0xa6,
0x2e, // 禁止滚动
0xaf}; // 开屏
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, 0x78, true);
i2c_master_write_byte(cmd, 0x00, true);
i2c_master_write(cmd, init_data, 25, true);
i2c_master_stop(cmd);
i2c_master_cmd_begin(0, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
clear_screen(buffer);
};
void horizontal_line(uint8_t *buffer, int x, int y, int l)
{
for (int i = 0; i < l; i++)
pixel(buffer, x + i, y);
};
void vertical_line(uint8_t *buffer, int x, int y, int l)
{
for (int i = 0; i < l; i++)
pixel(buffer, x, y + i);
};
void rectangle(uint8_t *buffer, int x, int y, int w, int h)
{
horizontal_line(buffer, x, y, w);
horizontal_line(buffer, x, y + h - 1, w);
vertical_line(buffer, x, y, h);
vertical_line(buffer, x + w - 1, y, h);
};
void show(uint8_t *buffer)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, 0x78, true);
i2c_master_write_byte(cmd, 0x40, true);
i2c_master_write(cmd, buffer, 1024, true);
i2c_master_stop(cmd);
i2c_master_cmd_begin(0, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
};
void pictrue16(uint8_t *buffer, uint8_t *pictrue, int x, int y)
{
for (int i = 0; i < 32; i++)
{
if (i < 16)
buffer[y / 8 * 128 + x + i] = pictrue[i];
else
buffer[y / 8 * 128 + x + 128 - 16 + i] = pictrue[i];
};
};
void pictrue32(uint8_t *buffer, uint8_t *pictrue, int x, int y)
{
for (int i = 0; i < 32; i++)
buffer[y / 8 * 128 + x + i] = pictrue[i];
for (int i = 32; i < 64; i++)
buffer[y / 8 * 128 + x + 128 + i-32] = pictrue[i];
for (int i = 64; i < 96; i++)
buffer[y / 8 * 128 + x + 256 + i-64] = pictrue[i];
for (int i = 96; i < 128; i++)
buffer[y / 8 * 128 + x + 384 + i-96] = pictrue[i];
};
void pictrue128_64(uint8_t *buffer,uint8_t *pictrue){
for(int i=0;i<1024;i++){
buffer[i]=pictrue[i];
};
}
void pictrue8_5(uint8_t *buffer,uint8_t *pictrue,int x,int y){
for(int i=0;i<5;i++){
buffer[y/8*128+x+i]=pictrue[i];
};
};
void app_main()
{
uint8_t buffer[16 * 64] = {0};
i2c_init();
ssd1306_init(buffer);
pictrue8_5(buffer, a,0,0);
show(buffer);
}