The pinout for the board is as follows, inclusive of the SD card connections:
1. GND
2. VCC 3. NC
4. NC
5. NC
6. LCD RESET
7. LCD A0 (R/S)
8. LCD SDA
9. LCD SCK
10. LCD CS
11. SD SCK
12. SD MISO
13. SD MOSI
14. SD CS
15. LED+
16. LED-
Interface via SPI
This LCD controller, ST7735, uses SPI for communication and requires just 5 data lines, namely RESET, A0, SDA, SCK and CS. Of particular note is the A0 line, also known as R/S, which indicates whether the bytes being transferred should be interpreted as command or as pixel data. Although SPI communication should preferably be done using the hardware SPI module (there are two on my PIC24FJ64GA002) for faster display speed, it can also be done via bit-banging if hardware SPI is not available. The following function will send a byte via SPI using software:
void write_spi_byte(unsigned char c){ char x; for(x=0;x<8;x++){ LCD_SCK = 0; LCD_SDA = 0; if(c & 0x80) LCD_SDA = 1; LCD_SCK = 1; c <<= 1; } }
I converted the Adafruit's Arduino library for this LCD to compile under Microchip C30 compiler for my PIC24FJ64GA002 and the LCD is able to draw some graphics nicely:
Using the bundled SD card socket and Microchip MDD library, together with my custom 5x7 font, I was able to display some SD card information on the LCD:
The board I purchased has an AMS1117 on-board regulator and expects at least 5V to be supplied to VCC to be able to generate 3.3V for the LCD and SD card to work. I did not know this and supplied 3.3V to VCC initially, only to find out that the SD card worked intermittently while the LCD still worked well. If you have problems with the SD card on this module, check if this is the case.
Setting the color model
The ST7735 controller supports up to 262,144 (218) colors. However, to be able to use 262K colors, for each pixel, 18-bit of data have to be transferred via SPI. Since this increases the complexity. I have decided to stay with 65,536 colors (16-bit) colors, where pixel data can be transferred nicely just by using 2 SPI writes.
In 16-bit color mode, the LCD expects pixel data to be in RGB565 format. The following will convert from the well-known RGB888 (24-bit color) format to RGB565:
#define RGB565(r,g,b) ((((r>>3)<<11) | ((g>>2)<<5) | (b>>3)))
An interesting point to note about this LCD is that there seems to be two variants with slightly different behaviors. If your module comes with a black tab, the BLUE and RED byte of each pixel will be swapped, resulting in the wrong color being displayed. If your module has a red or green tab, the byte order for each pixel will be correct.
To fix this issue, you can change the above RGB565 macro to swap the red and blue byte, or you can change the value of the MADCTL register during initialization:
writecommand(ST7735_MADCTL); // R and B byte are swapped // writedata(0xC8); // normal R G B order writedata(0xC0);
Downloads
Various bitmaps from my SD card as shown on the LCD:
The C30 source code for this LCD can be downloaded here.

