Menu

Adskeeper - header widge

728x90

Search This Blog

468x60

Navbar

AdsKeeper - IAB Display Standard Ad Unit

Tuesday, October 13, 2026

dsPIC30F2010 and Nokia 5110 LCD Software SPI in MikroC

Introduction

Nokia 5510 LCD Module is 84x48 monochrome graphical LCD that use a Philip PCD8544 pixel matrix LCD controller/driver. It is very easy to use since it uses only three wires SPI interface with some additional control pin. It configuration setting is simple that is very similar to the KS0108 LCD controller except the three wires SPI interface. Using this interface is easy to connect and maintenance with a master MCU. 

 

dsPIC30F2010 and Nokia 5110 LCD Software SPI in MikroC
Program Testing

 

 This graphical LCD is widely available at very low cost. Most electronic hobbyists use this LCD with an Arduino. However different micro-controllers can control this display via a dedicated or software SPI.

 

dsPIC30F2010 and Nokia 5110 LCD Programming using MikroC

MikroC doesn't have a build-in library for this LCD module. But it has both hardware and software SPI to communicate with any devices. Hardware or dedicated SPI is very fast even at the speed of Fosc/4 of a micro-controller clock.

 

dsPIC30F2010 and Nokia 5110 LCD Software SPI in MikroC
Program Testing

 

I can not properly configure the hardware SPI module of the dsPIC30F2010 at this time. So I use its software SPI library instead due to its select-able pins and lower transmission speed. Commonly the Nokia 5110 LCD is unable to operates at high clock frequency. It should be below 500kbps.

Schematic:

dsPIC30F2010 and Nokia 5110 LCD Software SPI in MikroC
Schematic Diagram

 

In this example, I use this LCD to shows some texts on screen. I can not put any additional graphic due to its limited ROM. The dsPIC30F2010 has only 12kBytes of ROM space. 

MikroC Source Code:


  1. #include "font.c"

  2. sbit Chip_Select at LATE0_bit;
  3. sbit SoftSpi_CLK at LATE1_bit;
  4. sbit SoftSpi_SDI at RE2_bit;
  5. sbit SoftSpi_SDO at LATE3_bit;

  6. sbit RST at LATE4_bit;
  7. //sbit CS at LATE5_bit;
  8. sbit D_C at LATE5_bit;

  9. sbit Chip_Select_Direction at TRISE0_bit;
  10. sbit SoftSpi_CLK_Direction at TRISE1_bit;
  11. sbit SoftSpi_SDI_Direction at TRISE2_bit;
  12. sbit SoftSpi_SDO_Direction at TRISE3_bit;

  13. sbit RST_Direction at TRISE4_bit;
  14. //sbit CS_Direction at TRISE5_bit;
  15. sbit D_C_Direction at TRISE5_bit;

  16. #define LCD_C 0
  17. #define LCD_D 1

  18. #define LCD_X 84
  19. #define LCD_Y 48

  20. void LcdCharacter( char charactor);
  21. void LcdClear(void);
  22. void LcdInitialize(void);
  23. void LcdString( char *charactor);
  24. void LcdWrite( char dc,unsigned char _data);
  25. void setXy(char x,char y);

  26. void main() {
  27. LcdInitialize();
  28. LcdClear();
  29. setXy(0,0);
  30. LcdString("MikroC dsPIC");
  31. setXy(0,1);
  32. LcdString("Nokia 5510");
  33. setXy(0,2);
  34. LcdString("Monochrome");
  35. setXy(0,3);
  36. LcdString("LCD Example");
  37. setXy(0,4);
  38. LcdString("dsPIC30F2010");
  39. setXy(0,5);
  40. LcdString("16-bit MCU");

  41. while(1){

  42. }
  43. }

  44. void LcdCharacter( char character){
  45. int i;
  46. LcdWrite(LCD_D,0x00);
  47. for(i=0;i<5;i++) LcdWrite(LCD_D,ASCII[character-0x20][i]);
  48. LcdWrite(LCD_D,0x00);
  49. }

  50. void LcdClear(void){
  51. int i;
  52. for(i=0;i<LCD_X*LCD_Y/8;i++) LcdWrite(LCD_D,0x00);
  53. }

  54. void LcdInitialize(void){
  55. Chip_Select_Direction = 0; // Set CS# pin as Output
  56. RST_Direction = 0;
  57. D_C_Direction = 0;
  58. Soft_SPI_Init(); // Initialize Soft_SPI

  59. RST=0;
  60. RST=1;
  61. Chip_Select=1;

  62. LcdWrite(LCD_C,0x21); // LCD Extended Commands
  63. LcdWrite(LCD_C,0xB0); // SET LCD CONTRAST
  64. LcdWrite(LCD_C,0x04); // set temp coefficient 0x04
  65. LcdWrite(LCD_C,0x14); // LCD bias 1:48 0x13
  66. LcdWrite(LCD_C,0x20);
  67. LcdWrite(LCD_C,0x0C); // LCD normal Mode
  68. }

  69. void LcdString( char *character){
  70. while(*character) LcdCharacter(*character++);
  71. }

  72. void LcdWrite( char _dc, char _data){
  73. D_C =_dc;
  74. Chip_Select=0;
  75. Soft_SPI_Write(_data);
  76. Chip_Select=1;
  77. }

  78. /*Set the cursor*/
  79. void setXy(char x,char y){
  80. /*x ranges from 0 to 83*/
  81. LcdWrite(LCD_C, 0x80+(6*x));
  82. /*y ranges from 0 to 5*/
  83. LcdWrite(LCD_C, 0x40+y);
  84. }

 

