1 Star 2 Fork 4

aiminick / 树莓派 4B iic oled

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
ssd1306_i2c.c 31.48 KB
一键复制 编辑 原始数据 按行查看 历史
陈俊鹏 提交于 2021-04-02 16:55 . 添加了设备的信息显示
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
/*********************************************************************
ssd306i2c库,用于Raspberry Pi。
基于Adafruit SSD1306 Arduino库。一些函数来自Adafruit GFX lib
修改者陈俊鹏
在Raspberry Pi 4B 上,连接了一个0.96寸上黄下蓝的OLED(128x64)上测试
*********************************************************************/
/*********************************************************************
这是一个基于SSD1306驱动程序的单色oled库
使用的是树莓派的i2c接口 接线方法:
GND-------GND----------任意0V
VCC-------3.3V---------任意3.3V
SDA-------SDA1---------3号引脚
SCK-------SCK1---------5号引脚
*********************************************************************/
#include <stdio.h>
#include <string.h>
#include "ssd1306_i2c.h"
#include <wiringPiI2C.h>
#include "oled_fonts.h"
#define true 1
#define false 0
#define rotation 0
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
int cursor_y = 64;
int cursor_x = 128;
// the memory buffer for the LCD. Displays Adafruit logo
int buffer[SSD1306_LCDWIDTH * SSD1306_LCDHEIGHT / 8] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
#if (SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH > 96*16)
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
0x80, 0x80, 0x00, 0x00,
0x80, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80,
0x80, 0x00, 0x80, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x8C, 0x8E, 0x84,
0x00, 0x00, 0x80, 0xF8,
0xF8, 0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xE0, 0xE0, 0xC0, 0x80,
0x00, 0xE0, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
0xFF, 0xC7, 0x01, 0x01,
0x01, 0x01, 0x83, 0xFF, 0xFF, 0x00, 0x00, 0x7C, 0xFE, 0xC7, 0x01, 0x01,
0x01, 0x01, 0x83, 0xFF,
0xFF, 0xFF, 0x00, 0x38, 0xFE, 0xC7, 0x83, 0x01, 0x01, 0x01, 0x83, 0xC7,
0xFF, 0xFF, 0x00, 0x00,
0x01, 0xFF, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x07, 0x01, 0x01, 0x01,
0x00, 0x00, 0x7F, 0xFF,
0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x01, 0xFF,
0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x03, 0x0F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE7, 0xC7, 0xC7, 0x8F,
0x8F, 0x9F, 0xBF, 0xFF, 0xFF, 0xC3, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFC, 0xFC, 0xFC,
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00,
0x01, 0x03, 0x03, 0x03,
0x03, 0x03, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03,
0x03, 0x03, 0x01, 0x01,
0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01,
0x03, 0x03, 0x00, 0x00,
0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01,
0x00, 0x00, 0x00, 0x03,
0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
#if (SSD1306_LCDHEIGHT == 64)
0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x3F, 0x1F, 0x0F,
0x87, 0xC7, 0xF7, 0xFF, 0xFF, 0x1F, 0x1F, 0x3D, 0xFC, 0xF8, 0xF8, 0xF8,
0xF8, 0x7C, 0x7D, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F, 0x07, 0x00,
0x30, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xE0, 0xC0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x7F, 0x7F, 0x3F, 0x1F,
0x0F, 0x07, 0x1F, 0x7F, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFE, 0xF8, 0xE0,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFE, 0xFE, 0x00, 0x00,
0x00, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x0E, 0xFC, 0xF8, 0x00, 0x00,
0xF0, 0xF8, 0x1C, 0x0E,
0x06, 0x06, 0x06, 0x0C, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFE, 0x00,
0x00, 0x00, 0x00, 0xFC,
0xFE, 0xFC, 0x00, 0x18, 0x3C, 0x7E, 0x66, 0xE6, 0xCE, 0x84, 0x00, 0x00,
0x06, 0xFF, 0xFF, 0x06,
0x06, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x06, 0x00, 0x00, 0xFE, 0xFE,
0x00, 0x00, 0xC0, 0xF8,
0xFC, 0x4E, 0x46, 0x46, 0x46, 0x4E, 0x7C, 0x78, 0x40, 0x18, 0x3C, 0x76,
0xE6, 0xCE, 0xCC, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F,
0x3F, 0x1F, 0x0F, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0F, 0x0F, 0x00, 0x00,
0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
0x03, 0x07, 0x0E, 0x0C,
0x18, 0x18, 0x0C, 0x06, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x0E,
0x0C, 0x18, 0x0C, 0x0F,
0x07, 0x01, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00,
0x00, 0x0F, 0x0F, 0x00,
0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F,
0x00, 0x00, 0x00, 0x07,
0x07, 0x0C, 0x0C, 0x18, 0x1C, 0x0C, 0x06, 0x06, 0x00, 0x04, 0x0E, 0x0C,
0x18, 0x0C, 0x0F, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
#endif
#endif
};
int _vccstate;
int i2cd;
#define ssd1306_swap(a, b) { int t = a; a = b; b = t; }
// the most basic function, set a single pixel
/**
* @description: 最基本的功能,设置单个像素
* @param {int} x 设置像素点在屏幕上x轴的位置
* @param {int} y 设置像素点在屏幕上y轴的位置
* @param {unsigned int} color
* @return {*} 无
*/
void ssd1306_drawPixel(int x, int y, unsigned int color)
{
if ((x < 0) || (x >= WIDTH) || (y < 0) || (y >= HEIGHT))
return;
// check rotation, move pixel around if necessary
switch (rotation) {
case 1:
ssd1306_swap(x, y);
x = WIDTH - x - 1;
break;
case 2:
x = WIDTH - x - 1;
y = HEIGHT - y - 1;
break;
case 3:
ssd1306_swap(x, y);
y = HEIGHT - y - 1;
break;
}
// x is which column
switch (color) {
case WHITE:
buffer[x + (y / 8) * SSD1306_LCDWIDTH] |= (1 << (y & 7));
break;
case BLACK:
buffer[x + (y / 8) * SSD1306_LCDWIDTH] &= ~(1 << (y & 7));
break;
case INVERSE:
buffer[x + (y / 8) * SSD1306_LCDWIDTH] ^= (1 << (y & 7));
break;
}
}
/**
* @description: 初始化1306屏
* @param {*} 参数一:vcc状态 参数二:i2c地址
* @return {*} 无
*/
void ssd1306_begin(unsigned int vccstate, unsigned int i2caddr)
{
// I2C Init
_vccstate = vccstate;
i2cd = wiringPiI2CSetup(i2caddr);
if (i2cd < 0) {
fprintf(stderr, "ssd1306_i2c : Unable to initialise I2C:\n");
return;
}
// Init sequence
ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE
ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
ssd1306_command(0x80); // the suggested ratio 0x80
ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8
ssd1306_command(SSD1306_LCDHEIGHT - 1);
ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3
ssd1306_command(0x0); // no offset
ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D
if (vccstate == SSD1306_EXTERNALVCC) {
ssd1306_command(0x10);
} else {
ssd1306_command(0x14);
}
ssd1306_command(SSD1306_MEMORYMODE); // 0x20
ssd1306_command(0x00); // 0x0 act like ks0108
ssd1306_command(SSD1306_SEGREMAP | 0x1);
ssd1306_command(SSD1306_COMSCANDEC);
#if defined SSD1306_128_32
ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
ssd1306_command(0x02);
ssd1306_command(SSD1306_SETCONTRAST); // 0x81
ssd1306_command(0x8F);
#elif defined SSD1306_128_64
ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
ssd1306_command(0x12);
ssd1306_command(SSD1306_SETCONTRAST); // 0x81
if (vccstate == SSD1306_EXTERNALVCC) {
ssd1306_command(0x9F);
} else {
ssd1306_command(0xCF);
}
#elif defined SSD1306_96_16
ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
ssd1306_command(0x2); // ada x12
ssd1306_command(SSD1306_SETCONTRAST); // 0x81
if (vccstate == SSD1306_EXTERNALVCC) {
ssd1306_command(0x10);
} else {
ssd1306_command(0xAF);
}
#endif
ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9
if (vccstate == SSD1306_EXTERNALVCC) {
ssd1306_command(0x22);
} else {
ssd1306_command(0xF1);
}
ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB
ssd1306_command(0x40);
ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4
ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6
ssd1306_command(SSD1306_DEACTIVATE_SCROLL);
ssd1306_command(SSD1306_DISPLAYON); // --turn on oled panel
}
/**
* @description: 反转显示
* @param {unsigned int} i 为1时正常显示,为0时反转显示
* @return {*} 无
*/
void ssd1306_invertDisplay(unsigned int i)
{
if (i) {
ssd1306_command(SSD1306_INVERTDISPLAY);
} else {
ssd1306_command(SSD1306_NORMALDISPLAY);
}
}
void ssd1306_command(unsigned int c)
{
// I2C
unsigned int control = 0x00; // Co = 0, D/C = 0
wiringPiI2CWriteReg8(i2cd, control, c);
}
/**
* @description: 刷新显示
* @param {*} 无
* @return {*} 无
*/
void ssd1306_display(void)
{
ssd1306_command(SSD1306_COLUMNADDR);
ssd1306_command(0); // Column start address (0 = reset)
ssd1306_command(SSD1306_LCDWIDTH - 1); // Column end address (127
// = reset)
ssd1306_command(SSD1306_PAGEADDR);
ssd1306_command(0); // Page start address (0 = reset)
#if SSD1306_LCDHEIGHT == 64
ssd1306_command(7); // Page end address
#endif
#if SSD1306_LCDHEIGHT == 32
ssd1306_command(3); // Page end address
#endif
#if SSD1306_LCDHEIGHT == 16
ssd1306_command(1); // Page end address
#endif
// I2C
int i;
for (i = 0; i < (SSD1306_LCDWIDTH * SSD1306_LCDHEIGHT / 8); i++) {
wiringPiI2CWriteReg8(i2cd, 0x40, buffer[i]);
//This sends byte by byte.
//Better to send all buffer without 0x40 first
//Should be optimized
}
}
/**
* @description: 开始向右滚动,激活从开始到停止的行的右手滚动.提示,显示屏有16排高。要滚动整个显示,请运行:ssd1306_scrollright(0x00, 0x0F)
* @param {unsigned int} start
* @param {unsigned int} stop
* @return {*}
*/
void ssd1306_startscrollright(unsigned int start, unsigned int stop)
{
ssd1306_command(SSD1306_RIGHT_HORIZONTAL_SCROLL);
ssd1306_command(0X00);
ssd1306_command(start);
ssd1306_command(0X00);
ssd1306_command(stop);
ssd1306_command(0X00);
ssd1306_command(0XFF);
ssd1306_command(SSD1306_ACTIVATE_SCROLL);
}
/**
* @description: 开始向左滚动,激活从开始到停止的行的左手滚动.提示,显示屏有16排高。要滚动整个显示,请运行:ssd1306_scrollright(0x00, 0x0F)
* @param {unsigned int} start
* @param {unsigned int} stop
* @return {*}
*/
void ssd1306_startscrollleft(unsigned int start, unsigned int stop)
{
ssd1306_command(SSD1306_LEFT_HORIZONTAL_SCROLL);
ssd1306_command(0X00);
ssd1306_command(start);
ssd1306_command(0X00);
ssd1306_command(stop);
ssd1306_command(0X00);
ssd1306_command(0XFF);
ssd1306_command(SSD1306_ACTIVATE_SCROLL);
}
/**
* @description: 开始向右滚动,激活从开始到停止的行的左手滚动.提示,显示屏有16排高。要滚动整个显示,请运行:ssd1306_scrollright(0x00, 0x0F)
* @param {unsigned int} start
* @param {unsigned int} stop
* @return {*}
*/
void ssd1306_startscrolldiagright(unsigned int start, unsigned int stop)
{
ssd1306_command(SSD1306_SET_VERTICAL_SCROLL_AREA);
ssd1306_command(0X00);
ssd1306_command(SSD1306_LCDHEIGHT);
ssd1306_command(SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL);
ssd1306_command(0X00);
ssd1306_command(start);
ssd1306_command(0X00);
ssd1306_command(stop);
ssd1306_command(0X01);
ssd1306_command(SSD1306_ACTIVATE_SCROLL);
}
/**
* @description: 开始向左滚动,激活从开始到停止的行的左手滚动.提示,显示屏有16排高。要滚动整个显示,请运行:ssd1306_scrollright(0x00, 0x0F)
* @param {unsigned int} start
* @param {unsigned int} stop
* @return {*}
*/
void ssd1306_startscrolldiagleft(unsigned int start, unsigned int stop)
{
ssd1306_command(SSD1306_SET_VERTICAL_SCROLL_AREA);
ssd1306_command(0X00);
ssd1306_command(SSD1306_LCDHEIGHT);
ssd1306_command(SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL);
ssd1306_command(0X00);
ssd1306_command(start);
ssd1306_command(0X00);
ssd1306_command(stop);
ssd1306_command(0X01);
ssd1306_command(SSD1306_ACTIVATE_SCROLL);
}
void ssd1306_stopscroll(void)
{
ssd1306_command(SSD1306_DEACTIVATE_SCROLL);
}
/**
* @description: 使显示器变暗
* @param {*} 为1时显示器变暗,为0时显示正常
* @return {*}无
*/
void ssd1306_dim(unsigned int dim)
{
unsigned int contrast;
if (dim) {
contrast = 0; // Dimmed display
} else {
if (_vccstate == SSD1306_EXTERNALVCC) {
contrast = 0x9F;
} else {
contrast = 0xCF;
}
}
// the range of contrast to too small to be really useful
// it is useful to dim the display
ssd1306_command(SSD1306_SETCONTRAST);
ssd1306_command(contrast);
}
/**
* @description: 清屏
* @param {*} 无
* @return {*} 无
*/
void ssd1306_clearDisplay(void)
{
memset(buffer, 0,
(SSD1306_LCDWIDTH * SSD1306_LCDHEIGHT / 8) * sizeof(int));
cursor_y = 0;
cursor_x = 0;
}
/**
* @description: 绘制快速H线内部
* @param {int} x 绘制的x轴位置
* @param {int} y 绘制的y轴位置
* @param {int} w 绘制的宽度
* @param {unsigned int} color
* @return {*} 无
*/
void ssd1306_drawFastHLineInternal(int x, int y, int w, unsigned int color)
{
// Do bounds/limit checks
if (y < 0 || y >= HEIGHT) {
return;
}
// make sure we don't try to draw below 0
if (x < 0) {
w += x;
x = 0;
}
// make sure we don't go off the edge of the display
if ((x + w) > WIDTH) {
w = (WIDTH - x);
}
// if our width is now negative, punt
if (w <= 0) {
return;
}
// set up the pointer for movement through the buffer
unsigned int *pBuf = buffer;
// adjust the buffer pointer for the current row
pBuf += ((y / 8) * SSD1306_LCDWIDTH);
// and offset x columns in
pBuf += x;
unsigned int mask = 1 << (y & 7);
switch (color) {
case WHITE:
while (w--) {
*pBuf++ |= mask;
};
break;
case BLACK:
mask = ~mask;
while (w--) {
*pBuf++ &= mask;
};
break;
case INVERSE:
while (w--) {
*pBuf++ ^= mask;
};
break;
}
}
/**
* @description: 绘制快速V线内部
* @param {int} x 绘制的x轴位置
* @param {int} y 绘制的y轴位置
* @param {int} w 绘制的高度
* @param {unsigned int} color
* @return {*} 无
*/
void ssd1306_drawFastVLineInternal(int x, int __y, int __h, unsigned int color)
{
// do nothing if we're off the left or right side of the screen
if (x < 0 || x >= WIDTH) {
return;
}
// make sure we don't try to draw below 0
if (__y < 0) {
// __y is negative, this will subtract enough from __h to account
// for __y being 0
__h += __y;
__y = 0;
}
// make sure we don't go past the height of the display
if ((__y + __h) > HEIGHT) {
__h = (HEIGHT - __y);
}
// if our height is now negative, punt
if (__h <= 0) {
return;
}
// this display doesn't need ints for coordinates, use local byte
// registers for faster juggling
unsigned int y = __y;
unsigned int h = __h;
// set up the pointer for fast movement through the buffer
unsigned int *pBuf = buffer;
// adjust the buffer pointer for the current row
pBuf += ((y / 8) * SSD1306_LCDWIDTH);
// and offset x columns in
pBuf += x;
// do the first partial byte, if necessary - this requires some
// masking
unsigned int mod = (y & 7);
if (mod) {
// mask off the high n bits we want to set
mod = 8 - mod;
// note - lookup table results in a nearly 10% performance
// improvement in fill* functions
// register unsigned int mask = ~(0xFF >> (mod));
static unsigned int premask[8] =
{ 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
unsigned int mask = premask[mod];
// adjust the mask if we're not going to reach the end of this
// byte
if (h < mod) {
mask &= (0XFF >> (mod - h));
}
switch (color) {
case WHITE:
*pBuf |= mask;
break;
case BLACK:
*pBuf &= ~mask;
break;
case INVERSE:
*pBuf ^= mask;
break;
}
// fast exit if we're done here!
if (h < mod) {
return;
}
h -= mod;
pBuf += SSD1306_LCDWIDTH;
}
// write solid bytes while we can - effectively doing 8 rows at a time
if (h >= 8) {
if (color == INVERSE) { // separate copy of the code so we don't
// impact performance of the black/white
// write version with an extra comparison
// per loop
do {
*pBuf = ~(*pBuf);
// adjust the buffer forward 8 rows worth of data
pBuf += SSD1306_LCDWIDTH;
// adjust h & y (there's got to be a faster way for me to
// do this, but this should still help a fair bit for now)
h -= 8;
}
while (h >= 8);
} else {
// store a local value to work with
register unsigned int val = (color == WHITE) ? 255 : 0;
do {
// write our value in
*pBuf = val;
// adjust the buffer forward 8 rows worth of data
pBuf += SSD1306_LCDWIDTH;
// adjust h & y (there's got to be a faster way for me to
// do this, but this should still help a fair bit for now)
h -= 8;
}
while (h >= 8);
}
}
// now do the final partial byte, if necessary
if (h) {
mod = h & 7;
// this time we want to mask the low bits of the byte, vs the high
// bits we did above
// register unsigned int mask = (1 << mod) - 1;
// note - lookup table results in a nearly 10% performance
// improvement in fill* functions
static unsigned int postmask[8] =
{ 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
unsigned int mask = postmask[mod];
switch (color) {
case WHITE:
*pBuf |= mask;
break;
case BLACK:
*pBuf &= ~mask;
break;
case INVERSE:
*pBuf ^= mask;
break;
}
}
}
/**
* @description: 绘制快速H线
* @param {int} x 绘制的x轴位置
* @param {int} y 绘制的y轴位置
* @param {int} w 绘制的宽度
* @param {unsigned int} color
* @return {*} 无
*/
void ssd1306_drawFastHLine(int x, int y, int w, unsigned int color)
{
unsigned int bSwap = false;
switch (rotation) {
case 0:
// 0 degree rotation, do nothing
break;
case 1:
// 90 degree rotation, swap x & y for rotation, then invert x
bSwap = true;
ssd1306_swap(x, y);
x = WIDTH - x - 1;
break;
case 2:
// 180 degree rotation, invert x and y - then shift y around for
// height.
x = WIDTH - x - 1;
y = HEIGHT - y - 1;
x -= (w - 1);
break;
case 3:
// 270 degree rotation, swap x & y for rotation, then invert y and
// adjust y for w (not to become h)
bSwap = true;
ssd1306_swap(x, y);
y = HEIGHT - y - 1;
y -= (w - 1);
break;
}
if (bSwap) {
ssd1306_drawFastVLineInternal(x, y, w, color);
} else {
ssd1306_drawFastHLineInternal(x, y, w, color);
}
}
/**
* @description: 绘制快速V线
* @param {int} x 绘制的x轴位置
* @param {int} y 绘制的y轴位置
* @param {int} w 绘制的高度
* @param {unsigned int} color
* @return {*} 无
*/
void ssd1306_drawFastVLine(int x, int y, int h, unsigned int color)
{
unsigned int bSwap = false;
switch (rotation) {
case 0:
break;
case 1:
// 90 degree rotation, swap x & y for rotation, then invert x and
// adjust x for h (now to become w)
bSwap = true;
ssd1306_swap(x, y);
x = WIDTH - x - 1;
x -= (h - 1);
break;
case 2:
// 180 degree rotation, invert x and y - then shift y around for
// height.
x = WIDTH - x - 1;
y = HEIGHT - y - 1;
y -= (h - 1);
break;
case 3:
// 270 degree rotation, swap x & y for rotation, then invert y
bSwap = true;
ssd1306_swap(x, y);
y = HEIGHT - y - 1;
break;
}
if (bSwap) {
ssd1306_drawFastHLineInternal(x, y, h, color);
} else {
ssd1306_drawFastVLineInternal(x, y, h, color);
}
}
/**
* @description: 绘制内部填充的长方体,从左下角开始
* @param {int} x 开始的x轴位置
* @param {int} y 开始的y轴位置
* @param {int} w 长方形的宽度
* @param {int} h 长方形的高度
* @param {int} fillcolor
* @return {*}
*/
void ssd1306_fillRect(int x, int y, int w, int h, int fillcolor)
{
// Bounds check
if ((x >= WIDTH) || (y >= HEIGHT))
return;
// Y bounds check
if (y + h > HEIGHT) {
h = HEIGHT - y - 1;
}
// X bounds check
if (x + w > WIDTH) {
w = WIDTH - x - 1;
}
switch (rotation) {
case 1:
swap_values(x, y);
x = WIDTH - x - 1;
break;
case 2:
x = WIDTH - x - 1;
y = HEIGHT - y - 1;
break;
case 3:
swap_values(x, y);
y = HEIGHT - y - 1;
break;
}
int i;
for (i = 0; i < h; i++)
ssd1306_drawFastHLine(x, y + i, w, fillcolor);
}
int textsize = 1;
int wrap = 1;
/**
* @description: 设置文本大小
* @param {int} s 大小 默认为1
* @return {*}
*/
void ssd1306_setTextSize(int s)
{
textsize = (s > 0) ? s : 1;
}
void ssd1306_write(int c)
{
if (c == '\n') {
cursor_y += textsize * 8;
cursor_x = 0;
} else if (c == '\r') {
// skip em
} else {
ssd1306_drawChar(cursor_x, cursor_y, c, WHITE, textsize);
cursor_x += textsize * 6;
if (wrap && (cursor_x > (WIDTH - textsize * 6))) {
cursor_y += textsize * 8;
cursor_x = 0;
}
}
}
/**
* @description: 向屏幕发送字符串
* @param {char} *str 发送内容
* @return {*}
*/
void ssd1306_drawString(char *str)
{
int i, end;
end = strlen(str);
for (i = 0; i < end; i++)
ssd1306_write(str[i]);
}
/**
* @description: 向屏幕发送一个字节
* @param {int} x 字节在x位置
* @param {int} y 字节在y位置
* @param {unsigned char} c
* @param {int} color
* @param {int} size 字体大小
* @return {*}
*/
void ssd1306_drawChar(int x, int y, unsigned char c, int color, int size)
{
if ((x >= WIDTH) || // Clip right
(y >= HEIGHT) || // Clip bottom
((x + 6 * size - 1) < 0) || // Clip left
((y + 8 * size - 1) < 0)) // Clip top
return;
int i;
int j;
for (i = 0; i < 6; i++) {
int line;
if (i == 5)
line = 0x0;
else
line = pgm_read_byte(font + (c * 5) + i);
for (j = 0; j < 8; j++) {
if (line & 0x1) {
if (size == 1) // default size
ssd1306_drawPixel(x + i, y + j, color);
else { // big size
ssd1306_fillRect(x + (i * size),
y + (j * size), size,
size, color);
}
}
line >>= 1;
}
}
}
/**
* @description: 显示字符串到屏幕上
* @param {int} x 开始显示的x轴位置
* @param {int} y 开始显示的y轴位置
* @param {int} *chr 字符串
* @return {*} 无
*/
void OLED_ShowString(int x,int y,int *chr)
{
unsigned char j=0;
while (chr[j]!='\0')
{ ssd1306_drawChar(x, y, chr[j], WHITE, textsize);
x+=8;
if(x>120){x=0;y+=2;}
j++;
}
}
int oled_pow(int m,int n)
{
int result=1;
while(n--)result*=m;
return result;
}
/**
* @description: 显示一个数字到屏幕上
* @param {int} x 开始显示的x轴位置
* @param {int} y 开始显示的y轴位置
* @param {int} num 显示的数字
* @param {int} len 欲显示数字的位数
* @return {*} 无
*/
void OLED_ShowNum(int x,int y,int num,int len)
{
int t,temp;
int enshow=0;
for(t=0;t<len;t++)
{
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
ssd1306_drawChar(x+6*t, y,' ', WHITE, textsize);
continue;
}else enshow=1;
}
ssd1306_drawChar(x+6*t, y, temp+'0', WHITE, textsize);
}
}
C
1
https://gitee.com/aiminick/raspberry-pie.git
git@gitee.com:aiminick/raspberry-pie.git
aiminick
raspberry-pie
树莓派 4B iic oled
master

搜索帮助