Library 61- SSD1306 OLED I2C LCD for STM32F4xx
Yeah, I got it too. These little, small and with nice contrast devices are really great.
I2C communication from my module isn’t really powerful because of slow I2C, even at 400kHz. To update full LCD, there are 1024 bytes of data to be transfered. And this can really take a while. But anyway, for having this LCD just to showing small updates and notifications for users in your project, I2C is still nice. Probably I should make it using I2C DMA transfer.
The heart of this OLED LCD is SSD1306 driver. Driver itself allows also some other communications like 3-wire SPI or 4-wire SPI as well as 6080 parallel interface any maybe more. Parallel interface is really not necessary here because of small amount of data to be transfered since each pixel is a bit in a bytes area.
In my LCD, I don’t like the fact that about 1/3 of LCD is yellow when pixel is ON and the rest is blue. This looks really crazy and not so useful. Anyway, library is here and ready to use.
Since this LCD is very small, LCD rotation is not possible with this library. By having interest in this feature I will add this too.
Library
Features
- Draw strings to LCD at any position you want
- Draw graphic things like lines, rectangles and circles
- Invert pixels in one function call
- Data for LCD are stored in STM’s ram, after each change, UPDATE command is necessary to get changes on LCD
Dependencies
- CMSIS
- STM32F4xx
- STM32F4xx I2C
- TM
- TM GPIO
- TM I2C
- TM FONTS
- defines.h
- TM GPIO
- C
- string.h
- stdlib.h
SSD1306 | STM32F4 | Description |
---|---|---|
VCC | 3.3V | |
GND | GND | |
SCL | PA8 | Serial clock line |
SDA | PC9 | Serial data line |
LCD works on I2C and it has options to select custom I2C address by changing BIT1 in I2C address. Default address (also used in this library) is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* I2C settings */ #ifndef SSD1306_I2C #define SSD1306_I2C I2C3 #define SSD1306_I2C_PINSPACK TM_I2C_PinsPack_1 #endif /* I2C address */ #ifndef SSD1306_I2C_ADDR #define SSD1306_I2C_ADDR 0x78 /* Use defines.h for custom definitions */ //#define SSD1306_I2C_ADDR 0x7A #endif /* SSD1306 settings */ /* SSD1306 width in pixels */ #ifndef SSD1306_WIDTH #define SSD1306_WIDTH 128 #endif /* SSD1306 LCD height in pixels */ #ifndef SSD1306_HEIGHT #define SSD1306_HEIGHT 64 #endif |
Functions and enumerations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
/** * @defgroup TM_SSD1306_Typedefs * @brief Library Typedefs * @{ */ /** * @brief SSD1306 color enumeration */ typedef enum { SSD1306_COLOR_BLACK = 0x00, /*!< Black color, no pixel */ SSD1306_COLOR_WHITE = 0x01 /*!< Pixel is set. Color depends on LCD */ } SSD1306_COLOR_t; /** * @} */ /** * @defgroup TM_SSD1306_Functions * @brief Library Functions * @{ */ /** * @brief Initializes SSD1306 LCD * @param None * @retval Initialization status: * - 0: LCD was not detected on I2C port * - > 0: LCD initialized OK and ready to use */ uint8_t TM_SSD1306_Init(void); /** * @brief Updates buffer from internal RAM to LCD * @note This function must be called each time you do some changes to LCD, to update buffer from RAM to LCD * @param None * @retval None */ void TM_SSD1306_UpdateScreen(void); /** * @brief Toggles pixels invertion inside internal RAM * @note @ref TM_SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen * @param None * @retval None */ void TM_SSD1306_ToggleInvert(void); /** * @brief Fills entire LCD with desired color * @note @ref TM_SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen * @param Color: Color to be used for screen fill. This parameter can be a value of @ref SSD1306_COLOR_t enumeration * @retval None */ void TM_SSD1306_Fill(SSD1306_COLOR_t Color); /** * @brief Draws pixel at desired location * @note @ref TM_SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen * @param x: X location. This parameter can be a value between 0 and SSD1306_WIDTH - 1 * @param y: Y location. This parameter can be a value between 0 and SSD1306_HEIGHT - 1 * @param color: Color to be used for screen fill. This parameter can be a value of @ref SSD1306_COLOR_t enumeration * @retval None */ void TM_SSD1306_DrawPixel(uint16_t x, uint16_t y, SSD1306_COLOR_t color); /** * @brief Sets cursor pointer to desired location for strings * @param x: X location. This parameter can be a value between 0 and SSD1306_WIDTH - 1 * @param y: Y location. This parameter can be a value between 0 and SSD1306_HEIGHT - 1 * @retval None */ void TM_SSD1306_GotoXY(uint16_t x, uint16_t y); /** * @brief Puts character to internal RAM * @note @ref TM_SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen * @param ch: Character to be written * @param *Font: Pointer to @ref TM_FontDef_t structure with used font * @param color: Color used for drawing. This parameter can be a value of @ref SSD1306_COLOR_t enumeration * @retval Character written */ char TM_SSD1306_Putc(char ch, TM_FontDef_t* Font, SSD1306_COLOR_t color); /** * @brief Puts string to internal RAM * @note @ref TM_SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen * @param *str: String to be written * @param *Font: Pointer to @ref TM_FontDef_t structure with used font * @param color: Color used for drawing. This parameter can be a value of @ref SSD1306_COLOR_t enumeration * @retval Zero on success or character value when function failed */ char TM_SSD1306_Puts(char* str, TM_FontDef_t* Font, SSD1306_COLOR_t color); /** * @brief Draws line on LCD * @note @ref TM_SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen * @param x0: Line X start point. Valid input is 0 to SSD1306_WIDTH - 1 * @param y0: Line Y start point. Valid input is 0 to SSD1306_HEIGHT - 1 * @param x1: Line X end point. Valid input is 0 to SSD1306_WIDTH - 1 * @param y1: Line Y end point. Valid input is 0 to SSD1306_HEIGHT - 1 * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration * @retval None */ void TM_SSD1306_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, SSD1306_COLOR_t c); /** * @brief Draws rectangle on LCD * @note @ref TM_SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen * @param x: Top left X start point. Valid input is 0 to SSD1306_WIDTH - 1 * @param y: Top left Y start point. Valid input is 0 to SSD1306_HEIGHT - 1 * @param w: Rectangle width in units of pixels * @param h: Rectangle height in units of pixels * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration * @retval None */ void TM_SSD1306_DrawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c); /** * @brief Draws filled rectangle on LCD * @note @ref TM_SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen * @param x: Top left X start point. Valid input is 0 to SSD1306_WIDTH - 1 * @param y: Top left Y start point. Valid input is 0 to SSD1306_HEIGHT - 1 * @param w: Rectangle width in units of pixels * @param h: Rectangle height in units of pixels * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration * @retval None */ void TM_SSD1306_DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c); /** * @brief Draws triangle on LCD * @note @ref TM_SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen * @param x1: First coordinate X location. Valid input is 0 to SSD1306_WIDTH - 1 * @param y1: First coordinate Y location. Valid input is 0 to SSD1306_HEIGHT - 1 * @param x2: Second coordinate X location. Valid input is 0 to SSD1306_WIDTH - 1 * @param y2: Second coordinate Y location. Valid input is 0 to SSD1306_HEIGHT - 1 * @param x3: Third coordinate X location. Valid input is 0 to SSD1306_WIDTH - 1 * @param y3: Third coordinate Y location. Valid input is 0 to SSD1306_HEIGHT - 1 * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration * @retval None */ void TM_SSD1306_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, SSD1306_COLOR_t color); /** * @brief Draws circle to STM buffer * @note @ref TM_SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen * @param x: X location for center of circle. Valid input is 0 to SSD1306_WIDTH - 1 * @param y: Y location for center of circle. Valid input is 0 to SSD1306_HEIGHT - 1 * @param r: Circle radius in units of pixels * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration * @retval None */ void TM_SSD1306_DrawCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c); /** * @brief Draws filled circle to STM buffer * @note @ref TM_SSD1306_UpdateScreen() must be called after that in order to see updated LCD screen * @param x: X location for center of circle. Valid input is 0 to SSD1306_WIDTH - 1 * @param y: Y location for center of circle. Valid input is 0 to SSD1306_HEIGHT - 1 * @param r: Circle radius in units of pixels * @param c: Color to be used. This parameter can be a value of @ref SSD1306_COLOR_t enumeration * @retval None */ void TM_SSD1306_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c); /** * @} */ |
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
/** * Keil project template * * Before you start, select your target, on the right of the "Load" button * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision 5 * @conf PLL parameters are set in "Options for Target" -> "C/C++" -> "Defines" * @packs STM32F4xx Keil packs version 2.4.0 or greater required * @stdperiph STM32F4xx Standard peripheral drivers version 1.5.0 or greater required */ /* Include core modules */ #include "stm32f4xx.h" /* Include my libraries here */ #include "defines.h" #include "tm_stm32f4_delay.h" #include "tm_stm32f4_disco.h" #include "tm_stm32f4_ssd1306.h" int main(void) { /* Initialize system */ SystemInit(); /* Initialize delay */ TM_DELAY_Init(); /* Init LEDS */ TM_DISCO_LedInit(); /* Init SSD1306 LCD 128 x 64 px */ if (TM_SSD1306_Init()) { /* SSD1306 is connected */ TM_DISCO_LedOn(LED_GREEN); } else { /* SSD1306 is not connected */ TM_DISCO_LedOn(LED_RED); } /* Go to location X = 30, Y = 4 */ TM_SSD1306_GotoXY(30, 4); TM_SSD1306_Puts("STM32F4xx", &TM_Font_7x10, SSD1306_COLOR_WHITE); /* Go to location X = 20, Y = 25 */ TM_SSD1306_GotoXY(8, 25); TM_SSD1306_Puts("I2C SSD1306 LCD", &TM_Font_7x10, SSD1306_COLOR_WHITE); /* Go to location X = 15, Y = 45 */ TM_SSD1306_GotoXY(15, 45); TM_SSD1306_Puts("Tilen Majerle", &TM_Font_7x10, SSD1306_COLOR_WHITE); /* Update screen, send changes to LCD */ TM_SSD1306_UpdateScreen(); while (1) { /* Invert pixels */ TM_SSD1306_ToggleInvert(); /* Update screen */ TM_SSD1306_UpdateScreen(); /* Make a little delay */ Delayms(500); } } |
Project is available on my Github, download library below.
Recent comments