I tested this example, on my DIY dsPIC30F2010 Prototype Board. The LCD dots is not clear due to its poor quality.

  

 

Monday, October 12, 2026

dsPIC30F2010 and SN74HC595N 16x4 Character LCD

Introduction

The SN74HC595N outputs can control any devices such relays, LED, or even a HD44780-based character LCD. Using a single SN74HC595N shift registers a master MCU can control a character LCD using the LCD 4-bit data transfer mode.

 

dsPIC30F2010 and SN74HC595N 16x4 Character LCD
Information Screen

I made my own serial character LCD using a SN74HC595N chip, a TC1604-01 16x4 HD44780 LCD, some passive components, and a DIY PCB.

 

 

 

dsPIC30F2010 and SN74HC595N 16x4 Character LCD
DIY SN74HC595N 16x4 Serial LCD using TC1604-01 HD44780

However using its 4-bit data transfer mode, we need to care about the LCD RS and Enable Pin since the nibbles have to transfer twice. 

dsPIC30F2010 LCD Programming in MikroC

I need to write my own LCD driver routine for this example. However the source code is difficult than using the direct 4-bit LCD interface.

We can wire your own SPI LCD using the schematic below.

Schematic: 

 

dsPIC30F2010 and SN74HC595N 16x4 Character LCD
Schematic Diagram

 

However the 16x2 and the 16x4 LCD pin outs are the same. We can use one of these.

In this example, the dsPIC30F2010 show some texts on this serial LCD module. 

