Interfacing STM32 Blue Pill with ST7735 Color TFT Display
Interfacing STM32 Blue Pill with ST7735 Color TFT Display
This is another project using STMicroelectronics ARM Cortex-M3 microcontroller based STM32F103C8T6 Blue Pill development board.
In this post we will see how to interface the ST32 Blue Pill board with ST7735 color TFT display where Arduino IDE software is used to write the interfacing program code. We will also see the simulation of the STM32F103C8T6 Blue Pill board with the ST7735 TFT display using Proteus simulation software.
The ST7735 TFT display is a color display with diagonal size of 1.8″ and resolution of 128×160 pixels. This display uses SPI protocol for the communication with master device which is in this example the STM32 Blue Pill board microcontroller STM32F103C8T6.
The ST7735 TFT display module usually comes with an SD card slot which allows -when SD card inserted- the storage of large size files such as images in order to print them in the display (not used in this project).
This module works with 3.3V only, connecting it directly to a 5V system will not work and may damage its controller circuit!
The display which is used in this project is shown below (face):
and the back of the display module:
As shown in the back of the display module image there is AMS1117 3V3 voltage regulator IC, it’s used to supply the display controller circuit with 3.3V from an input supply of 5V (because it does work with 3.3V only).
Also, we can disuse the built-in voltage regulator (AMS1117 3V3) if we already have a regulated voltage source of 3.3V, here we have to close (solder) jumper J1 (red ellipse).
In this example I’m going use 3.3V from the STM32 Blue Pill board, so I have to close J1 jumper.
Interfacing STM32F103C8T6 Blue Pill with ST7735 TFT display circuit:
Project circuit schematic diagram is shown below.
The ST7735S shown in project circuit diagram has 8 pins: (from right to left): RST (reset), CE (chip enable), DC (or D/C: data/command), DIN (data in), CLK (clock), VCC, BL (back light) and Gnd (ground).
Hardware required:
This is a summary of circuit required parts.
- STM32 Blue Pill board —> STM32F103C8T6 32-bit Arm Cortex-M3 MCU
- ST7735 TFT display module
- Breadboard & jumper wires…
- FTDI FT232RL USB-to-UART converter (for burning program file to the MCU)
Circuit description:
The main power source of the circuit comes from the micro USB port of the STM32 Blue Pill board with voltage of 5V. The board contains a voltage regulator that feeds the STM32F103C8T6 microcontroller with 3.3V. The ST7735 display module is powered with 3V3 from the STM32 Blue Pill board where its ‘VCC’ & ‘BL’ pins are connected to ‘3.3V’ pin of the BluePill board.
The ST7735 display is connected to the STM32F103C8T6 Blue Pill board as follows:
RST pin is connected to pin PA2 of the Blue Pill board,
CS pin is connected to pin PA3 of the Blue Pill board,
D/C pin is connected to pin PA4 of the Blue Pill board,
CLK pin is connected to pin PA5 of the Blue Pill board,
DIN pin is connected to pin PA7 of the Blue Pill board,
VCC and BL are connected to pin 3V3,
GND is connected to pin GND of the Blue Pill board board.
Pins PA5 and PA7 are hardware SPI1 module pins of the STM32F103C8T6 microcontroller respectively for SCK (serial clock) and MOSI (master-out slave-in).
Interfacing STM32 Blue Pill with ST7735 display Arduino code:
Arduino IDE is used to write project code, the STM32 Blue Pill board has to be added to the IDE before compilation.
The STM32 Blue Pill board can be installed using Arduino IDE Boards Manager.
Project Arduino code is just an example of graphics test provided by Adafruit Industries with the ST7735 display library.
The FT232RL USB to serial UART converter is used to program the STM32F103C8T6 microcontroller, the ST-LINK V2 programmer also can be used and it is supported by the Arduino IDE.
The following Arduino code requires two libraries from Adafruit Industries:
The first library is a driver for the ST7735 TFT display which can be installed from Arduino IDE library manager (Sketch —> Include Library —> Manage Libraries …, in the search box write “st7735” and install the one from Adafruit).
The second library is Adafruit graphics library which can be installed also from Arduino IDE library manager.
During installation of the Adafruit ST7735 library Arduino IDE may ask for installing some other libraries form Adafruit Industries.
Hints:
The used libraries are included in the Arduino code as shown below:
1
2
3
|
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>
|
The connection between the STM32 Blue Pill board and the ST7735 display is as shown in the above circuit schematic, it is defined in the Arduino code as shown below:
1
2
3
|
#define TFT_CS PA3
#define TFT_DC PA4
#define TFT_RST PA2 // Or set to -1 and connect to Arduino RESET pin
|
And the initialization of the ST7735 display library with the connections previously defined:
1
|
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
|
Full Arduino code:
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
|
/**************************************************************************************
* Interfacing STM32F103C8T6 Blue Pill board with ST7735 TFT display (128×160 pixel).
* This is a free software with NO WARRANTY.
* http://simple-circuit.com/
/**************************************************************************************
This is a library for several Adafruit displays based on ST77* drivers.
Works with the Adafruit 1.8″ TFT Breakout w/SD card
—-> http://www.adafruit.com/products/358
The 1.8″ TFT shield
—-> https://www.adafruit.com/product/802
The 1.44″ TFT breakout
—-> https://www.adafruit.com/product/2088
The 1.14″ TFT breakout
—-> https://www.adafruit.com/product/4383
The 1.3″ TFT breakout
—-> https://www.adafruit.com/product/4313
The 1.54″ TFT breakout
—-> https://www.adafruit.com/product/3787
The 1.69″ TFT breakout
—-> https://www.adafruit.com/product/5206
The 2.0″ TFT breakout
—-> https://www.adafruit.com/product/4311
as well as Adafruit raw 1.8″ TFT display
—-> http://www.adafruit.com/products/618
Check out the links above for our tutorials and wiring diagrams.
These displays use SPI to communicate, 4 or 5 pins are required to
interface (RST is optional).
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
MIT license, all text above must be included in any redistribution
************************************************************************************/
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>
// For the breakout board, you can use any 2 or 3 pins.
// These pins will also work for the 1.8″ TFT shield.
#define TFT_CS PA3
#define TFT_DC PA4
#define TFT_RST PA2 // Or set to -1 and connect to Arduino RESET pin
// OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique
// to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and
// SCLK = pin 13. This is the fastest mode of operation and is required if
// using the breakout board’s microSD card.
// For 1.44″ and 1.8″ TFT with ST7735 use:
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// For 1.14″, 1.3″, 1.54″, 1.69″, and 2.0″ TFT with ST7789:
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
// OPTION 2 lets you interface the display using ANY TWO or THREE PINS,
// tradeoff being that performance is not as fast as hardware SPI above.
//#define TFT_MOSI 11 // Data out
//#define TFT_SCLK 13 // Clock out
// For ST7735-based displays, we will use this call
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
// OR for the ST7789-based displays, we will use this call
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
float p = 3.1415926;
void setup(void) {
Serial.begin(9600);
Serial.print(F(“Hello! ST77xx TFT Test”));
// Use this initializer if using a 1.8″ TFT screen:
tft.initR(INITR_BLACKTAB); // Init ST7735S chip, black tab
// OR use this initializer if using a 1.8″ TFT screen with offset such as WaveShare:
// tft.initR(INITR_GREENTAB); // Init ST7735S chip, green tab
// OR use this initializer (uncomment) if using a 1.44″ TFT:
//tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab
// OR use this initializer (uncomment) if using a 0.96″ 160×80 TFT:
//tft.initR(INITR_MINI160x80); // Init ST7735S mini display
// OR use this initializer (uncomment) if using a 0.96″ 160×80 TFT with
// plug-in FPC (if you see the display is inverted!)
//tft.initR(INITR_MINI160x80_PLUGIN); // Init ST7735S mini display
// OR use this initializer (uncomment) if using a 1.3″ or 1.54″ 240×240 TFT:
//tft.init(240, 240); // Init ST7789 240×240
// OR use this initializer (uncomment) if using a 1.69″ 280×240 TFT:
//tft.init(240, 280); // Init ST7789 280×240
// OR use this initializer (uncomment) if using a 2.0″ 320×240 TFT:
//tft.init(240, 320); // Init ST7789 320×240
// OR use this initializer (uncomment) if using a 1.14″ 240×135 TFT:
//tft.init(135, 240); // Init ST7789 240×135
// OR use this initializer (uncomment) if using a 1.47″ 172×320 TFT:
//tft.init(172, 320); // Init ST7789 172×320
// SPI speed defaults to SPI_DEFAULT_FREQ defined in the library, you can override it here
// Note that speed allowable depends on chip and quality of wiring, if you go too fast, you
// may end up with a black screen some times, or all the time.
//tft.setSPISpeed(40000000);
Serial.println(F(“Initialized”));
uint16_t time = millis();
tft.fillScreen(ST77XX_BLACK);
time = millis() – time;
Serial.println(time, DEC);
delay(500);
// large block of text
tft.fillScreen(ST77XX_BLACK);
testdrawtext(“Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. “, ST77XX_WHITE);
delay(1000);
// tft print function!
tftPrintTest();
delay(4000);
// a single pixel
tft.drawPixel(tft.width()/2, tft.height()/2, ST77XX_GREEN);
delay(500);
// line draw test
testlines(ST77XX_YELLOW);
delay(500);
// optimized lines
testfastlines(ST77XX_RED, ST77XX_BLUE);
delay(500);
testdrawrects(ST77XX_GREEN);
delay(500);
testfillrects(ST77XX_YELLOW, ST77XX_MAGENTA);
delay(500);
tft.fillScreen(ST77XX_BLACK);
testfillcircles(10, ST77XX_BLUE);
testdrawcircles(10, ST77XX_WHITE);
delay(500);
testroundrects();
delay(500);
testtriangles();
delay(500);
mediabuttons();
delay(500);
Serial.println(“done”);
delay(1000);
}
void loop() {
tft.invertDisplay(true);
delay(500);
tft.invertDisplay(false);
delay(500);
}
void testlines(uint16_t color) {
tft.fillScreen(ST77XX_BLACK);
for (int16_t x=0; x < tft.width(); x+=6) {
tft.drawLine(0, 0, x, tft.height()–1, color);
delay(0);
}
for (int16_t y=0; y < tft.height(); y+=6) {
tft.drawLine(0, 0, tft.width()–1, y, color);
delay(0);
}
tft.fillScreen(ST77XX_BLACK);
for (int16_t x=0; x < tft.width(); x+=6) {
tft.drawLine(tft.width()–1, 0, x, tft.height()–1, color);
delay(0);
}
for (int16_t y=0; y < tft.height(); y+=6) {
tft.drawLine(tft.width()–1, 0, 0, y, color);
delay(0);
}
tft.fillScreen(ST77XX_BLACK);
for (int16_t x=0; x < tft.width(); x+=6) {
tft.drawLine(0, tft.height()–1, x, 0, color);
delay(0);
}
for (int16_t y=0; y < tft.height(); y+=6) {
tft.drawLine(0, tft.height()–1, tft.width()–1, y, color);
delay(0);
}
tft.fillScreen(ST77XX_BLACK);
for (int16_t x=0; x < tft.width(); x+=6) {
tft.drawLine(tft.width()–1, tft.height()–1, x, 0, color);
delay(0);
}
for (int16_t y=0; y < tft.height(); y+=6) {
tft.drawLine(tft.width()–1, tft.height()–1, 0, y, color);
delay(0);
}
}
void testdrawtext(char *text, uint16_t color) {
tft.setCursor(0, 0);
tft.setTextColor(color);
tft.setTextWrap(true);
tft.print(text);
}
void testfastlines(uint16_t color1, uint16_t color2) {
tft.fillScreen(ST77XX_BLACK);
for (int16_t y=0; y < tft.height(); y+=5) {
tft.drawFastHLine(0, y, tft.width(), color1);
}
for (int16_t x=0; x < tft.width(); x+=5) {
tft.drawFastVLine(x, 0, tft.height(), color2);
}
}
void testdrawrects(uint16_t color) {
tft.fillScreen(ST77XX_BLACK);
for (int16_t x=0; x < tft.width(); x+=6) {
tft.drawRect(tft.width()/2 –x/2, tft.height()/2 –x/2 , x, x, color);
}
}
void testfillrects(uint16_t color1, uint16_t color2) {
tft.fillScreen(ST77XX_BLACK);
for (int16_t x=tft.width()–1; x > 6; x-=6) {
tft.fillRect(tft.width()/2 –x/2, tft.height()/2 –x/2 , x, x, color1);
tft.drawRect(tft.width()/2 –x/2, tft.height()/2 –x/2 , x, x, color2);
}
}
void testfillcircles(uint8_t radius, uint16_t color) {
for (int16_t x=radius; x < tft.width(); x+=radius*2) {
for (int16_t y=radius; y < tft.height(); y+=radius*2) {
tft.fillCircle(x, y, radius, color);
}
}
}
void testdrawcircles(uint8_t radius, uint16_t color) {
for (int16_t x=0; x < tft.width()+radius; x+=radius*2) {
for (int16_t y=0; y < tft.height()+radius; y+=radius*2) {
tft.drawCircle(x, y, radius, color);
}
}
}
void testtriangles() {
tft.fillScreen(ST77XX_BLACK);
uint16_t color = 0xF800;
int t;
int w = tft.width()/2;
int x = tft.height()–1;
int y = 0;
int z = tft.width();
for(t = 0 ; t <= 15; t++) {
tft.drawTriangle(w, y, y, x, z, x, color);
x-=4;
y+=4;
z-=4;
color+=100;
}
}
void testroundrects() {
tft.fillScreen(ST77XX_BLACK);
uint16_t color = 100;
int i;
int t;
for(t = 0 ; t <= 4; t+=1) {
int x = 0;
int y = 0;
int w = tft.width()–2;
int h = tft.height()–2;
for(i = 0 ; i <= 16; i+=1) {
tft.drawRoundRect(x, y, w, h, 5, color);
x+=2;
y+=3;
w-=4;
h-=6;
color+=1100;
}
color+=100;
}
}
void tftPrintTest() {
tft.setTextWrap(false);
tft.fillScreen(ST77XX_BLACK);
tft.setCursor(0, 30);
tft.setTextColor(ST77XX_RED);
tft.setTextSize(1);
tft.println(“Hello World!”);
tft.setTextColor(ST77XX_YELLOW);
tft.setTextSize(2);
tft.println(“Hello World!”);
tft.setTextColor(ST77XX_GREEN);
tft.setTextSize(3);
tft.println(“Hello World!”);
tft.setTextColor(ST77XX_BLUE);
tft.setTextSize(4);
tft.print(1234.567);
delay(1500);
tft.setCursor(0, 0);
tft.fillScreen(ST77XX_BLACK);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(0);
tft.println(“Hello World!”);
tft.setTextSize(1);
tft.setTextColor(ST77XX_GREEN);
tft.print(p, 6);
tft.println(” Want pi?”);
tft.println(” “);
tft.print(8675309, HEX); // print 8,675,309 out in HEX!
tft.println(” Print HEX!”);
tft.println(” “);
tft.setTextColor(ST77XX_WHITE);
tft.println(“Sketch has been”);
tft.println(“running for: “);
tft.setTextColor(ST77XX_MAGENTA);
tft.print(millis() / 1000);
tft.setTextColor(ST77XX_WHITE);
tft.print(” seconds.”);
}
void mediabuttons() {
// play
tft.fillScreen(ST77XX_BLACK);
tft.fillRoundRect(25, 10, 78, 60, 8, ST77XX_WHITE);
tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_RED);
delay(500);
// pause
tft.fillRoundRect(25, 90, 78, 60, 8, ST77XX_WHITE);
tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_GREEN);
tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_GREEN);
delay(500);
// play color
tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_BLUE);
delay(50);
// pause color
tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_RED);
tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_RED);
// play color
tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_GREEN);
}
// end of code.
|
The below video shows my DIY circuit for this project:
Proteus Simulation:
The interfacing of ST32F103C8T6 Blue Pill with ST7735 display project can be simulated using Proteus simulation software as shown in the video below:
Proteus simulation file download:
Interfacing STM32F103C8T6 Blue Pill with ST7735 display Proteus simulation file download link is below, use Proteus version 8.15 or higher to open it.
Download
And the link below is Proteus library for the STM32F103C8T6 Blue Pill board. After the download put the file in Proteus library folder, for example in my case Proteus library folder path is: C:\ProgramData\Labcenter Electronics\Proteus 8 Professional\Library
Proteus library for the STM32F103C8T6 Blue Pill board