-
Notifications
You must be signed in to change notification settings - Fork 0
Setup Guide
- Download or clone the repository.
- Navigate to the
libfolder. - Copy the
ssd1306.candssd1306.hinto your project directory. - Include the
ssd1306.hin your source file. - Set up your display by following the Display Setup below. See the Example
main.cFiles as well. - Use the provided library functions to test your display. Optionally you can use the demo or test animations.
Define an I2C callback function with the following prototype:
void i2c_write(uint8_t *data, uint16_t length);You'll need to either create an I2C library or adapt an existing one for your platform. Most embedded systems are shipped with hardware abstraction libraries that can be used with minimal tweaking as shown in the examples below.
Note: The first byte of the data passed to this function will always be the 8-bit I2C write address (i2c_address << 1) of the display. Note that this isn't the original 7-bit address but the I2C write command for that address. This is done to enable support for various I2C libraries, some of which don't have a sequential write or address-data separate write functions. If your I2C library sends the address separately:
- Read the first
databyte to get the address. If necessary, shift it to the right by one to get the 7-bit address.- Advance the
datapointer by one, and decrement thelengthby one, and send the data with your library write function.
Example - Discrete I2C Functions (Start/Stop/Write):
void i2c_write(uint8_t *data, uint16_t length) {
I2C1_Start();
for (uint16_t i = 0; i < length; i++) {
I2C1_Write(data[i]);
}
I2C1_Stop();
}Example - STM32 HAL Library: (Source)
void i2c_write(uint8_t *data, uint16_t length) {
/* Send display commands (first byte is 8-bit write address) */
uint8_t address = *data;
HAL_I2C_Master_Transmit(&hi2c1, address, ++data, --length, 1000);
}Example - PIC16/18 MCC Library: (Source)
void i2c_write(uint8_t *data, uint16_t length) {
/* Send display commands (first byte is 8-bit write address) */
uint8_t address = *data >> 1;
if (I2C1_Host.Write(address, ++data, --length)) {
uint8_t wait_counter = 100;
while (I2C1_Host.IsBusy()) {
I2C1_Host.Tasks();
wait_counter--;
}
}
}Define an ssd1306_display structure for your display. This object will represent your display, and all library functions will require it as their first argument:
static struct ssd1306_display display;Define a uint8_t array for your display. This array will serve as the internal buffer for your display. Use the macros in the header file to declare an array with the appropriate size according to your display type:
/* For 128x64 displays */
static uint8_t display_array[SSD1306_ARRAY_SIZE_64];
/* For 128x32 displays */
static uint8_t display_array[SSD1306_ARRAY_SIZE_32];Initialize the ssd1306_display structure with the ssd1306_init() function. This will initialize both the structure and the physical display:
The arguments are:
- Arg1: The address of your
ssd1306_displaystructure.- Arg2: The 7-bit I2C address of your display.
- Arg3: The Type of your display. Use the
ssd1306_display_typeenum from the header file:
SSD1306_DISPLAY_TYPE_32for 128x32 displays.SSD1306_DISPLAY_TYPE_64for 128x64 displays.- Arg4: The address of your
display_array.- Arg5: The address of your
i2c_writefunction
/* 128x64 display with the address 0x3C */
ssd1306_init(&display,
0x3C,
SSD1306_DISPLAY_TYPE_64,
display_array,
i2c_write);/* 128x32 display with the address 0x3C */
ssd1306_init(&display,
0x3C,
SSD1306_DISPLAY_TYPE_32,
display_array,
i2c_write);Below are example main.c files demonstrating the minimum code required to display a circle in the center of a 128x64 display with the I2C address 0x3C:
Note: For 128x32 displays, simply adjust the display initialization and the circle shape accordingly.
Example - Discrete I2C Functions (Start/Stop/Write):
/* Other includes... */
#include "ssd1306.h"
/* I2C callback definition */
void i2c_write(uint8_t *data, uint16_t length) {
I2C1_Start();
for (uint16_t i = 0; i < length; i++) {
I2C1_Write(data[i]);
}
I2C1_Stop();
}
int main(void) {
/* System setup... */
/* Display initialization */
static struct ssd1306_display display;
static uint8_t display_array[SSD1306_ARRAY_SIZE_64];
ssd1306_init(&display,
0x3C,
SSD1306_DISPLAY_TYPE_64,
display_array,
i2c_write);
/* Draw a circle at (64, 32) with a radius of 30 */
ssd1306_draw_circle(&display, 64, 32, 30);
ssd1306_display_update(&display);
while (1);
}Example - STM32 HAL Library:
/* Other includes... */
#include "ssd1306.h"
/* I2C callback definition */
void i2c_write(uint8_t *data, uint16_t length) {
/* Send display commands (first byte is 8-bit write address) */
uint8_t address = *data;
HAL_I2C_Master_Transmit(&hi2c1, address, ++data, --length, 1000);
}
int main(void) {
/* System setup... */
/* Display initialization */
static struct ssd1306_display display;
static uint8_t display_array[SSD1306_ARRAY_SIZE_64];
ssd1306_init(&display,
0x3C,
SSD1306_DISPLAY_TYPE_64,
display_array,
i2c_write);
/* Draw a circle at (64, 32) with a radius of 30 */
ssd1306_draw_circle(&display, 64, 32, 30);
ssd1306_display_update(&display);
while (1);
}Example - PIC16/18 MCC Library:
/* Other includes... */
#include "ssd1306.h"
/* I2C callback definition */
void i2c_write(uint8_t *data, uint16_t length) {
/* Send display commands (first byte is 8-bit write address) */
uint8_t address = *data >> 1;
if (I2C1_Host.Write(address, ++data, --length)) {
uint8_t wait_counter = 100;
while (I2C1_Host.IsBusy()) {
I2C1_Host.Tasks();
wait_counter--;
}
}
}
void main(void) {
/* System setup... */
/* Display initialization */
static struct ssd1306_display display;
static uint8_t display_array[SSD1306_ARRAY_SIZE_64];
ssd1306_init(&display,
0x3C,
SSD1306_DISPLAY_TYPE_64,
display_array,
i2c_write);
/* Draw a circle at (64, 32) with a radius of 30 */
ssd1306_draw_circle(&display, 64, 32, 30);
ssd1306_display_update(&display);
while (1);
}
The library also includes demo and test animations:
-
Demofiles include various cool animations that can be performed with the library. -
Testfiles include lazily written test animations for each library function. These aren't unit tests, but simple animations.
Note: Instead of a manual setup like shown below, you have the option to put the entire repository into your project instead.
- Follow the Library Setup.
- Navigate to the
demofolder and copy thessd1306_demo.candssd1306_demo.hinto your project the same way. - Open the
ssd1306_demo.hand update the include path for thessd1306.h:
/* Original */
#include "../ssd1306.h"
/* Change to */
#include "ssd1306.h"- Include the
ssd1306_demo.hin your source file and call one of the demo functions listed in the header file (all demo functions are infinite loops):
Note: Demo functions take a display object and an arbitrary delay number. Read the function descriptions.
#include "ssd1306_demo.h"
/* In your main.c after display initializations */
ssd1306_demo_1(&display, 0);- Follow the Library Setup.
- Navigate to the
testfolder and copy thessd1306_test.candssd1306_test.hinto your project the same way. - Open the
ssd1306_test.hand update the include path for thessd1306.h:
/* Original */
#include "../ssd1306.h"
/* Change to */
#include "ssd1306.h"- Include the
ssd1306_test.hin your source file and call one of the test functions listed in the header file (all test functions are infinite loops):
Note: Test functions take a display object and an arbitrary delay number. Read the function descriptions.
#include "ssd1306_test.h"
/* In your main.c after display initializations */
ssd1306_test_draw_shifts(&display, 0);