MikroC Source Code:

 

  1. /*TWI LCD Driver*/
  2. #define RS 1
  3. #define RW 2
  4. #define EN 3
  5. #define BL 0

  6. // Chip Select Pin
  7. sbit Chip_Select at LATE3_bit;
  8. sbit Chip_Select_Direction at TRISE3_bit;

  9. char backLight=0;

  10. void lcd_delay(unsigned int counts){
  11. unsigned int i=0;
  12. for (i=0;i<counts;i++);
  13. }

  14. void spi_lcd_command(char command){
  15. char _data;
  16. _data=command&0xF0;
  17. SPI1_Write(_data|(backLight<<BL)|(1<<EN));
  18. Chip_Select = 0; // Select SPI chip
  19. Chip_Select = 1; // Deselect SPI chip

  20. SPI1_Write(_data|(backLight<<BL));
  21. Chip_Select = 0; // Select SPI chip
  22. Chip_Select = 1; // Deselect SPI chip

  23. _data=command<<4;
  24. SPI1_Write(_data|(backLight<<BL)|(1<<EN));

  25. Chip_Select = 0; // Select SPI chip
  26. lcd_delay(10);

  27. Chip_Select = 1; // Deselect SPI chip
  28. SPI1_Write(_data|(backLight<<BL));
  29. Chip_Select = 0; // Select SPI chip
  30. Chip_Select = 1; // Deselect SPI chip
  31. }

  32. void spi_lcd___data(char command){
  33. char __data;
  34. __data=command&0xF0;
  35. SPI1_Write(__data|(backLight<<BL)|(1<<EN)|(1<<RS));
  36. Chip_Select = 0; // Select SPI chip
  37. Chip_Select = 1; // Deselect SPI chip
  38. SPI1_Write(__data|(backLight<<BL)|(1<<RS));
  39. Chip_Select = 0; // Select SPI chip
  40. Chip_Select = 1; // Deselect SPI chip
  41. lcd_delay(50);

  42. __data=command<<4;
  43. SPI1_Write(__data|(backLight<<BL)|(1<<EN)|(1<<RS));
  44. Chip_Select = 0; // Select SPI chip
  45. Chip_Select = 1; // Deselect SPI chip
  46. SPI1_Write(__data|(backLight<<BL)|(1<<RS));
  47. Chip_Select = 0; // Select SPI chip
  48. Chip_Select = 1; // Deselect SPI chip
  49. }

  50. void spi_lcd_xy(char x, char y){
  51. //16x2
  52. //char addr[]={0x80,0xC0};
  53. //16x4
  54. char addr[]={0x80,0xC0,0x90,0xD0};
  55. spi_lcd_command(addr[y-1]+x-1);
  56. }

  57. void spi_lcd_line_1(void){
  58. spi_lcd_command(0x80);
  59. }

  60. void spi_lcd_line_2(void){
  61. spi_lcd_command(0xC0);
  62. }

  63. void spi_lcd_line_3(void){
  64. spi_lcd_command(0x90);
  65. }

  66. void spi_lcd_line_4(void){
  67. spi_lcd_command(0xD0);
  68. }

  69. void spi_lcd_cursor_off(void){
  70. spi_lcd_command(0x0C);
  71. }

  72. void spi_lcd_text(char *txt){
  73. while(*txt) spi_lcd___data(*txt++);
  74. }

  75. void i2c_lcdClear(void){
  76. spi_lcd_command(0x01);
  77. Delay_ms(10);
  78. }

  79. void spi_lcd_init(void){

  80. SPI1_Write(0);
  81. lcd_delay(500);
  82. spi_lcd_command(0x33);
  83. lcd_delay(10);
  84. spi_lcd_command(0x32);
  85. lcd_delay(10);
  86. spi_lcd_command(0x28);
  87. lcd_delay(10);
  88. spi_lcd_command(0x0F);
  89. lcd_delay(10);
  90. spi_lcd_command(0x01);
  91. Delay_ms(20);
  92. spi_lcd_command(0x06);
  93. lcd_delay(50);
  94. }

  95. void main() {
  96. Chip_Select = 1;
  97. Chip_Select_Direction = 0; // Set CS# pin as Output
  98. SPI1_Init(); // Initialize SPI module
  99. spi_lcd_init();
  100. Chip_Select = 1;
  101. spi_lcd_line_1();
  102. spi_lcd_text("dsPIC30F2010 SPI");
  103. spi_lcd_line_2();
  104. spi_lcd_text("SN74HC595N LCD");
  105. spi_lcd_line_3();
  106. spi_lcd_text("Programming with");
  107. spi_lcd_line_4();
  108. spi_lcd_text("MikroC for dsPIC");
  109. while(1){
  110. }
  111. }

 

I tested this program on my DIY dsPIC30F1010 Prototype Board. It works fine. 

 

dsPIC30F2010 and SN74HC595N 16x4 Character LCD
DIY dsPIC30F1010 Prototype Board

 

 