Is there any possibility to download the full source code? I tried it but it doesn't work :(, maybe the speed from my pic16f1827 is too slow.
ReplyDeleteGreg ( fb@synk.at )
Hi Greg,
ReplyDeleteWhat errors are you encountering with the provided code? Are you able to compile it? Take note that you'll need the custom font (provided in the article as well) for the code to compile, The source code is using software (bit-bang) SPI, or you can also use hardware SPI. The PIC16F1827 has 1 hardware SPI module.
What SPI speed is your PIC running at? This LCD should work with an SPI speed at 1MHz or above.
If all fails, refer this https://github.com/adafruit/Adafruit-ST7735-Library/blob/master/Adafruit_ST7735.cpp source code and have a look at the function void Adafruit_ST7735::initB(void). Your LCD may require a slightly different initialization routine, depending on the color of its tab (red, green or blue).
Let me know if you have any other questions.
Hi MD, thanks for you quick response. I have no trouble with your code and I am able to compile it. I took not all from your code because I want only to change the color of the screen and draw two lines. I found already another example on the internet ( https://sites.google.com/site/arduinomega2560projects/microchip-pic/level-3/st7735-1-8-tft ), when I am using his code and changing the ports, I can see many colorful pixels for a short time but not a line or something like that (his code is using the hardware spi).
ReplyDeleteIt should be 2 Mhz, because I use the internal oscillator with 8 Mhz. This is my code http://synk.at/testLCD.txt
I have exactly the same LCD like you.
Can I see the init of your PIC? Did you change anything?
Greg
Hi Greg,
ReplyDeleteYou can first try to write a simple program with a while(1) loop to toggle the pins assigned for this LCD (e.g. LATBbits.LATB1, LATAbits.LATA6) with sufficient delay (e.g. 100ms) in between and see if you can observe a square wave on your oscilloscope, or 2.5V on your multimeter if you do not own an oscilloscope, on each of the output pins. In fact it is a good practice to make sure all output pins you intend to use can be freely controlled from code and all input pins can recognize digital 0 and digital 1 properly before attempting to connect any devices to the PIC.
In particular, make sure that you are able to control LATAbits.LATA6 freely from code. RA6 a shared pin on the PIC16F1827 so you'll need to set some registers to enable digital input on that pin. At minimum, set TRISA = 0x00 and TRISB = 0x00 for all output pins, and remove SDO1SEL because you're going to use software SPI (as in the code you sent me) and not hardware SPI.
RA6 is a special pin on this PIC, so your configuration bits (_CONFIG() declaration at the beginning of your code) will needs to be set properly to allow using it as output. Refer to this http://www.microchip.com/forums/m691867.aspx for more details.
The same applies for other output pins too, make sure that you can set their states from codes. This ensures that the LCD can receive the proper initialization data. If you're using the PICKit for programming, make sure that none of the pins you use for this LCD conflicts with the pins used for the PICKit - that will cause problems.
The code on the website you sent me is very similar to my codes, except that the author does not set the gamma control (ST7735_GMCTRP1) of the LCD during initialization. As this is optional, both codes should work on your LCD. You can also try between the PORTA/PORTB registers and the LATA/LATB registers and check if there's any different when using the source code provided by that website. In my experience using the latch to write to the port is always better to avoid read-modify-write issues.
You may find the entire source code for this LCD (and other interesting modules you can play with) here https://dl.dropboxusercontent.com/u/5881137/pic24f_hobby2.zip designed for the PIC24FJ64GA002 but can be ported to other PIC too. The source code features a terminal via UART which allows you to read a 128x160 24-bit bitmap from the SD card slot and display it on the LCD. It is using software SPI for this LCD (but can be switched to hardware SPI easily). For the PIC initialization (refer to function initIO() in main.c), nothing really special to take note of, except to set the correct TRIS bit to assign the input/output pins.
Let me know your progress. :)
Thank you for your detailed help :)! Now its working fine, RA6 was the problem ;)! You are my hero :)!
ReplyDeleteHi Greg,
ReplyDeleteGlad you got it working. Enjoy playing with the LCD!
Thanks for this great tutorial, I have been a PIC fan for a long time. Just decided I wanted a graphics and touch screen display for a project. looked around purchased a few displays on E bay. found this site and your source code easy to understand.Got me up and running. Thanks again. Rod
ReplyDeleteGlad you find the source code useful. :) I am also a PIC fan and electronics hobbyist too (my full time job is a software professional). Love the PIC- small but otherwise powerful microcontrollers.
DeleteI am only a hobby programmer. so I need to ask. as this is a pic blog. How do I erase a character before drawing another on top. Basically I need to create animation its the most basic function but its eluding me on this display.
ReplyDeleteIn the PC we called it double buffering. Well it was last time I programmed a computer. Could you point me in the direction of some code. for this display.
Is there a way to write to the ram and display it after the write.
Hi Rodney,
DeleteFor simple clearing of the screen and drawing new text/graphics over, you can use ST7735_fillRect function, provided in my library. Just fill the area you want to draw with a color that is the same as the background color. This will effectively clear that area of the display and you can draw the new contents over.
However, to create animation on this display, you would need to use what you've already described in your question, which is a double buffer. On a PC or a PIC with a large enough memory, you can try to declare an array (~40K for this LCD) which holds on the pixel color information. For any drawing, update that array first without affecting the LCD. Once the drawing is finalized, create another method which will write the entire array contents to the LCD. At a fast enough SPI speed (32 MHz for example), the transfer of 40K of data would finish in a fraction of seconds and there would (hopefully) be no visible effects on the LCD, resulting in a smooth animation. You can perhaps do this on a PIC with large enough RAM (PIC32 or DSPIC for example).
You can check the datasheet of the ST7735 here ftp://imall.iteadstudio.com/IM120419001_ITDB02_1.8SP/DS_ST7735.pdf
I have read through the datasheet and apparently there is no internal support for double buffering on this LCD controller. There is some information in section 9.11 (Tearing Effect Output Line), 9.11.3 and 9.11.4 on pages 62-65 which describes how the LCD handles memory writes that are faster or slower than its internal update speed. You can see from the graphics illustration which shows the characters B or A being partially drawn - implying that there is no internal buffer on this LCD controller.
You may also find the command list for this LCD on page 77 of the datasheet useful. Refer to this post http://fabienroyer.wordpress.com/2011/05/29/driving-an-adafruit-st7735-tft-display-with-a-netduino/ on a similar attempt at using software-buffering on this LCD.
Again Thank you. Do you have a donation button. If you don't you should have.
ReplyDeleteEven with the internet being a paradise of information sometimes its still just works to ask..
Your explanation was spot on. Being in new tech sometimes its hard to know if what you are looking for is there or you just don't recognize it when you see it.
My PIC of choice for this project . 32MX460 512 . So I went with your first option to write the back ground color over the text and then redraw the new text on top. I needed a 6 digit decimal hi speed counter for a frequency reading project with graphics support.
I am going to give the array dump suggestion a try, that sounds like fun. The source code you provided with this Blog is very nicely written its clean easy to read and straight to the point, it integrated so well. Now to get the SD card reader going that looks a bit harder.
cheers Rod
Hi Rodney,
DeleteI am happy to hear that my suggestions and the library work well for your project, a PIC-based frequency counter project! This makes me feel more excited and motivated to continue to maintain this blog to help other people with similar interests.
I love the PIC32 too - it can run at at much faster speed compared with PIC24 and has more RAM to play. Unfortunately most PIC32 devices are in small packaging (TSSOP, SOIC, etc) and not the more hobbyist-friendly PDIP packaging. I have in my collection here the PIC32MX250F128B - one of the few PIC32s available in PDIP - and plan to play around with it soon, perhaps by attempting to display graphics on this ST7735 LCD using double-buffering and see the results.
For interfacing with the SD card, you can use the Microchip Memory Disk Drive (MDD) library. It uses the hardware SPI module and contains everything you need to read SD card up to 2GB, in FAT12, FAT16 and FAT32 format. You simply need to change the HardwareProfile.h declaration to match your connections. Methods to read/write files on the SD card are something like fsfread, fsfwrite, fsfclose - similar to standard C functions so it's very easy to use.
You can refer to my other article, http://minhdanh2002.blogspot.sg/2014/03/using-picojpeg-library-on-pic24-with.html , which uses the MDD library to read JPEG file from an SD card and display on the ILI9341 LCD.
Keep me updated on your progress.
Hi MD
ReplyDeleteI now have the SD card supporting my project. I must say when I looked at the MDD library and the code for the card I was think What am I Going to now. They seem to write it to support there development kits and there was all this other code I did not need. The UART had me confused for a while. Once again your example code was very helpful, I am very happy to be moving forward will my project and to now have graphics and SD card to my skill set. Still plenty to do. cheers Rod
Hi Rodney,
DeleteGlad to hear you've made good progress on the SD card interfacing in your project. Let me know if you need any other help. :)
Hi MD
ReplyDeleteI have been working on all thing PIC and the related. SD cards and TFT displays
I have tested a quite a few different displays with a verity of controllers, Having good fun and learning heaps. You said ask if I had a question.
I want to look a program I have in a PIC processor. The short question is can I disassemble a PIC hex file back to source code .
I want to look at an algorithm that's in a chip I have. I can read the chip its not locked.
I remember you saying you disassembled some old dos games.
cheers
Hi Rodney,
DeleteGlad you're having fun with the PIC and LCD displays. :)
If the code protection bit (CP) was not set in the configuration register of the PIC during programming, you'll be able to read the contents of the program memory back into a HEX file. From there it is possible to disassemble the HEX file back into assembly code. The few methods I know of are below:
1. Start MPLAB 8.92 and open File>Import and select the HEX file which you've read back from the PIC. The output window should say that the Hex file is loaded successfully. After that, select View > Program Memory. A new window should open with several tabs at the bottom (OpCode Hex, Machine, Symbolic, etc.). Select the Symbolic tab and you'll see the disassemble listing of the HEX file. The first line should be something like "goto 0x200" which shows you where in memory the execution of the program should start.
2. Use the free tool PICDISASM downloadable from http://www.hagi-online.org/picmicro/picdisasm_en.html - this supports PIC16 and lower. PIC24, PIC32 and dsPIC are not supported.
3. Use the PIC disassembler downloadable from http://www.eolis-software.co.uk/picdisassembler24.shtml which supports most PIC devices including PIC24 and PIC32. However this tool is not free - a trial version can be downloaded for evaluation purposes.
As for decompiling the HEX file back to the original source code - that is not possible as far as I know as much of the information required to create the original code is lost during compilation. There are some such tools for the x86 PC which attempts to construct a human-readable C code from the assembly listing but the quality of the generated C code may vary - sometimes reading the generated C code is harder then reading the disassembly! I do not know of such a tool for the PIC, presumably because its possible usage is limited and no-one has attempted yet.
In my experience, with just some basic assembly knowledge and some understanding on the connections (e.g. where each pin is connected and what it is for), you can still understand what the program is doing by reading the assembly listing - as most of what the code is doing will possibly be just toggling output pins or reading input :) Other more complex logic such as interrupt may be harder to decipher. Try to recreate the complete ASM file from the disassemble listing (this requires figuring out the original configuration bits), compile it under MPASM and run it to debug. I have tried that before - quite tough but it's fun and a good learning exercise.
Let me know if you manage to figure out the algorithm that you wanted.
Hi,
ReplyDeleteDoes this support the PIC32?
Hi,
DeleteYes, the code should be able to be ported to the PIC32 with only major changes. let me know if you encounter any issues.
I purchased a board with the same controller and similar pin outs. The seller claims that it's a touch display. Based on what you know about the module, could this be true? How would you connect the touch controls.
ReplyDeleteI purchased a board with the same controller and similar pin outs. The seller claims that it's a touch display. Based on what you know about the module, could this be true? How would you connect the touch controls.
ReplyDeleteHi,
DeleteSorry for the late reply. Can you post the pinout of your board here? I may be able to check whether it supports touch. Also check my other article here http://www.toughdev.com/viewpost.php?id=4329548174080303786&t=0&v=1#s0 to see how low-level touch interface is implemented on a similar LCD module (HY28A using ILI9320 controller)
Certainly! Thanks for your help.
DeleteGRN
VCC
NC
NC
NC
RESET
AO
SDA
SCK
CS
SCK
MISO
MOSI
CS
LED+
LED-
Hi. It does not seem to support touch from the pinout. The SDA/SCK/CS/MISO/MOSI are purely for the main LCD module. If touch is supported, there should be separate pins named TP_XXXX for the touch controller. Nevertheless, you may want to confirm this by looking up the datasheet for the LCD module controller.
DeleteThis comment has been removed by the author.
ReplyDeleteNo problem. You can still try to have a close look at the IC chipset on the lcd board and find out which controller they are using from the label, and google for the IC codes to find the datasheet.
DeleteUnfortunately, no chipset is visible. :-/
DeleteAre there any screws on the module attaching the LCD to the PCB? If yes, try to unscrew these things - you may be able to find the driver/controller chipset hidden in between the board and the actual LCD. This is the case for one of my units.
DeleteThanks for your thoughts!
ReplyDelete