SSD1306

图片转字节组的draw mode:

  • Draw mode选择Vertical - 1 bit per pixel

128x32,I2C接口

接线

  • SCL与SDA连接单片机,配置10k上拉电阻。接线图参考 注意:RES一定要有一个电容到地,否则可以初始化及设置亮度,但是屏幕上只显示白色随机亮点,无法刷新

编程

控制字节control byte

  • 控制字节配置高两位(Co和D/C#),剩下六位置零,共三种有效情况和一种无效情况
    • 0x00:其随后的一个字节为命令,然后结束I2C通讯
    • 0x80:其随后的字节为命令,然后应跟随另一个控制字节
    • 0x40:其随后的字节为图形数据,然后结束I2C通讯
    • 0xC0:无效组合

图形内存(Graphic Display Data RAM/GDDRAM)

内存的布局
  • 共8个分页(page),像素8行一页,每页128列(column)
三种寻址模式
  • 页寻址
    • 默认寻址模式,通过命令0x20,0x02配置,指针只在页内移动。
    • 每次写入一个字节后列指针+1,列指针指向127后下一次会回到0。
    • 页指针不变。
  • 水平寻址
    • 通过命令0x20,0x00配置。
    • 每次写入一个字节后后列指针+1,列指针达到127后,下一次列指针回到0。
    • 列指针从127->0时页指针+1。页指针达到结束页后回回到起始页。
  • 垂直寻址
    • 通过命令0x20,0x01配置
    • 每次写入一个字节后后页指针+1,页指针达到结束页后,下一次页指针回到0。
    • 页指针从结束页归零时列指针+1。列指针达到127后归0。
屏幕的初始化和绘图基本代码
  • 命令0xA8, 0x1F用来将屏幕配置为128x32模式
#define OzOLED_Max_X                    128 //128 Pixels
#define OzOLED_Max_Y                    32  //64  Pixels
#define OLED_ADDRESS                    0x3C
 
// registers
#define OzOLED_COMMAND_MODE             0x80
#define OzOLED_DATA_MODE                0x40
 
#define OLED_INIT_LEN   12
const uint8_t OLED_INIT_CMD[] PROGMEM = {
  0xA8, 0x1F,       // set multiplex (HEIGHT-1): 0x1F for 128x32, 0x3F for 128x64 
  0x22, 0x00, 0x03, // set min and max page
  0x20, 0x00,       // set horizontal memory addressing mode
  0xDA, 0x02,       // set COM pins hardware configuration to sequential
  0x8D, 0x14,       // enable charge pump
  0xAF,             // switch on OLED
  0xA1, 0xC8        // flip the screen
};
 
void sendCommand(byte command){
  TinyWireM.beginTransmission(OLED_ADDRESS); // begin transmitting
  TinyWireM.send(OzOLED_COMMAND_MODE);//data mode
  TinyWireM.send(command);
  TinyWireM.endTransmission();    // stop transmitting
}
 
void setCursorXY(byte X, byte Y){
  // Y up to down,    unit: 1 page (8 pixels)
  // X left to right, unit: 1 seg  (1 pixel)
    sendCommand(0x00 + (X & 0x0F));     //set column lower address
    sendCommand(0x10 + ((X>>4)&0x0F));  //set column higher address
    sendCommand(0xB0 + Y);                //set page address 
}
 
void drawBitmap(const byte *bitmap, byte X, byte Y, uint8_t w, uint8_t h){
  setCursorXY(X, Y);
  for(uint8_t i = 0; i<h; i++) {
    TinyWireM.beginTransmission(OLED_ADDRESS); // begin transmitting
    TinyWireM.send(OzOLED_DATA_MODE);//data mode
    for (uint8_t j = 0; j< w; j++){
      if (bitmap==NULL){
        // clear area
        TinyWireM.send(0);
      }
      else{
        TinyWireM.send(pgm_read_byte(&bitmap[i*w+j]));
      }
    }
    TinyWireM.endTransmission();    // stop transmitting
    setCursorXY(X, ++Y);
  }
}
 
void init(){
  TinyWireM.begin();
    for (uint8_t i = 0; i < OLED_INIT_LEN; i++){
      sendCommand(pgm_read_byte(&OLED_INIT_CMD[i]));
    }
}

72x40,I2C