dsPIC30F2010 Simple DVM Serial LCD

There are one on-board POT. So we can make a simple 5VDC serial display digital voltmeter.  The variable DC input voltage is connect to RB4(AN4) pin via  a POT. Its maximum measurement is 5VDC since the supply and ADC reference voltage is 5VDC.


dsPIC30F2010 and SN74HC595N 16x4 Character LCD
dsPIC30F2010 and SN74HC595N 16x4 Character LCD


MikroC Source Code:

 

  1. /*TWI LCD Driver*/
  2. #define RS 1
  3. #define RW 2
  4. #define EN 3
  5. #define BL 0

  6. // Chip Select Pin
  7. sbit Chip_Select at LATE3_bit;
  8. sbit Chip_Select_Direction at TRISE3_bit;

  9. char backLight=0;

  10. void lcd_delay(unsigned int counts){
  11. unsigned int i=0;
  12. for (i=0;i<counts;i++);
  13. }

  14. void spi_lcd_command(char command){
  15. char _data;
  16. _data=command&0xF0;
  17. SPI1_Write(_data|(backLight<<BL)|(1<<EN));
  18. Chip_Select = 0; // Select SPI chip
  19. Chip_Select = 1; // Deselect SPI chip

  20. SPI1_Write(_data|(backLight<<BL));
  21. Chip_Select = 0; // Select SPI chip
  22. Chip_Select = 1; // Deselect SPI chip

  23. _data=command<<4;
  24. SPI1_Write(_data|(backLight<<BL)|(1<<EN));

  25. Chip_Select = 0; // Select SPI chip
  26. lcd_delay(10);

  27. Chip_Select = 1; // Deselect SPI chip
  28. SPI1_Write(_data|(backLight<<BL));
  29. Chip_Select = 0; // Select SPI chip
  30. Chip_Select = 1; // Deselect SPI chip
  31. }

  32. void spi_lcd___data(char command){
  33. char __data;
  34. __data=command&0xF0;
  35. SPI1_Write(__data|(backLight<<BL)|(1<<EN)|(1<<RS));
  36. Chip_Select = 0; // Select SPI chip
  37. Chip_Select = 1; // Deselect SPI chip
  38. SPI1_Write(__data|(backLight<<BL)|(1<<RS));
  39. Chip_Select = 0; // Select SPI chip
  40. Chip_Select = 1; // Deselect SPI chip
  41. lcd_delay(50);

  42. __data=command<<4;
  43. SPI1_Write(__data|(backLight<<BL)|(1<<EN)|(1<<RS));
  44. Chip_Select = 0; // Select SPI chip
  45. Chip_Select = 1; // Deselect SPI chip
  46. SPI1_Write(__data|(backLight<<BL)|(1<<RS));
  47. Chip_Select = 0; // Select SPI chip
  48. Chip_Select = 1; // Deselect SPI chip
  49. }

  50. void spi_lcd_xy(char x, char y){
  51. //16x2
  52. //char addr[]={0x80,0xC0};
  53. //16x4
  54. char addr[]={0x80,0xC0,0x90,0xD0};
  55. spi_lcd_command(addr[y-1]+x-1);
  56. }

  57. void spi_lcd_line_1(void){
  58. spi_lcd_command(0x80);
  59. }

  60. void spi_lcd_line_2(void){
  61. spi_lcd_command(0xC0);
  62. }

  63. void spi_lcd_line_3(void){
  64. spi_lcd_command(0x90);
  65. }

  66. void spi_lcd_line_4(void){
  67. spi_lcd_command(0xD0);
  68. }

  69. void spi_lcd_cursor_off(void){
  70. spi_lcd_command(0x0C);
  71. }

  72. void spi_lcd_text(char *txt){
  73. while(*txt) spi_lcd___data(*txt++);
  74. }

  75. void i2c_lcdClear(void){
  76. spi_lcd_command(0x01);
  77. Delay_ms(10);
  78. }

  79. void spi_lcd_init(void){

  80. SPI1_Write(0);
  81. lcd_delay(500);
  82. spi_lcd_command(0x33);
  83. lcd_delay(10);
  84. spi_lcd_command(0x32);
  85. lcd_delay(10);
  86. spi_lcd_command(0x28);
  87. lcd_delay(10);
  88. spi_lcd_command(0x0C);
  89. lcd_delay(10);
  90. spi_lcd_command(0x01);
  91. Delay_ms(20);
  92. //spi_lcd_command(0x06);
  93. lcd_delay(50);
  94. }

  95. void main() {
  96. unsigned int temp_res;
  97. float voltage=0;
  98. char text[16];
  99. TRISB = 0xFFFF; // PORTB is input
  100. ADC1_Init(); // Enable ADC module
  101. Delay_ms(10);
  102. Chip_Select = 1;
  103. Chip_Select_Direction = 0; // Set CS# pin as Output
  104. SPI1_Init(); // Initialize SPI module
  105. spi_lcd_init();
  106. Chip_Select = 1;
  107. spi_lcd_line_1();
  108. spi_lcd_text("dsPIC30F2010 ADC");
  109. spi_lcd_line_2();
  110. spi_lcd_text("SN74HC595N SPI");
  111. spi_lcd_line_3();
  112. spi_lcd_text("LCD Voltmeter");
  113. spi_lcd_line_4();
  114. spi_lcd_text("MikroC for dsPIC");
  115. Delay_ms(5000);
  116. spi_lcd_command(0x01);
  117. Delay_ms(20);
  118. while(1){
  119. // Get 10-bit results of AD conversion
  120. temp_res = ADC1_Read(4);
  121. voltage = (5.0 * temp_res)/1023;
  122. spi_lcd_line_1();
  123. spi_lcd_text(" AN4 ADC:");
  124. spi_lcd_line_2();
  125. sprintf(text," %4d Decimal",temp_res);
  126. spi_lcd_text(text);
  127. spi_lcd_line_3();
  128. spi_lcd_text(" Voltage:");
  129. spi_lcd_line_4();
  130. sprintf(text," %0.4f Volts",voltage);
  131. spi_lcd_text(text);
  132. Delay_ms(500);
  133. }
  134. }


