/** * @file ssd1306_oled.c * @author xushenghao * @brief 0.96 SSD1306 OLED display driver * @version 0.1 * @note PB13-SCK PB12-SDA */ #include "ssd1306_oled.h" #include "string.h" /************************************6*8的点阵************************************/ const uint8_t F6x8[][6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // ! 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // " 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // # 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $ 0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // % 0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // & 0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // ' 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // ( 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // ) 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // * 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // + 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // , 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // - 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // . 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // / 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1 0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4 0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6 0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7 0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // : 0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ; 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // < 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // = 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // > 0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ? 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @ 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R 0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W 0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X 0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y 0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [ 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ] 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _ 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // ' 0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b 0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d 0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r 0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, // z 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, // horiz lines }; /****************************************8*16的点阵************************************/ const uint8_t F8X16[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00, //! 1 0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //" 2 0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00, 0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00, // # 3 0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00, 0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00, //$ 4 0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00, 0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00, //% 5 0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10, //& 6 0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //' 7 0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00, //( 8 0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, //) 9 0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00, 0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00, //* 10 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00, //+ 11 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, //, 12 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, //- 13 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, //. 14 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04, 0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, /// 15 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00, // 0 16 0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // 1 17 0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00, // 2 18 0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // 3 19 0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00, // 4 20 0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00, // 5 21 0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // 6 22 0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, // 7 23 0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00, // 8 24 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00, // 9 25 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, //: 26 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, //; 27 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, //< 28 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, //= 29 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, //> 30 0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00, //? 31 0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00, 0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00, //@ 32 0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20, // A 33 0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // B 34 0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, // C 35 0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // D 36 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00, // E 37 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, // F 38 0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00, // G 39 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20, // H 40 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // I 41 0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00, // J 42 0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00, 0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00, // K 43 0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00, // L 44 0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00, // M 45 0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00, // N 46 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // O 47 0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00, // P 48 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00, // Q 49 0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20, // R 50 0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00, // S 51 0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // T 52 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // U 53 0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00, // V 54 0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00, 0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00, // W 55 0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08, 0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20, // X 56 0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // Y 57 0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00, // Z 58 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00, //[ 59 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00, //\ 60 0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00, //] 61 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //^ 62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, //_ 63 0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //` 64 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20, // a 65 0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // b 66 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00, // c 67 0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20, // d 68 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00, // e 69 0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // f 70 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00, // g 71 0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // h 72 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // i 73 0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, // j 74 0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00, // k 75 0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // l 76 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F, // m 77 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // n 78 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // o 79 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00, // p 80 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80, // q 81 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00, // r 82 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00, // s 83 0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00, // t 84 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20, // u 85 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00, // v 86 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, 0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00, // w 87 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00, // x 88 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00, // y 89 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00, // z 90 0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40, //{ 91 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, //| 92 0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, //} 93 0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //~ 94 }; const uint8_t LOGO[] = { 0x00, 0x03, 0x05, 0x09, 0x11, 0xFF, 0x11, 0x89, 0x05, 0xC3, 0x00, 0xE0, 0x00, 0xF0, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0xFF, 0x11, 0xAA, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x01, 0x38, 0x44, 0x82, 0x92, 0x92, 0x74, 0x01, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x44, 0xC7, 0x01, 0x7D, 0x7D, 0x7D, 0x7D, 0x01, 0x7D, 0x7D, 0x7D, 0x7D, 0x01, 0x7D, 0x7D, 0x7D, 0x7D, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0x00, 0x00, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x06, 0xE6, 0x66, 0x20, 0x00, 0x06, 0x06, 0x86, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x86, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x86, 0x86, 0x86, 0x86, 0x86, 0x80, 0x80, 0x86, 0x86, 0x06, 0x86, 0x86, 0xC0, 0xC0, 0x86, 0x86, 0x86, 0x06, 0x06, 0xD0, 0x30, 0x76, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1C, 0x00, 0xFE, 0x00, 0x01, 0x02, 0x00, 0xC4, 0x18, 0x20, 0x02, 0x9E, 0x63, 0xB2, 0x0E, 0x00, 0xFF, 0x81, 0x81, 0xFF, 0x00, 0x00, 0x80, 0x40, 0x30, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x23, 0xEA, 0xAA, 0xBF, 0xAA, 0xEA, 0x03, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0C, 0x08, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x81, 0x80, 0x80, 0x81, 0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x09, 0x0C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x1E, 0x21, 0x40, 0x40, 0x50, 0x21, 0x5E, 0x00, 0x1E, 0x21, 0x40, 0x40, 0x50, 0x21, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC1, 0xC1, 0xFF, 0xFF, 0xC1, 0xC1, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0xFC, 0xF3, 0xEF, 0xF3, 0xFC, 0x80, 0xFF, 0x80, 0xEE, 0xEE, 0xEE, 0xF5, 0xFB, 0xFF, 0x9C, 0xBE, 0xB6, 0xB6, 0x88, 0xFF, 0x00, // end }; static uint8_t _buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8]; // 定义屏幕缓冲区 static uint8_t _buffer_copy[SSD1306_WIDTH * SSD1306_HEIGHT / 8]; // 屏幕缓冲区副本 static void i2c_start(void) { SDA_OUT(); GPIO_SET(SSD1306_SDA_PORT, SSD1306_SDA_PIN); GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); delay_us(4); GPIO_RESET(SSD1306_SDA_PORT, SSD1306_SDA_PIN); delay_us(4); GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); } static void i2c_stop(void) { SDA_OUT(); GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); GPIO_RESET(SSD1306_SDA_PORT, SSD1306_SDA_PIN); delay_us(4); GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); GPIO_SET(SSD1306_SDA_PORT, SSD1306_SDA_PIN); delay_us(4); } static BOOL i2c_wait_ack(void) { uint8_t count = 0; SDA_IN(); GPIO_SET(SSD1306_SDA_PORT, SSD1306_SDA_PIN); delay_us(4); GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); delay_us(4); while (GPIO_READ(SSD1306_SDA_PORT, SSD1306_SDA_PIN)) { count++; if (count > 250) { i2c_stop(); return FALSE; } } GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); return TRUE; } static void i2c_ack(void) { GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); SDA_OUT(); GPIO_RESET(SSD1306_SDA_PORT, SSD1306_SDA_PIN); delay_us(2); GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); delay_us(2); GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); } static void i2c_nack(void) { GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); SDA_OUT(); GPIO_SET(SSD1306_SDA_PORT, SSD1306_SDA_PIN); delay_us(2); GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); delay_us(2); GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); } uint8_t i2c_read_byte(BOOL ack) { uint8_t i = 0, receive = 0; SDA_IN(); for (i = 0; i < 8; i++) { GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); delay_us(2); GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); receive <<= 1; if (GPIO_READ(SSD1306_SDA_PORT, SSD1306_SDA_PIN)) { receive++; } delay_us(1); } if (!ack) { i2c_nack(); } else { i2c_ack(); } return receive; } void i2c_write_byte(uint8_t data) { uint8_t i = 0; SDA_OUT(); GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); for (i = 0; i < 8; i++) { // IIC_SDA=(txd&0x80)>>7; if ((data & 0x80) >> 7) GPIO_SET(SSD1306_SDA_PORT, SSD1306_SDA_PIN); else GPIO_RESET(SSD1306_SDA_PORT, SSD1306_SDA_PIN); data <<= 1; delay_us(2); GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); delay_us(2); GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN); delay_us(2); } } static void i2c_write_command(uint8_t command) { uint8_t dd[2]; dd[0] = SSD1306_CMD_SET_LOW_COLUMN; // Co = 0, D/C# = 0 dd[1] = command; i2c_start(); i2c_write_byte(SSD1306_I2C_ADDRESS); i2c_wait_ack(); i2c_write_byte(dd[0]); i2c_wait_ack(); i2c_write_byte(dd[1]); i2c_wait_ack(); i2c_stop(); } static void i2c_write_data(uint8_t data) { uint8_t dd[2]; dd[0] = SSD1306_CMD_SET_START_LINE; // Co = 0, D/C# = 1 dd[1] = data; i2c_start(); i2c_write_byte(SSD1306_I2C_ADDRESS); i2c_wait_ack(); i2c_write_byte(dd[0]); i2c_wait_ack(); i2c_write_byte(dd[1]); i2c_wait_ack(); } /** * @brief 设置SSD1306 OLED显示屏上的显示位置 * * 该函数用于设置SSD1306 OLED显示屏上的显示位置,通过x和y坐标确定显示位置。 * * @param x 要设置的横坐标(0-127) * @param y 要设置的纵坐标(0-7,对应SSD1306 OLED的8个页面) */ void set_position(uint8_t x, uint8_t y) { i2c_write_command(0xb0 + y); i2c_write_command(((x & 0xf0) >> 4) | 0x10); i2c_write_command((x & 0x0f) | 0x01); } void ssd1306_test(void) { ssd1306_f8x16_string(0, 0, " TEST"); ssd1306_f8x16_number(40, 0, -15.26, 2); ssd1306_f6x8_string_number(0, 3, " @ADC1:", 'V', 24); ssd1306_update_screen(); } void ssd1306_init(void) { i2c_write_command(SSD1306_CMD_DISPLAY_OFF); // display off i2c_write_command(SSD1306_CMD_MEMORY_MODE); // Set Memory Addressing Mode i2c_write_command(SSD1306_CMD_SET_HIGH_COLUMN); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid i2c_write_command(SSD1306_CMD_COM_SCAN_DEC); // Set COM Output Scan Direction i2c_write_command(SSD1306_CMD_SET_LOW_COLUMN); //---set low column address i2c_write_command(SSD1306_CMD_SET_HIGH_COLUMN); //---set high column address i2c_write_command(SSD1306_CMD_SET_START_LINE); //--set start line address i2c_write_command(SSD1306_CMD_SET_CONTRAST); //--set contrast control register i2c_write_command(0xff); // 亮度调节 0x00~0xff i2c_write_command(0xa1); //--set segment re-map 0 to 127 i2c_write_command(SSD1306_CMD_NORMAL_DISPLAY); //--set normal display i2c_write_command(SSD1306_CMD_SET_MULTIPLEX); //--set multiplex ratio(1 to 64) i2c_write_command(0x3f); // i2c_write_command(SSD1306_CMD_DISPLAY_ALL_ON_RESUME); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content i2c_write_command(SSD1306_CMD_SET_DISPLAY_OFFSET); //-set display offset i2c_write_command(SSD1306_CMD_SET_LOW_COLUMN); //-not offset i2c_write_command(SSD1306_CMD_SET_DISPLAY_CLOCK_DIV); //--set display clock divide ratio/oscillator frequency i2c_write_command(0xf0); //--set divide ratio i2c_write_command(SSD1306_CMD_SET_PRECHARGE); //--set pre-charge period i2c_write_command(SSD1306_CMD_PAGE_ADDR); // i2c_write_command(SSD1306_CMD_SET_COM_PINS); //--set com pins hardware configuration i2c_write_command(0x12); i2c_write_command(SSD1306_CMD_SET_VCOM_DETECT); //--set vcomh i2c_write_command(SSD1306_CMD_MEMORY_MODE); // 0x20,0.77xVcc i2c_write_command(SSD1306_CMD_CHARGE_PUMP); //--set DC-DC enable i2c_write_command(SSD1306_CMD_SET_DC_DC_ENABLE); // i2c_write_command(SSD1306_CMD_DISPLAY_ON); //--turn on oled panel ssd1306_clear(); // ssd1306_test(); } void ssd1306_logo(void) { ssd1306_draw_bmp(0, 0, SSD1306_WIDTH, 2, LOGO); } void ssd1306_display_on(void) { i2c_write_command(SSD1306_CMD_CHARGE_PUMP); // 设置电荷泵 i2c_write_command(SSD1306_CMD_SET_DC_DC_ENABLE); // 开启电荷泵 i2c_write_command(SSD1306_CMD_DISPLAY_ON); // OLED唤醒 } void ssd1306_display_off(void) { i2c_write_command(SSD1306_CMD_CHARGE_PUMP); // 设置电荷泵 i2c_write_command(SSD1306_CMD_SET_HIGH_COLUMN); // 关闭电荷泵 i2c_write_command(SSD1306_CMD_DISPLAY_OFF); // OLED休眠 } /** * @brief 更新SSD1306 OLED显示屏的内容 * * 此函数将缓冲区中的数据写入SSD1306 OLED显示屏,从而更新显示内容。 * * 首先,通过发送命令设置列地址和页地址,然后将缓冲区中的数据逐行写入显示屏。 * * @note 在调用此函数之前,需要将需要显示的数据写入缓冲区。 */ void ssd1306_update_screen(void) { for (uint8_t i = 0; i < SSD1306_HEIGHT / 8; i++) { uint8_t update_needed = 0; for (uint8_t j = 0; j < SSD1306_WIDTH; j++) { if (_buffer[j + i * SSD1306_WIDTH] != _buffer_copy[j + i * SSD1306_WIDTH]) { update_needed = 1; break; } } if (update_needed) { i2c_write_command(0xb0 + i); i2c_write_command(0x01); i2c_write_command(0x10); for (uint8_t j = 0; j < SSD1306_WIDTH; j++) { i2c_write_data(_buffer[j + i * SSD1306_WIDTH]); } } } osel_memcpy(_buffer_copy, _buffer, ARRAY_LEN(_buffer)); } /** * @brief 填充整个屏幕为指定颜色 * * 该函数将 SSD1306 OLED 显示屏的每一个像素点都设置为指定的颜色。 * * @param color 颜色值,SSD1306_BLACK 表示关闭像素点(黑色),SSD1306_WHITE 表示打开像素点(白色) */ void ssd1306_fill(uint8_t color) { ssd1306_clear_buffer(); osel_memset(_buffer, color, ARRAY_LEN(_buffer)); ssd1306_update_screen(); } /** * @brief 清空SSD1306显示屏 * * 该函数通过向SSD1306显示屏发送一系列命令来清空显示内容。 * * 首先,通过循环遍历每个页面(SSD1306显示屏有8个页面), * 对每个页面执行以下操作: * 1. 发送页面地址命令(0xb0 + y),其中y为当前页面索引。 * 2. 发送列地址低位命令(0x01)。 * 3. 发送列地址高位命令(0x10),表示从第一列开始。 * 4. 循环遍历每一列(SSD1306显示屏的宽度), * 发送数据0x00以清空该列的内容。 */ void ssd1306_clear(void) { ssd1306_clear_buffer(); ssd1306_update_screen(); } void ssd1306_clear_buffer(void) { osel_memset(_buffer, SSD1306_BLACK, ARRAY_LEN(_buffer)); osel_memset(_buffer_copy, 0xff, ARRAY_LEN(_buffer_copy)); } /** * @brief 在指定区域内绘制BMP * * 在指定坐标区域内绘制一个BMP,使用SSD1306 OLED显示屏 * ssd1306_draw_bmp(0, 0, SSD1306_WIDTH, 2); * @param x0 BMP绘制的起始X坐标 * @param y0 BMP绘制的起始Y坐标 * @param x1 BMP绘制的结束X坐标 * @param y1 BMP绘制的结束Y坐标 */ void ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const uint8_t *bmp) { uint8_t j = 0; uint8_t x, y; ssd1306_clear_buffer(); if (y1 % 8 == 0) y = y1 / 8; else y = y1 / 8 + 1; for (y = y0; y < y1; y++) { set_position(x0, y); for (x = x0; x < x1; x++) { i2c_write_data(bmp[j++]); } } } /** * @brief 在SSD1306 OLED显示屏上显示字符串 * * 在SSD1306 OLED显示屏上以6x8像素的字体显示给定的字符串。 * * @param x 显示字符串的起始x坐标 * @param y 显示字符串的起始y坐标 * @param str 要显示的字符串 */ void ssd1306_f6x8_string(uint8_t x, uint8_t y, const uint8_t *ch) { uint8_t c = 0, i = 0, j = 0; while (ch[j] != '\0') { c = ch[j] - 32; if (x > 126) { x = 0; y++; } for (i = 0; i < 6; i++) _buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i]; x += 6; j++; } } /** * @brief 将浮点数显示在SSD1306显示屏上 * * 该函数将给定的浮点数num转换为字符串,并将其显示在SSD1306显示屏的指定位置。 * * @param x 显示的起始x坐标 * @param y 显示的起始y坐标 * @param num 要显示的浮点数 * @param dot_num 小数点后的位数,0表示不显示小数部分 */ void ssd1306_f6x8_number(uint8_t x, uint8_t y, float32 num, uint8_t dot_num) { uint8_t ch[9] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'}; uint8_t c = 0, i = 0, j = 0; if (num < 0) { ch[i++] = '-'; num = -num; } if (num > 32000) return; c = 8 - i; if (num >= 10000) { ch[i++] = num / 10000 + 48; ch[i++] = (int32_t)(num) % 10000 / 1000 + 48; ch[i++] = (int32_t)(num) % 1000 / 100 + 48; ch[i++] = (int32_t)(num) % 100 / 10 + 48; ch[i++] = (int32_t)(num) % 10 + 48; } else if (num >= 1000) { ch[i++] = (int32_t)(num) % 10000 / 1000 + 48; ch[i++] = (int32_t)(num) % 1000 / 100 + 48; ch[i++] = (int32_t)(num) % 100 / 10 + 48; ch[i++] = (int32_t)(num) % 10 + 48; } else if (num >= 100) { ch[i++] = (int32_t)(num) % 1000 / 100 + 48; ch[i++] = (int32_t)(num) % 100 / 10 + 48; ch[i++] = (int32_t)(num) % 10 + 48; } else if (num >= 10) { ch[i++] = (int32_t)(num) % 100 / 10 + 48; ch[i++] = (int32_t)(num) % 10 + 48; } else if (num >= 0) { ch[i++] = (int32_t)(num) % 10 + 48; } if (dot_num > 0 && i < 7) { ch[i++] = '.'; num = num - (int32_t)num; if (dot_num == 1 && i < 8) { num = num * 10; ch[i++] = (int32_t)(num + 0.5) % 10 + 48; } if (dot_num >= 2 && i < 8) { num = num * 100; ch[i++] = (int32_t)num % 100 / 10 + 48; if (i < 8) ch[i++] = (int32_t)(num + 0.5) % 10 + 48; } } while (ch[j] != '\0') { c = ch[j] - 32; if (x > 120) { x = 0; y++; } for (i = 0; i < 6; i++) _buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i]; x += 6; j++; } } /** * @brief 在SSD1306 OLED屏幕上显示字符串和数字 * * 该函数用于在SSD1306 OLED屏幕上显示字符串和数字。首先显示一个字符串, * 然后显示一个浮点数。字符串和数字按照指定的位置和单位显示。 * * @param x 起始位置的x坐标 * @param y 起始位置的y坐标 * @param ch 要显示的字符串 * @param unit 数字的单位,例如'm'表示米 * @param num 要显示的浮点数 */ void ssd1306_f6x8_string_number(uint8_t x, uint8_t y, const uint8_t *ch, uint8_t unit, float32 num) { uint8_t c = 0, i = 0, j = 0; int8_t a, number[7] = {0, 0, 0, -2, 0, 0, 0}; uint32_t d; while (ch[j] != '\0') { c = ch[j] - 32; if (x > 126) { x = 0; y++; } for (i = 0; i < 6; i++) _buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i]; x += 6; j++; } d = 1000 * num; for (a = 0; a < 3; a++) { number[6 - a] = d % 10; d = d / 10; } for (a = 4; a < 7; a++) { number[6 - a] = d % 10; d = d / 10; } if (num >= 100) { a = 0; } else if (num >= 10) { a = 1; } else if (num >= 0) { a = 2; } for (; a < 7; a++) { c = number[a] + 16; if (x > 126) { x = 0; y++; } for (i = 0; i < 6; i++) _buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i]; x += 6; j++; } for (int h = 0; h < 7; h++) { c = unit - 32; for (i = 0; i < 6; i++) _buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i]; } } /** * @brief 在SSD1306 OLED显示屏上显示8x16大小的字符串 * * 该函数使用8x16字体在SSD1306 OLED显示屏上显示指定的字符串。字符串的字符位置由x和y参数指定。 * * @param x 显示字符串的起始x坐标 * @param y 显示字符串的起始y坐标 * @param str 要显示的字符串 */ void ssd1306_f8x16_string(uint8_t x, uint8_t y, const uint8_t *ch) { uint8_t c = 0, i = 0, j = 0; while (ch[j] != '\0') { c = ch[j] - 32; if (x > 120) { x = 0; y++; } for (i = 0; i < 8; i++) _buffer[(y * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i]; for (i = 0; i < 8; i++) _buffer[((y + 1) * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i + 8]; x += 8; j++; } } /** * @brief 在SSD1306 OLED显示屏上以8x16像素字体显示浮点数 * * 在指定的坐标位置 (x, y) 上,使用8x16像素大小的字体显示浮点数 num,并显示指定数量的小数点 dot_num。 * * @param x 显示位置的x坐标 * @param y 显示位置的y坐标 * @param num 要显示的浮点数 * @param dot_num 要显示的小数点数量 */ void ssd1306_f8x16_number(uint8_t x, uint8_t y, float32 num, uint8_t dot_num) { uint8_t ch[9] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'}; uint8_t c = 0, i = 0, j = 0; if (num < 0) { ch[i++] = '-'; num = -num; } if (num > 32000) return; c = 8 - i; if (num >= 10000) { ch[i++] = num / 10000 + 48; ch[i++] = (int32_t)(num) % 10000 / 1000 + 48; ch[i++] = (int32_t)(num) % 1000 / 100 + 48; ch[i++] = (int32_t)(num) % 100 / 10 + 48; ch[i++] = (int32_t)(num) % 10 + 48; } else if (num >= 1000) { ch[i++] = (int32_t)(num) % 10000 / 1000 + 48; ch[i++] = (int32_t)(num) % 1000 / 100 + 48; ch[i++] = (int32_t)(num) % 100 / 10 + 48; ch[i++] = (int32_t)(num) % 10 + 48; } else if (num >= 100) { ch[i++] = (int32_t)(num) % 1000 / 100 + 48; ch[i++] = (int32_t)(num) % 100 / 10 + 48; ch[i++] = (int32_t)(num) % 10 + 48; } else if (num >= 10) { ch[i++] = (int32_t)(num) % 100 / 10 + 48; ch[i++] = (int32_t)(num) % 10 + 48; } else if (num >= 0) { ch[i++] = (int32_t)(num) % 10 + 48; } if (dot_num > 0 && i < 7) { ch[i++] = '.'; num = num - (int32_t)num; if (dot_num == 1 && i < 8) { num = num * 10; ch[i++] = (int32_t)(num + 0.5) % 10 + 48; } if (dot_num >= 2 && i < 8) { num = num * 100; ch[i++] = (int32_t)num % 100 / 10 + 48; if (i < 8) ch[i++] = (int32_t)(num + 0.5) % 10 + 48; } } while (ch[j] != '\0') { c = ch[j] - 32; if (x > 120) { x = 0; y++; } for (i = 0; i < 8; i++) _buffer[(y * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i]; for (i = 0; i < 8; i++) _buffer[((y + 1) * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i + 8]; x += 8; j++; } } // 在 SSD1306 显示屏上绘制一个像素 void ssd1306_draw_pixel(uint8_t x, uint8_t y, uint8_t color) { if (x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT) { // 超出屏幕范围 return; } // 设置像素颜色 if (color == SSD1306_WHITE) { _buffer[x + (y / 8) * SSD1306_WIDTH] |= 1 << (y % 8); } else { _buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8)); } } // 在 SSD1306 显示屏上绘制一条线 void ssd1306_draw_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color) { int16_t dx, dy, sx, sy, err, e2; dx = ABS(x2 - x1); dy = ABS(y2 - y1); sx = (x1 < x2) ? 1 : -1; sy = (y1 < y2) ? 1 : -1; err = dx - dy; while (1) { ssd1306_draw_pixel(x1, y1, color); if (x1 == x2 && y1 == y2) break; e2 = err * 2; if (e2 > -dy) { err -= dy; x1 += sx; } if (e2 < dx) { err += dx; y1 += sy; } } } // 在 SSD1306 显示屏上绘制一个矩形 void ssd1306_draw_rect_angle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) { // 绘制矩形的四条边 ssd1306_draw_line(x, y, x + w, y, color); // 上边 ssd1306_draw_line(x, y + h, x + w, y + h, color); // 下边 ssd1306_draw_line(x, y, x, y + h, color); // 左边 ssd1306_draw_line(x + w, y, x + w, y + h, color); // 右边 } // 在 SSD1306 显示屏上绘制一个填充矩形 void ssd1306_fill_rect_angle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) { for (uint8_t i = 0; i < h; i++) { ssd1306_draw_line(x, y + i, x + w, y + i, color); } } // 绘制进度条 void ssd1306_draw_progress_bar(uint8_t progress) { uint8_t offset_y = 10; char progress_text[5]; // 用于存储百分比文本 // 绘制边框 ssd1306_draw_rect_angle(10, 24 + offset_y, 108, 10, SSD1306_WHITE); // 绘制进度条 ssd1306_fill_rect_angle(12, 26 + offset_y, 4 + progress, 7, SSD1306_WHITE); // 显示百分比文本 snprintf(progress_text, sizeof(progress_text), "%3d%%", progress); ssd1306_f8x16_string(SSD1306_WIDTH * 0.35, 2, (const uint8_t *)progress_text); // 更新显示 ssd1306_update_screen(); } // 在中间显示文字 void ssd1306_draw_text_center(uint8_t y, const char *text) { uint8_t x = (SSD1306_WIDTH - strlen(text) * 6) / 2; ssd1306_f6x8_string(x, y, (const uint8_t *)text); // 更新显示 ssd1306_update_screen(); }