C51 COMPILER V9.54 SSD1306 09/19/2022 22:36:48 PAGE 1 C51 COMPILER V9.54, COMPILATION OF MODULE SSD1306 OBJECT MODULE PLACED IN .\Objects\ssd1306.obj COMPILER INVOKED BY: D:\Keil5 C51\C51\BIN\C51.EXE ssd1306.c OPTIMIZE(8,SPEED) BROWSE DEBUG OBJECTEXTEND PRINT(.\Listings -\ssd1306.lst) TABS(2) OBJECT(.\Objects\ssd1306.obj) line level source 1 /* 2 ssd1306.c 3 4 Driver for SSD1306 IC with SPI Interface 5 6 Copyright (c) 2020 Creative Lau (creativelaulab@gmail.com) 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in all 16 copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 SOFTWARE. 25 26 Note: 27 28 版本:V0.2 29 作者:老刘爱捣鼓 30 时间:2020-04-24 31 老刘爱捣鼓(全网同名)期待您的关注! 32 33 说明: 34 为Mini DSO这个项目临时编写的SSD1306 128x64驱动,并不完善 35 有写字符,字符串,数字,16x16中文字符,画水平线,垂直线,任意两点线段,绘制图片等功能 36 主要参考了Arduino中Adafruit SSD1306的库函数 37 采用全屏buf驱动,需占用128x8个uint8内存空间 38 全屏缓存操控屏幕内容比较方便,刷新速度快,但对单片机的内存大小有要求 39 F6x8字体来自中景园电子的DEMO 40 41 2020-04-30 42 1. 更新OLED_Draw_Byte函数,修正以覆盖方式跨页写入时会同时修改两页内容,上下页的其他字符被覆盖,现在可 -以在任意点写入字符,不会影响上下页的内容 43 2. 优化算法/8改为>>3,%8改为&7 44 3. 修正OLED初始化错误,行模式要设置0x21和0x22设置显示范围,并用0x40设置起始行, 45 0xB0-0xB7设置起始页是页面模式专用,在行模式下使用会造成设置的起始页第一次到达结尾时无法自动换页 46 4. 删除OLED_Set_Pos中多余的设置内存位置命令 47 5. 画线或像素时,置位OLED_Reverse则进行擦除 48 */ 49 #include "ssd1306.h" *** WARNING C318 IN LINE 33 OF ssd1306.h: can't open file 'delay.h' 50 #include "ssd1306font.h" *** WARNING C318 IN LINE 50 OF ssd1306.c: can't open file 'ssd1306font.h' 51 C51 COMPILER V9.54 SSD1306 09/19/2022 22:36:48 PAGE 2 52 //OLED的显存 53 //存放格式如下. 54 //[0]0 1 2 3 ... 127 55 //[1]0 1 2 3 ... 127 56 //[2]0 1 2 3 ... 127 57 //[3]0 1 2 3 ... 127 58 //[4]0 1 2 3 ... 127 59 //[5]0 1 2 3 ... 127 60 //[6]0 1 2 3 ... 127 61 //[7]0 1 2 3 ... 127 62 63 #define uint8 unsigned char; *** WARNING C317 IN LINE 63 OF ssd1306.c: attempt to redefine macro 'uint8' 64 #define uint16 unsigned int; *** WARNING C317 IN LINE 64 OF ssd1306.c: attempt to redefine macro 'uint16' 65 66 #ifndef _swap_char 67 #define _swap_char(a, b) \ 68 { \ 69 uint8 t = a; \ 70 a = b; \ 71 b = t; \ 72 } 73 #endif 74 75 bit _OLED_Reverse = 0; 76 bit _OLED_Overlap = 1; 77 uint8 _buf[WIDTH * PAGES]; //全屏缓存,横向WIDTH个像素,纵向PAGES页,页内每8个像素作为一个字节,共WIDTH * P -AGES个字节 78 79 static char _x, _y; 80 static uint8 _Font_Width = 6; 81 82 83 84 /* 绘制一个像素至缓存 85 Draw one pixel to buffer */ 86 void OLED_DrawPixel(uint8 x, uint8 y) 87 { 88 1 uint8 mask; 89 1 uint8 *pBuf; 90 1 91 1 if (_x > WIDTH - 1) 92 1 { 93 2 _x = 0; 94 2 _y += 1; 95 2 } 96 1 if (_y > HEIGHT - 1) 97 1 { 98 2 _y = 0; 99 2 } 100 1 101 1 pBuf = &_buf[(y >> 3) * WIDTH + x]; 102 1 mask = 1 << (y & 7); 103 1 if (_OLED_Reverse) 104 1 { 105 2 *pBuf++ &= ~mask; 106 2 } 107 1 else 108 1 { 109 2 *pBuf++ |= mask; 110 2 } C51 COMPILER V9.54 SSD1306 09/19/2022 22:36:48 PAGE 3 111 1 } 112 113 114 /* 绘制两点线段至缓存 115 Draw line between two points to buffer */ 116 void OLED_DrawLine(uint8 x0, uint8 y0, uint8 x1, uint8 y1) 117 { 118 1 char dx, dy, ystep; 119 1 int err; 120 1 bit swapxy = 0; 121 1 122 1 if (x0 > WIDTH - 1) 123 1 x0 = WIDTH - 1; 124 1 125 1 if (y0 > HEIGHT - 1) 126 1 y0 = HEIGHT - 1; 127 1 128 1 if (x1 > WIDTH - 1) 129 1 x1 = WIDTH - 1; 130 1 131 1 if (y1 > HEIGHT - 1) 132 1 y1 = HEIGHT - 1; 133 1 134 1 dx = abs(x1 - x0); 135 1 dy = abs(y1 - y0); 136 1 137 1 if (dy > dx) 138 1 { 139 2 swapxy = 1; 140 2 _swap_char(dx, dy); 141 2 _swap_char(x0, y0); 142 2 _swap_char(x1, y1); 143 2 } 144 1 145 1 if (x0 > x1) 146 1 { 147 2 _swap_char(x0, x1); 148 2 _swap_char(y0, y1); 149 2 } 150 1 151 1 err = dx >> 1; 152 1 153 1 if (y0 < y1) 154 1 { 155 2 ystep = 1; 156 2 } 157 1 else 158 1 { 159 2 ystep = -1; 160 2 } 161 1 162 1 for (; x0 <= x1; x0++) 163 1 { 164 2 if (swapxy == 0) 165 2 OLED_DrawPixel(x0, y0); 166 2 else 167 2 OLED_DrawPixel(y0, x0); 168 2 169 2 err -= dy; 170 2 171 2 if (err < 0) 172 2 { C51 COMPILER V9.54 SSD1306 09/19/2022 22:36:48 PAGE 4 173 3 y0 += ystep; 174 3 err += dx; 175 3 } 176 2 } 177 1 } 178 179 /* 绘制垂直线至缓存 180 Draw vertical line to buffer*/ 181 void OLED_DrawVLine(uint8 x, uint8 y, uint8 w) 182 { 183 1 uint8 mask; 184 1 uint8 *pBuf; 185 1 186 1 if (x > WIDTH - 1) 187 1 x = WIDTH - 1; 188 1 189 1 if (y + w > HEIGHT) 190 1 w = HEIGHT - y; 191 1 192 1 while (w--) 193 1 { 194 2 pBuf = &_buf[(y >> 3) * WIDTH + x]; 195 2 mask = 1 << (y & 7); 196 2 if (_OLED_Reverse) 197 2 { 198 3 *pBuf++ &= ~mask; 199 3 } 200 2 else 201 2 { 202 3 *pBuf++ |= mask; 203 3 } 204 2 y++; 205 2 } 206 1 } 207 208 /* 绘制水平线至缓存 209 Draw horizontal line to buffer */ 210 void OLED_DrawHLine(uint8 x, uint8 y, uint8 w) 211 { 212 1 uint8 *pBuf; 213 1 uint8 mask; 214 1 215 1 if (x + w > WIDTH) 216 1 w = WIDTH - x; 217 1 218 1 if (y > HEIGHT - 1) 219 1 y = HEIGHT - 1; 220 1 221 1 pBuf = &_buf[(y >> 3) * WIDTH + x]; 222 1 mask = 1 << (y & 7); 223 1 224 1 while (w--) 225 1 { 226 2 if (_OLED_Reverse) 227 2 { 228 3 *pBuf++ &= ~mask; 229 3 } 230 2 else 231 2 { 232 3 *pBuf++ |= mask; 233 3 } 234 2 } C51 COMPILER V9.54 SSD1306 09/19/2022 22:36:48 PAGE 5 235 1 } 236 237 238 /* 将缓存内容显示到屏幕上 239 Send buffer to display */ 240 void OLED_Display(void) 241 { 242 1 uint8 i, j; 243 1 uint8 *pBuf; 244 1 pBuf = _buf; 245 1 246 1 for (j = 0; j < PAGES; j++) 247 1 { 248 2 for (i = 0; i < WIDTH; i++) 249 2 { 250 3 OLED_Write_Data(*pBuf++); *** WARNING C206 IN LINE 250 OF ssd1306.c: 'OLED_Write_Data': missing function-prototype *** ERROR C267 IN LINE 250 OF ssd1306.c: 'OLED_Write_Data': requires ANSI-style prototype 251 3 } 252 2 } 253 1 } 254 255 /* 初始化SSD1306 256 Initialize SSD1306 */ 257 void OLED_Init(void) 258 { 259 1 OLED_RST_Set(); *** ERROR C202 IN LINE 259 OF ssd1306.c: 'OLED_RST': undefined identifier 260 1 Delay50ms(); 261 1 OLED_RST_Clr(); 262 1 Delay50ms(); 263 1 OLED_RST_Set(); 264 1 265 1 OLED_Write_Command(0xAE); //--Turn off oled panel 266 1 267 1 /* 268 1 以下三条命令是给页面模式用的,行模式和列模式不要设置,会引起问题 269 1 行模式或列模式,要用0x21和0x22设置范围 270 1 Following three commands are for Page Addressing Mode. Do not set them in Horizontal addressing mo -de or Vertical addressing mode, will rise problem. 271 1 For Horizontal addressing mode or Vertical addressing mode, should use 0x21 and 0x22 set column an -d page address 272 1 */ 273 1 // OLED_Write_Command(0x00); //-Set Lower Column Start Address for Page Addressing Mode 274 1 // OLED_Write_Command(0x10); //-Set Higher Column Start Address for Page Addressing Mode 275 1 // OLED_Write_Command(0xB0); //-Set the page start address of the target display location by command f -or Page Addressing Mode 276 1 277 1 OLED_Write_Command(0x20); //-Set Page Addressing Mode (0x00/0x01/0x02) 278 1 OLED_Write_Command(0x00); //--0x00: Horizontal addressing mode, 0x01: Vertical addressing mode, 0x02: -Page addressing mode 279 1 280 1 OLED_Write_Command(0x21); //-Set Column Address 281 1 OLED_Write_Command(0x00); //--Start address 282 1 OLED_Write_Command(0x7f); //--End address 283 1 284 1 OLED_Write_Command(0x22); //-Set Page Address 285 1 OLED_Write_Command(0x00); //---Start address 286 1 OLED_Write_Command(0x07); //--End address 287 1 288 1 OLED_Write_Command(0x40); //-Set Display Start Line (0x40h~0x7F) 289 1 C51 COMPILER V9.54 SSD1306 09/19/2022 22:36:48 PAGE 6 290 1 OLED_Write_Command(0x81); //-Set Contrast Control for BANK0 291 1 OLED_Write_Command(OLED_Brightness * 10); // -0x00 to 0xFF, The segment output current increases as - the contrast step value increases 292 1 293 1 OLED_Write_Command(0xA1); //-Set Segment Re-map. 0xA1: Normal, 0xA0: Re-map left and right 294 1 OLED_Write_Command(0xC8); //-Set COM Output Scan Direction. 0xC8: Normal, 0xC0: Re-map up and down 295 1 OLED_Write_Command(0xA6); //-Set Normal/Inverse Display, 0xA6:Normal, 0xA7: Inverse 296 1 297 1 OLED_Write_Command(0xA8); //-Set Multiplex Ratio (16~63) 298 1 OLED_Write_Command(0x3F); //--63 multiplex mode 299 1 300 1 OLED_Write_Command(0xD3); //-Set Display Offset (0x00~0x3F) 301 1 OLED_Write_Command(0x00); //--No offset 302 1 303 1 OLED_Write_Command(0xD5); //-Set display clock divide ratio/oscillator frequency 304 1 OLED_Write_Command(0x20); //--Set Clock as 60 Frames/Sec 305 1 306 1 OLED_Write_Command(0xD9); //-Set pre-charge period 307 1 OLED_Write_Command(0xF2); //--Set Pre-Charge as 15 Clocks & Discharge as 2 Clock 308 1 309 1 OLED_Write_Command(0xDA); //-Set com pins hardware configuration 310 1 OLED_Write_Command(0x12); // 311 1 312 1 OLED_Write_Command(0xDB); //-Set VCOM Deselect Level 313 1 OLED_Write_Command(0x30); //--0.83xVcc 314 1 315 1 OLED_Write_Command(0x8D); //-Set Charge Pump enable/disable 316 1 OLED_Write_Command(0x14); //--0x14: Enable, 0x10: Disable 317 1 318 1 OLED_Write_Command(0xA4); //-Entire Display ON, 0xA4: Disable, 0xA5: Enable 319 1 OLED_Write_Command(0xAF); //-Turn on oled panel 320 1 } C51 COMPILATION COMPLETE. 5 WARNING(S), 2 ERROR(S)