DIY dsPIC30F2010 Prototype Board:

 

dsPIC30F2010 and SN74HC595N 16x4 Character LCD
ADC Voltage Reading


dsPIC30F2010 and SN74HC595N 16x4 Character LCD
ADC Voltage Reading


dsPIC30F2010 and SN74HC595N 16x4 Character LCD
ADC Voltage Reading


dsPIC30F2010 and SN74HC595N 16x4 Character LCD
Information Screen

 

 


 

 

 

 

dsPIC30F2010 SPI Display 5VDC DVM using MikroC

In previous example, I use the SPI module of the dsPIC30F2010 to control a serial LED display and seven-segment display. Now let put them together making a serial display digital volt-meter.

 

dsPIC30F3011 SPI Display 5VDC DVM using MikroC
ADC Reading 

 

There is one on-board POT so I use it to adjust input voltage that varies between 0 and +5VDC. It will show the reading voltage on a serial seven-segment display.

Schematic: 

dsPIC30F2010 SPI Programming Example in MikroC
Schematic Diagram

This is just schematic using device symbols. I can not be simulated like other build-in models. I download the dsPIC30F2010 symbol from SnapEDA for free. 

 

MikroC Source Code: 



  1. // Chip Select Pin
  2. sbit Chip_Select at LATE3_bit;
  3. sbit Chip_Select_Direction at TRISE3_bit;

  4. void SN74595_Send(char _data){
  5. SPI_Write(_data); // Send high byte via SPI
  6. Chip_Select = 0; // Select SPI chip
  7. Chip_Select = 1; // Deselect SPI chip
  8. }

  9. // Common Cathod Segment Data
  10. const char cc[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
  11. 0x7F,0x6F,0x77,0x7C,0x58,0x5E,0x79,0x71};

  12. void show_number(char number){
  13. SN74595_Send(~cc[number]);
  14. }



  15. void main() {
  16. unsigned int temp_res;
  17. float voltage=0;
  18. char digit=0;
  19. Chip_Select = 1; // Deselect DAC
  20. Chip_Select_Direction = 0; // Set CS# pin as Output
  21. SPI1_Init(); // Initialize SPI module
  22. TRISB = 0xFFFF; // PORTB is input
  23. TRISD = 0; // PORTD is output
  24. TRISF = 0; // PORTF is output
  25. ADC1_Init(); // Enable ADC module
  26. while(1){
  27. temp_res = ADC1_Read(4); // Get 10-bit results of AD conversion
  28. voltage = (5.0 * temp_res)/1023;
  29. digit = (char)voltage;
  30. show_number(digit);
  31. Delay_ms(500);
  32. }

  33. }

 
