#include "bsp_oled_sh1106.h" #include #include #include "FreeRTOS.h" #include "semphr.h" #include "elog.h" #include "heap.h" #define BSP_OLED_WRITE_DATA 0x40 #define BSP_OLED_WRITE_CMD 0x00 static const char *TAG = "bsp_oled"; static const uint8_t OLED_FONT6x8[94][6]; static const uint8_t OLED_FONT8x16[94][16]; static const uint8_t OLED_INIT_REGS[23]; static SemaphoreHandle_t bsp_oled_i2c_tx_semphr = NULL; static I2C_HandleTypeDef *bsp_oled_i2c_handle = NULL; static uint8_t *bsp_oled_frame_buffer = NULL; static uint32_t bsp_oled_updated_line = 0xFF; static HAL_StatusTypeDef bsp_oled_send_cmd(const uint8_t *cmd_buf, uint8_t cmd_len); static HAL_StatusTypeDef bsp_oled_send_dat(const uint8_t *dat_buf, uint16_t dat_len); static HAL_StatusTypeDef bsp_oled_set_cursor(uint8_t column, uint8_t page); static void bsp_oled_6x8_char(uint8_t y, uint8_t x, char ch); static void bsp_oled_8x16_char(uint8_t y, uint8_t x, char ch); void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c) { BaseType_t higher_task_woken = pdFALSE; higher_task_woken |= bsp_oled_i2c_tx_done_cb(hi2c); portYIELD_FROM_ISR(higher_task_woken); } BaseType_t bsp_oled_i2c_tx_done_cb(I2C_HandleTypeDef *hi2c) { BaseType_t higher_task_woken = pdFALSE; if (hi2c == bsp_oled_i2c_handle && bsp_oled_i2c_tx_semphr != NULL) { xSemaphoreGiveFromISR(bsp_oled_i2c_tx_semphr, &higher_task_woken); } return higher_task_woken; } /** * @brief 内部函数,向OLED写入命令 * * @param cmd_buf 指向存放命令的缓冲区 * @param cmd_len 要发送命令的长度 * * @return 错误代码 */ static HAL_StatusTypeDef bsp_oled_send_cmd(const uint8_t *cmd_buf, uint8_t cmd_len) { if (bsp_oled_i2c_handle == NULL) { elog_error(TAG, "i2c handle is null, call bsp_oled_init first"); return HAL_ERROR; } HAL_StatusTypeDef status = HAL_I2C_Mem_Write(bsp_oled_i2c_handle, BSP_OLED_I2C_ADDRESS << 1, BSP_OLED_WRITE_CMD, 1, (uint8_t*)cmd_buf, cmd_len, BSP_OLED_I2C_TIMEOUT); if (status != HAL_OK) { elog_error(TAG, "error while writing register"); } return status; } /** * @brief 内部函数,向OLED写入数据 * * @param cmd_buf 指向存放数据的缓冲区 * @param cmd_len 要发送数据的长度 * * @return 错误代码 */ static HAL_StatusTypeDef bsp_oled_send_dat(const uint8_t *dat_buf, uint16_t dat_len) { if (bsp_oled_i2c_handle == NULL) { elog_error(TAG, "i2c handle is null, call bsp_oled_init first"); return HAL_ERROR; } HAL_StatusTypeDef status = HAL_I2C_Mem_Write_DMA(bsp_oled_i2c_handle, BSP_OLED_I2C_ADDRESS << 1, BSP_OLED_WRITE_DATA, 1, (uint8_t*)dat_buf, dat_len); if (status != HAL_OK) { elog_error(TAG, "error while writing data"); } xSemaphoreTake(bsp_oled_i2c_tx_semphr, portMAX_DELAY); //等待传输完成 return status; } /** * @brief 内部函数,设置OLED页写入模式的显示位置 * * @param column 下一次写入时光标的横向位置,取值0-127 * @param page 下一次写入时光标的纵向Column,取值0-7 * * @return 错误代码 */ static HAL_StatusTypeDef bsp_oled_set_cursor(uint8_t column, uint8_t page) { uint8_t cmds[3]; cmds[0] = 0xB0 + page; //设定page cmds[1] = 0x0F & column; //设定column的高四位 cmds[2] = 0x10 + (column >> 4); //设定column的低四位 return bsp_oled_send_cmd(cmds, sizeof(cmds)); } /** * @brief 初始化OLED * * @return 错误代码 */ HAL_StatusTypeDef bsp_oled_init(I2C_HandleTypeDef *hi2c) { if (hi2c == NULL) { elog_error(TAG, "hi2c handle is null"); return HAL_ERROR; } bsp_oled_i2c_handle = hi2c; HAL_StatusTypeDef ret = bsp_oled_send_cmd((uint8_t*)OLED_INIT_REGS, sizeof(OLED_INIT_REGS)); if(ret != HAL_OK) { elog_error(TAG, "error while initializing registers"); goto ERROR; } bsp_oled_frame_buffer = malloc_ahb(BSP_OLED_X * BSP_OLED_Y); if(bsp_oled_frame_buffer == NULL) { elog_error(TAG, "error while allocating oled frame buffer"); ret = HAL_ERROR; goto ERROR; } bsp_oled_i2c_tx_semphr = xSemaphoreCreateBinary(); if(bsp_oled_i2c_tx_semphr == NULL) { elog_error(TAG, "error while creating oled i2c tx semphr"); ret = HAL_ERROR; goto ERROR; } bsp_oled_clear_fb(); elog_info(TAG, "oled initialized"); return ret; ERROR: free_ahb(bsp_oled_frame_buffer); if (bsp_oled_i2c_tx_semphr) { vSemaphoreDelete(bsp_oled_i2c_tx_semphr); } bsp_oled_i2c_handle = NULL; bsp_oled_frame_buffer = NULL; bsp_oled_i2c_tx_semphr = NULL; return ret; } /** * @brief 内部函数,在OLED上显示一个6x8的字符 * * @param y 纵向显示的Column,取值为0-7 * @param x 横向显示的位置,取值为0-127 * @param ch 要显示的字符的ASCII码 * * @return 错误代码 */ static void bsp_oled_6x8_char(uint8_t y, uint8_t x, char ch) { if (bsp_oled_frame_buffer == NULL) { elog_error(TAG, "bsp_oled_6x8_char: oled frame buffer is null, call bsp_oled_init first"); return; } if (y >= BSP_OLED_Y || x >= BSP_OLED_X) { elog_error(TAG, "bsp_oled_6x8_char: invalid position"); return; } #ifdef BSP_OLED_CONTROLLER_SH1106 x += 2; //SH1106需要额外的显示偏移 #endif memcpy(&bsp_oled_frame_buffer[y * BSP_OLED_X + x], &OLED_FONT6x8[(uint8_t)ch - 32][0], sizeof(OLED_FONT6x8[0])); bsp_oled_updated_line |= 1 << y; } /** * @brief 内部函数,在OLED上显示一个8x16的字符 * * @param y 纵向显示的Column,取值为0-7 * @param x 横向显示的位置,取值为0-127 * @param ch 要显示的字符的ASCII码 * * @return 错误代码 */ static void bsp_oled_8x16_char(uint8_t y, uint8_t x, char ch) { if (bsp_oled_frame_buffer == NULL) { elog_error(TAG, "bsp_oled_8x16_char: oled frame buffer is null, call bsp_oled_init first"); return; } if (y >= BSP_OLED_Y || x >= BSP_OLED_X) { elog_error(TAG, "bsp_oled_8x16_char: invalid position"); return; } #ifdef BSP_OLED_CONTROLLER_SH1106 x += 2; //SH1106需要额外的显示偏移 #endif memcpy(&bsp_oled_frame_buffer[y * BSP_OLED_X + x], &OLED_FONT8x16[(uint8_t)ch - 32][0], sizeof(OLED_FONT8x16[0]) / 2); bsp_oled_updated_line |= 1 << y; memcpy(&bsp_oled_frame_buffer[++y * BSP_OLED_X + x], &OLED_FONT8x16[(uint8_t)ch - 32][8], sizeof(OLED_FONT8x16[0]) / 2); bsp_oled_updated_line |= 1 << y; } /** * @brief 清空OLED的显存 * * @return 错误代码 */ void bsp_oled_clear_fb(void) { if (bsp_oled_frame_buffer == NULL) { return; } memset(bsp_oled_frame_buffer, 0, BSP_OLED_X * BSP_OLED_Y); bsp_oled_updated_line = 0xFF; } /** * @brief 在OLED上显示6x8的字符串 * * @param y 字符串起始的纵向Column,取值为0-7 * @param x 字符串起始的横向位置,取值为0-127 * @param str 要显示的字符串 * * @return 错误代码 */ void bsp_oled_6x8(uint8_t y, uint8_t x, const char *str) { if (str == NULL) { elog_error(TAG, "bsp_oled_6x8: invalid str pointer"); return; } while (*str != '\0') { if (x > BSP_OLED_X - 6 || *str == '\n') { x = 0; ++ y; if (y >= BSP_OLED_Y) { break; } } else if (*str < 32 || *str > 127) { continue; } bsp_oled_6x8_char(y, x, *str); x += 6; ++ str; } } /** * @brief 在OLED上显示8x16的字符串 * * @param y 字符串起始的纵向Column,取值为0-7 * @param x 字符串起始的横向位置,取值为0-127 * @param str 要显示的字符串 * * @return 错误代码 */ void bsp_oled_8x16(uint8_t y, uint8_t x, const char *str) { if (str == NULL) { elog_error(TAG, "bsp_oled_8x16: invaldid str pointer"); return; } while (*str) { if (x > BSP_OLED_X-8 || *str == '\n') { x = 0; y += 2; if (y >= BSP_OLED_Y) { break; } } else if (*str < 32 || *str > 127) { continue; } bsp_oled_8x16_char(y, x, *str); x += 8; ++ str; } } HAL_StatusTypeDef bsp_oled_update(void) { HAL_StatusTypeDef status = HAL_OK; for (uint8_t line = 0; line < BSP_OLED_Y; line ++) { if (bsp_oled_updated_line & (1 << line)) { #ifdef BSP_OLED_CONTROLLER_SH1106 status = bsp_oled_set_cursor(2, line); //SH1106需要额外的显示偏移 #else status = bsp_oled_set_cursor(0, line); //SH1106需要额外的显示偏移 #endif if (status != HAL_OK) { elog_error(TAG, "oled update: error while setting cursor"); break; } status = bsp_oled_send_dat(bsp_oled_frame_buffer + line * BSP_OLED_X, BSP_OLED_X); if (status != HAL_OK) { elog_error(TAG, "oled update: error while sending framebuffer"); break; } } } bsp_oled_updated_line = 0; return status; } /** * @brief 6*8的点阵字库 * */ static const uint8_t OLED_FONT6x8[94][6] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ' ' {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}, // '\' {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 {0x00, 0x08, 0x3E, 0x41, 0x00, 0x00}, // { {0x00, 0x00, 0x7F, 0x00, 0x00, 0x00}, // | {0x00, 0x00, 0x41, 0x3E, 0x08, 0x00}, // } }; /** * @brief 8*16的点阵字库 * */ static const uint8_t OLED_FONT8x16[94][16] = { {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ' ' {0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00}, // ! {0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // " {0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00}, // # {0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00}, // $ {0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00}, // % {0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10}, // & {0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ' {0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00}, // ( {0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00}, // ) {0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00}, // * {0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00}, // + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00}, // , {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, // - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00}, // . {0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00}, // / {0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00}, // 0 {0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00}, // 1 {0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00}, // 2 {0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00}, // 3 {0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00}, // 4 {0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00}, // 5 {0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00}, // 6 {0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00}, // 7 {0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00}, // 8 {0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00}, // 9 {0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00}, // : {0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00}, // ; {0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00}, // < {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00}, // = {0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00}, // > {0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00}, // ? {0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00}, // @ {0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20}, // A {0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00}, // B {0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00}, // C {0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00}, // D {0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00}, // E {0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00}, // F {0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00}, // G {0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20}, // H {0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00}, // I {0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00}, // J {0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00}, // K {0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00}, // L {0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00}, // M {0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00}, // N {0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00}, // O {0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00}, // P {0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00}, // Q {0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20}, // R {0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00}, // S {0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00}, // T {0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00}, // U {0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00}, // V {0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00}, // W {0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20}, // X {0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00}, // Y {0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00}, // Z {0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00}, // [ {0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00}, // '\' {0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00}, // ] {0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ^ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80}, // _ {0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ` {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20}, // a {0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00}, // b {0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00}, // c {0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20}, // d {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00}, // e {0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00}, // f {0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00}, // g {0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20}, // h {0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00}, // i {0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00}, // j {0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00}, // k {0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00}, // l {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F}, // m {0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20}, // n {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00}, // o {0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00}, // p {0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80}, // q {0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00}, // r {0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00}, // s {0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00}, // t {0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20}, // u {0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00}, // v {0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00}, // w {0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00}, // x {0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00}, // y {0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00}, // z {0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40}, // { {0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00}, // | {0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00}, // } }; #ifdef BSP_OLED_CONTROLLER_SH1106 static const uint8_t OLED_INIT_REGS[23] = { 0xA1, //左右不反置(0xA0左右反置 0xA1正常) 0xC8, //上下不反置(0xC0上下反置 0xC8正常) 0xA6, //不反显(A6正常,A7反显) 0xA4, //正常显示(A4正常显示 A5全屏亮) 0x40, //显示RAM第0行对应纵向COM1(硬件连接的起始) 0x33, //设定内置电荷泵电压为9v 0x81, 0x80, //设置亮度为最高 0xA8, 0x3F, //设置刷新率倍数 默认值1/64 0xAD, 0x8B, //使用DC-DC模式 0xD3, 0x00, //设置显示偏移 不偏移(0-63) 0xD5, 0x80, //振荡器和分频 低四位为分频比率,高四位为振荡器频率 0xD9, 0x22, //设定预充电 预充电2时钟周期,放电2时钟周期 0xDA, 0x01, //设定管脚排列为默认顺序 0xDB, 0x40, //设定列驱动电流级别为默认值 0xAF //开显示 }; #endif