SSD1306 Example I2C communication without library
thanks to this forum https://www.ccsinfo.com/forum/viewtopic.php?t=52836
main.cpp@0:cf50c95c11c5, 2017-11-22 (annotated)
- Committer:
- kohlerba
- Date:
- Wed Nov 22 21:33:27 2017 +0000
- Revision:
- 0:cf50c95c11c5
SSD1306;
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| kohlerba | 0:cf50c95c11c5 | 1 | #include "mbed.h" |
| kohlerba | 0:cf50c95c11c5 | 2 | |
| kohlerba | 0:cf50c95c11c5 | 3 | #define DISPLAY_RESET D0 |
| kohlerba | 0:cf50c95c11c5 | 4 | |
| kohlerba | 0:cf50c95c11c5 | 5 | #define SSD1306_LCDWIDTH 128 |
| kohlerba | 0:cf50c95c11c5 | 6 | #define SSD1306_LCDHEIGHT 64 |
| kohlerba | 0:cf50c95c11c5 | 7 | #define SSD1306_SETCONTRAST 0x81 |
| kohlerba | 0:cf50c95c11c5 | 8 | #define SSD1306_DISPLAYALLON_RESUME 0xA4 |
| kohlerba | 0:cf50c95c11c5 | 9 | #define SSD1306_DISPLAYALLON 0xA5 |
| kohlerba | 0:cf50c95c11c5 | 10 | #define SSD1306_NORMALDISPLAY 0xA6 |
| kohlerba | 0:cf50c95c11c5 | 11 | #define SSD1306_INVERTDISPLAY 0xA7 |
| kohlerba | 0:cf50c95c11c5 | 12 | #define SSD1306_DISPLAYOFF 0xAE |
| kohlerba | 0:cf50c95c11c5 | 13 | #define SSD1306_DISPLAYON 0xAF |
| kohlerba | 0:cf50c95c11c5 | 14 | #define SSD1306_SETDISPLAYOFFSET 0xD3 |
| kohlerba | 0:cf50c95c11c5 | 15 | #define SSD1306_SETCOMPINS 0xDA |
| kohlerba | 0:cf50c95c11c5 | 16 | #define SSD1306_SETVCOMDETECT 0xDB |
| kohlerba | 0:cf50c95c11c5 | 17 | #define SSD1306_SETDISPLAYCLOCKDIV 0xD5 |
| kohlerba | 0:cf50c95c11c5 | 18 | #define SSD1306_SETPRECHARGE 0xD9 |
| kohlerba | 0:cf50c95c11c5 | 19 | #define SSD1306_SETMULTIPLEX 0xA8 |
| kohlerba | 0:cf50c95c11c5 | 20 | #define SSD1306_SETLOWCOLUMN 0x00 |
| kohlerba | 0:cf50c95c11c5 | 21 | #define SSD1306_SETHIGHCOLUMN 0x10 |
| kohlerba | 0:cf50c95c11c5 | 22 | #define SSD1306_SETSTARTLINE 0x40 |
| kohlerba | 0:cf50c95c11c5 | 23 | #define SSD1306_MEMORYMODE 0x20 |
| kohlerba | 0:cf50c95c11c5 | 24 | #define SSD1306_COLUMNADDR 0x21 |
| kohlerba | 0:cf50c95c11c5 | 25 | #define SSD1306_PAGEADDR 0x22 |
| kohlerba | 0:cf50c95c11c5 | 26 | #define SSD1306_COMSCANINC 0xC0 |
| kohlerba | 0:cf50c95c11c5 | 27 | #define SSD1306_COMSCANDEC 0xC8 |
| kohlerba | 0:cf50c95c11c5 | 28 | #define SSD1306_SEGREMAP 0xA0 |
| kohlerba | 0:cf50c95c11c5 | 29 | #define SSD1306_CHARGEPUMP 0x8D |
| kohlerba | 0:cf50c95c11c5 | 30 | #define SSD1306_EXTERNALVCC 0x1 |
| kohlerba | 0:cf50c95c11c5 | 31 | #define SSD1306_SWITCHCAPVCC 0x2 |
| kohlerba | 0:cf50c95c11c5 | 32 | |
| kohlerba | 0:cf50c95c11c5 | 33 | I2C i2c(I2C_SDA, I2C_SCL); |
| kohlerba | 0:cf50c95c11c5 | 34 | |
| kohlerba | 0:cf50c95c11c5 | 35 | char _i2c_address; |
| kohlerba | 0:cf50c95c11c5 | 36 | char display_buffer[1024]; |
| kohlerba | 0:cf50c95c11c5 | 37 | |
| kohlerba | 0:cf50c95c11c5 | 38 | void ssd1306_command(char c){ |
| kohlerba | 0:cf50c95c11c5 | 39 | char control = 0x00; |
| kohlerba | 0:cf50c95c11c5 | 40 | i2c.start(); |
| kohlerba | 0:cf50c95c11c5 | 41 | i2c.write(_i2c_address); |
| kohlerba | 0:cf50c95c11c5 | 42 | i2c.write(control); |
| kohlerba | 0:cf50c95c11c5 | 43 | i2c.write(c); |
| kohlerba | 0:cf50c95c11c5 | 44 | i2c.stop(); |
| kohlerba | 0:cf50c95c11c5 | 45 | } |
| kohlerba | 0:cf50c95c11c5 | 46 | |
| kohlerba | 0:cf50c95c11c5 | 47 | void ssd1306_data(char c){ |
| kohlerba | 0:cf50c95c11c5 | 48 | i2c.start(); |
| kohlerba | 0:cf50c95c11c5 | 49 | i2c.write(_i2c_address); |
| kohlerba | 0:cf50c95c11c5 | 50 | i2c.write(0x40); |
| kohlerba | 0:cf50c95c11c5 | 51 | i2c.write(c); |
| kohlerba | 0:cf50c95c11c5 | 52 | i2c.stop(); |
| kohlerba | 0:cf50c95c11c5 | 53 | } |
| kohlerba | 0:cf50c95c11c5 | 54 | |
| kohlerba | 0:cf50c95c11c5 | 55 | void setColAddress() |
| kohlerba | 0:cf50c95c11c5 | 56 | { |
| kohlerba | 0:cf50c95c11c5 | 57 | ssd1306_command(SSD1306_COLUMNADDR); // 0x21 COMMAND |
| kohlerba | 0:cf50c95c11c5 | 58 | ssd1306_command(0); // Column start address |
| kohlerba | 0:cf50c95c11c5 | 59 | ssd1306_command(SSD1306_LCDWIDTH-1); // Column end address |
| kohlerba | 0:cf50c95c11c5 | 60 | } |
| kohlerba | 0:cf50c95c11c5 | 61 | |
| kohlerba | 0:cf50c95c11c5 | 62 | void setPageAddress() |
| kohlerba | 0:cf50c95c11c5 | 63 | { |
| kohlerba | 0:cf50c95c11c5 | 64 | ssd1306_command(SSD1306_PAGEADDR); // 0x22 COMMAND |
| kohlerba | 0:cf50c95c11c5 | 65 | ssd1306_command(0); // Start Page address |
| kohlerba | 0:cf50c95c11c5 | 66 | ssd1306_command((SSD1306_LCDHEIGHT/8)-1);// End Page address |
| kohlerba | 0:cf50c95c11c5 | 67 | } |
| kohlerba | 0:cf50c95c11c5 | 68 | |
| kohlerba | 0:cf50c95c11c5 | 69 | void TransferBuffer() |
| kohlerba | 0:cf50c95c11c5 | 70 | { |
| kohlerba | 0:cf50c95c11c5 | 71 | int j=0; |
| kohlerba | 0:cf50c95c11c5 | 72 | |
| kohlerba | 0:cf50c95c11c5 | 73 | // set the Column and Page addresses to 0,0 |
| kohlerba | 0:cf50c95c11c5 | 74 | setColAddress(); |
| kohlerba | 0:cf50c95c11c5 | 75 | setPageAddress(); |
| kohlerba | 0:cf50c95c11c5 | 76 | |
| kohlerba | 0:cf50c95c11c5 | 77 | i2c.start(); |
| kohlerba | 0:cf50c95c11c5 | 78 | i2c.write(_i2c_address); |
| kohlerba | 0:cf50c95c11c5 | 79 | i2c.write(0X40); // data not command |
| kohlerba | 0:cf50c95c11c5 | 80 | for(j=0;j<1024;j++) |
| kohlerba | 0:cf50c95c11c5 | 81 | { |
| kohlerba | 0:cf50c95c11c5 | 82 | i2c.write(display_buffer[j]); |
| kohlerba | 0:cf50c95c11c5 | 83 | } |
| kohlerba | 0:cf50c95c11c5 | 84 | |
| kohlerba | 0:cf50c95c11c5 | 85 | i2c.stop(); |
| kohlerba | 0:cf50c95c11c5 | 86 | } |
| kohlerba | 0:cf50c95c11c5 | 87 | |
| kohlerba | 0:cf50c95c11c5 | 88 | void InitializeDisplay() |
| kohlerba | 0:cf50c95c11c5 | 89 | { |
| kohlerba | 0:cf50c95c11c5 | 90 | DigitalOut(DISPLAY_RESET,1); |
| kohlerba | 0:cf50c95c11c5 | 91 | // VDD (3.3V) goes high at start, lets just chill for a ms |
| kohlerba | 0:cf50c95c11c5 | 92 | wait_ms(1); |
| kohlerba | 0:cf50c95c11c5 | 93 | // bring reset low |
| kohlerba | 0:cf50c95c11c5 | 94 | DigitalOut(DISPLAY_RESET,0); |
| kohlerba | 0:cf50c95c11c5 | 95 | // wait 10ms |
| kohlerba | 0:cf50c95c11c5 | 96 | wait_ms(10); |
| kohlerba | 0:cf50c95c11c5 | 97 | // bring out of reset |
| kohlerba | 0:cf50c95c11c5 | 98 | DigitalOut(DISPLAY_RESET,1); |
| kohlerba | 0:cf50c95c11c5 | 99 | // turn on VCC (9V?) |
| kohlerba | 0:cf50c95c11c5 | 100 | |
| kohlerba | 0:cf50c95c11c5 | 101 | // Init sequence for 128x64 OLED module |
| kohlerba | 0:cf50c95c11c5 | 102 | ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE |
| kohlerba | 0:cf50c95c11c5 | 103 | |
| kohlerba | 0:cf50c95c11c5 | 104 | ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5 |
| kohlerba | 0:cf50c95c11c5 | 105 | ssd1306_command(0x80); // the suggested ratio 0x80 |
| kohlerba | 0:cf50c95c11c5 | 106 | |
| kohlerba | 0:cf50c95c11c5 | 107 | ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8 |
| kohlerba | 0:cf50c95c11c5 | 108 | ssd1306_command(0x3F); |
| kohlerba | 0:cf50c95c11c5 | 109 | |
| kohlerba | 0:cf50c95c11c5 | 110 | ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3 |
| kohlerba | 0:cf50c95c11c5 | 111 | ssd1306_command(0x0); // no offset |
| kohlerba | 0:cf50c95c11c5 | 112 | |
| kohlerba | 0:cf50c95c11c5 | 113 | ssd1306_command(SSD1306_SETSTARTLINE);// | 0x0); // line #0 |
| kohlerba | 0:cf50c95c11c5 | 114 | |
| kohlerba | 0:cf50c95c11c5 | 115 | ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D |
| kohlerba | 0:cf50c95c11c5 | 116 | ssd1306_command(0x14); // using internal VCC |
| kohlerba | 0:cf50c95c11c5 | 117 | |
| kohlerba | 0:cf50c95c11c5 | 118 | ssd1306_command(SSD1306_MEMORYMODE); // 0x20 |
| kohlerba | 0:cf50c95c11c5 | 119 | ssd1306_command(0x00); // 0x00 horizontal addressing |
| kohlerba | 0:cf50c95c11c5 | 120 | |
| kohlerba | 0:cf50c95c11c5 | 121 | ssd1306_command(SSD1306_SEGREMAP | 0x1); // rotate screen 180 |
| kohlerba | 0:cf50c95c11c5 | 122 | |
| kohlerba | 0:cf50c95c11c5 | 123 | ssd1306_command(SSD1306_COMSCANDEC); // rotate screen 180 |
| kohlerba | 0:cf50c95c11c5 | 124 | |
| kohlerba | 0:cf50c95c11c5 | 125 | ssd1306_command(SSD1306_SETCOMPINS); // 0xDA |
| kohlerba | 0:cf50c95c11c5 | 126 | ssd1306_command(0x12); |
| kohlerba | 0:cf50c95c11c5 | 127 | |
| kohlerba | 0:cf50c95c11c5 | 128 | ssd1306_command(SSD1306_SETCONTRAST); // 0x81 |
| kohlerba | 0:cf50c95c11c5 | 129 | ssd1306_command(0xCF); |
| kohlerba | 0:cf50c95c11c5 | 130 | |
| kohlerba | 0:cf50c95c11c5 | 131 | ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9 |
| kohlerba | 0:cf50c95c11c5 | 132 | ssd1306_command(0xF1); |
| kohlerba | 0:cf50c95c11c5 | 133 | |
| kohlerba | 0:cf50c95c11c5 | 134 | ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB |
| kohlerba | 0:cf50c95c11c5 | 135 | ssd1306_command(0x40); |
| kohlerba | 0:cf50c95c11c5 | 136 | |
| kohlerba | 0:cf50c95c11c5 | 137 | ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4 |
| kohlerba | 0:cf50c95c11c5 | 138 | |
| kohlerba | 0:cf50c95c11c5 | 139 | ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6 |
| kohlerba | 0:cf50c95c11c5 | 140 | |
| kohlerba | 0:cf50c95c11c5 | 141 | ssd1306_command(SSD1306_DISPLAYON); //switch on OLED |
| kohlerba | 0:cf50c95c11c5 | 142 | } |
| kohlerba | 0:cf50c95c11c5 | 143 | |
| kohlerba | 0:cf50c95c11c5 | 144 | int main() { |
| kohlerba | 0:cf50c95c11c5 | 145 | |
| kohlerba | 0:cf50c95c11c5 | 146 | // fill buffer with something for test |
| kohlerba | 0:cf50c95c11c5 | 147 | memset( display_buffer, 0X02, 1024); // tried other values |
| kohlerba | 0:cf50c95c11c5 | 148 | |
| kohlerba | 0:cf50c95c11c5 | 149 | _i2c_address = 0x78; |
| kohlerba | 0:cf50c95c11c5 | 150 | |
| kohlerba | 0:cf50c95c11c5 | 151 | InitializeDisplay(); |
| kohlerba | 0:cf50c95c11c5 | 152 | |
| kohlerba | 0:cf50c95c11c5 | 153 | TransferBuffer(); // try sending buffer |
| kohlerba | 0:cf50c95c11c5 | 154 | |
| kohlerba | 0:cf50c95c11c5 | 155 | while(1) |
| kohlerba | 0:cf50c95c11c5 | 156 | { |
| kohlerba | 0:cf50c95c11c5 | 157 | wait_ms(1000); // keyboard code here |
| kohlerba | 0:cf50c95c11c5 | 158 | if(DigitalIn(LED1) == 0){DigitalOut(LED1,1);} |
| kohlerba | 0:cf50c95c11c5 | 159 | else{DigitalOut(LED1,0);} |
| kohlerba | 0:cf50c95c11c5 | 160 | } |
| kohlerba | 0:cf50c95c11c5 | 161 | } |
Bradley Kohler