Using a 0.5 second delay time making the display run very smooth without glitching. It could saves the power consumption since the ADC reading is not so frequently. For more information about using the ADC please read this post.

 

dsPIC30F3011 SPI Display 5VDC DVM using MikroC
Zero Volt ADC Reading


dsPIC30F3011 SPI Display 5VDC DVM using MikroC
3 Volt ADC Reading

dsPIC30F3011 SPI Display 5VDC DVM using MikroC
5 Volt ADC Reading

 I test example using my DIY dsPIC30F1010 Prototype Board. For more information about this PCB see this post.

 


 

 

 

Adskeep- Standard Ads

336x280

DIY Electronic Projects And Instruments

AdsKeeper - 2091654

Labels

23K256 (1) 24C16B (2) 25AA010A (2) 8051 (7) 93AA46B (1) ADC (39) Analog Comparator (1) Arduino (16) ARM (32) AT89C52 (7) ATMega32 (59) ATMega644P (27) AVR (88) AVR PCB (2) Bootloader (1) CCS PICC (31) Change Notify Interrupt (CNI) (2) DAC (2) DHT11 (5) Display (156) Distance Sensor (3) dot matrix (1) ds1307 (10) DS18B20 (6) ds3231 (1) ds3232 (2) dsPIC (13) dsPIC30F1010 (3) dsPIC30F2010 (13) EEPROM (5) Environment Sensor (6) ESP32 (1) esp8266 (1) Graphical LCD (3) HD44780 (10) I2C (38) ILI9341 (1) Input/Output (83) Interrupt (22) IoT PCB (1) Keil (5) Keypad (16) KS0108 (3) LCD (85) LM35 (4) Master/Slave (2) MAX7221 (1) MCP23017 (8) MCP23S17 (7) MCP4921 (1) MCP4922 (2) Meter (3) MikroC (2) MikroC ARM (1) MikroC dsPIC (8) Module PCB (2) Motor (15) MPLABX (73) Nokia 5110 LCD (5) OLED (2) One-Wire (7) Oscillator (8) PCB (13) PCD8544 (3) PCF8574 (10) PIC (117) PIC12F (3) PIC16 (105) PIC16F628A (3) PIC16F630 (2) PIC16F716 (4) PIC16F818 (11) PIC16F818/819 (3) PIC16F84A (16) PIC16F876A (2) PIC16F877A (9) PIC16F88 (2) PIC16F887 (60) PIC18 (19) PIC18F1220 (5) PIC18F2550 (5) PIC18F4550 (12) PICKit2 (1) PICMicro PCB (4) Pin Change Interrupt (1) PWM (12) RTC (12) SBN0064G (1) Sensor (15) SH1106 (3) Shift Register (15) Shift Registers (19) SN74HC595N (9) Software SPI (1) Software TWI (2) SPI (44) sprinf (3) ST7735 (1) STM32 (29) STM32 Black Pill (1) STM32 Blue Pill (12) STM32 HAL (23) STM32CubeIDE (32) STM32F103C8T6 (9) STM32F103R6 (18) STM32F401CCU6 (1) SysTick (7) temperature sensor (15) TFT (1) TG12864A (1) Thermometer (22) Timer/Counter (32) TM1637 (2) twi (10) UART (11) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (96)