Overview
dsPIC30F2010 is a 16-bit Digital Signal Controller from Microchip Technology. This 28-pin PICMicro has a 10-bit ADC module with up to 1MSPS conversion rate. It able to operates up to 30MIPs.
![]() |
PCBWay.com Sponsor PCB Project |
I have two dsPIC30 device that I bought from online store many years now. They have small pin counts and small-size Flash memory suitable for some simple control applications.
![]() |
dsPIC30F2010-20I/SP I have |
I have as SMD adapter for soldering the dsPIC30FF1010-30I/SP for breadboard prototyping. This chip has a high speed ADC.
![]() |
dsPIC30F1010-30I/SO I have |
Proteus VSM has a large amount of libraries that is suitable for this simple PCB design.
![]() |
3D Model in Proteus |
![]() |
3D Model in Proteus |
![]() |
3D Model in Proteus |
![]() |
3D Model in Proteus |
![]() |
3D Model in Proteus |
![]() |
Soldered PCBA |
dsPIC30F1010 is 16-bit Digital Signal Controller enhanced for SMPS application. It has a 10-bit ADC module with the conversion speed up to 2000kSPS. It also able to operate up to 20MIPs.
![]() |
A dsPIC30F2010 DIP |
![]() |
A dsPIC30F1010 DIP |
These DIP micro-controllers can easily prototype on a breadboard. However we can create a simple prototype board for these chip from scratch. I designed a prototype board for these chips with a PICKit2 programmer to make it self and easier to prototype.
Circuit Design
I use Proteus VSM to design the schematics for this board. Most of parts are already have in Protues while other parts are downloaded from snapeda website.
I putted some major modules on this board:
- PICKit2 programmer
- dsPIC30F2010 and dsPIC30F1010 IC socket
- RS-232 to TTL converter
- ADC inputs
- Switches inputs,
- LEDs outputs
- Male header for external connection
![]() |
Schematic Sheet #1 |
![]() |
Schematic Sheet #2 |
![]() |
Schematic Sheet #3 |
I use three A4 size sheet of this design.
PCB Design
Protues PCB design is very easy to use and light weight. It also have a 3D preview tool and Gerber file exporting and viewing tool.
![]() |
PCB Design in Protues |
This PCB is approximately 10cmx10cm in size. I use two layers of copper because it is convenience. Furthermore this size of PCB is very low cost to fabricate using any popular PCB manufacturer such as PCBWay .
![]() |
Top Copper |
![]() |
Bottom Copper |
![]() |
Top Silk |
It's difficult to fabricate this double-side PCB at home using a CNC machine or toner transfer method. This PCB can be fabricate at very low cost by many PCB manufacturers.
PCB Fabrication
I have been using PCBWay for many years now. PCBWay fabricate PCBs at low cost, fast processing time for only 24 hours, and fast delivery time using any carrier options. This double side 10cmx10cm can be fabricate at only 5USD for 5 to 10pcs by PCBWay. It's a standard PCB with silk screen and solder mask.
![]() |
10 PCBs for only 5USD |
For different size of PCB we can instantly quote on PCBWay website using a zip PCB Gerber file without account.
![]() |
PCBWay Instant Quote |
We can accurately see the preview of fabricated PCB generated by the company's online Gerber file viewer.
![]() |
Top Side |
![]() |
Bottom Side |
PCBWay also offer PCBA assembly service at reasonable price.
![]() |
PCBWay PCB Assembly Service |
Click here to download this PCB design
![]() |
PIC18F4550 and DSPIC30F2010 PCB fabrication from PCBWay.com |
![]() | ||
A box of two PCB for PIC18F4550 and dsPIC30F2010 Prototype Board sponsored by PCBWay |
A PCB package of 5-pcs |
![]() |
A PCB package of 5-pcs |
The PCB processing time is only one day with a few days of delivery time. DHL logistic is preferred by PCBWay and customers.
It's a standard and high quality PCB. Finished PCB needs a surface treatment process to treat them from corrosion. So even we don't solder them instantly its quality is not defected by outside environment.
For this 5USD PCB order, we can choose different colors of solder mask and silk screen legend as preferred. The standard thickness is 1.6mm that is robust enough for most of application. We can order up to 10 units for only 5USD.
PCB Assembling
PCBWay offers PCB assembling service for a wide range of order with a minimum order of 25 units at a reasonable price.
![]() |
Soldering PCB Kit |
It takes one day to assemble and test this PCBA. The circuit working is correct. Some drill holes have problems so I need to correct it later.
![]() |
PCBA Top Side |
I tested this PCBA with my PC program to to the PICKit2 device programmer. Everything works well.
![]() |
Power Supply Testing |
I test it with PICKit2 on host software. It's error free.
![]() |
PICKit2 Software Test |
![]() |
PICKit2 Software |
I putted a two-row machine-tool female pin header to optionally place a dsPIC30F1010-30I/SO I soldered on an SMD IC adapter board.
![]() |
A dsPIC30F2010-20I/SP and a dsPIC30F1010-30I/SP that could fit on this PCBA |
I needed to remove dsPIC30F2010 from this PCBA first before placing the dsPIC30F1010 chip.
![]() |
Testing the dsPIC30F1010 on this PCBA |
This chip could programmed with the earlier version of PICKIT programmer, PICKIT2.
![]() |
Testing the dsPIC30F1010-30I/SP with PICKIT2 |
Click here to download this PCB design.
If you don't have a USB programmer for the on-board PICKIT2 device programmer. You can use a simple serial port JDM programmer with WINPIC800 PC software.
CCS PICC Sample Code
CCS PICC is very easy to use but we need to pay for license. For beginners with with this embedded C compiler using its project wizard is a good choice.
Using Project 24 Bit Wizard
We can use this wizard for dsPIC30F2010 since it's a 24-bit instruction device.
![]() |
LED Blinking Using Wizard - Device Settings |
![]() |
LED Blinking Using Wizard - Blinking Example |
It will generate source code for us.
- #include <main.h>
- void main()
- {
- //Example blinking LED program
- while(true)
- {
- output_low(LED);
- delay_ms(DELAY);
- output_high(LED);
- delay_ms(DELAY);
- }
- }
Its main.h file is separated from main.c file.
- #include <30F2010.h>
- #device ICSP=1
- #use delay(clock=20000000)
- #FUSES NOWDT //No Watch Dog Timer
- #FUSES CKSFSM
- //Clock Switching is enabled, fail Safe clock monitor is enabled
- #define LED PIN_D0
- #define DELAY 1000
In the #use delay directive I have the parameter crystal=20000000 to clock=20000000 to prevent error.
Click here to download this program example.
On Board LED Blinking
On this PCBA there are two LEDs connects to RD0 and RD1 respectively. So I wrote a simple PIC24 C program to toggle these two LEDs.
- #include "board.h"
- void main()
- {
- //Example blinking LED program
- while(true)
- {
- output_low(LED0);
- output_high(LED1);
- delay_ms(DELAY);
- output_high(LED0);
- output_low(LED1);
- delay_ms(DELAY);
- }
- }
I also separate its board.h header file as lists below.
- #include <30F2010.h>
- #device ICSP=1
- #fuses HS,NODEBUG,NOWDT,PR,CKSFSM
- #use delay(crystal=20000000)
- #define LED0 PIN_D0
- #define LED1 PIN_D1
- #define DELAY 500
I use its on-board 20MHz crystal oscillator instead of a 10MHz oscillator because I can not use its PLL to get its maximum 20MHz frequency. So this crystal oscillator will directly drive the processor.
Click here to download this sample program.
Tactile Switches and LEDs
There are two push button connect to RC13 and RC14 of dsPIC30F2010 PCBA respectively. I use software polling from these two switches to toggle two on-board LEDs of RD0 and RD1 respectively.
- #include "board.h"
- void main()
- {
- set_pullup(TRUE,PIN_C13);
- set_pullup(TRUE,PIN_C14);
- while(TRUE)
- {
- //TODO: User Code
- if(input(SW0)==0){
- output_toggle(LED0);
- delay_ms(500);
- }
- if(input(SW1)==0){
- output_toggle(LED1);
- delay_ms(500);
- }
- }
- }
I also modify its main.h file adding two buttons definition.
- #include <30F2010.h>
- #device ICSP=1
- #fuses HS,NODEBUG,NOWDT,PR,CKSFSM
- #use delay(crystal=20000000)
- #define LED0 PIN_D0
- #define LED1 PIN_D1
- #define SW0 PIN_C13
- #define SW1 PIN_C14
- #define DELAY 500
I don't use ICD feature due to complexity, and I don't this hardware.
Click here to download this sample program.
RS-232 To TTL UART Converter
I putted a DB9 COM Port connector on this board for device and host PC communication. However I don't use its standard MAX232 level converter. Instead I use transistor level converter.
This is a sample program for on-board UART.
- #include "board.h"
- #use rs232(UART1, baud=9600, stream=UART_PORT1)
- void main()
- {
- long cnt=0;
- printf("HELLO WORLD!\n\r");
- printf("Saturady 13 September 2025\n\r");
- printf("dsPIC30F2010 DIY Prototype Board.\n\r");
- printf("UART To RS-232 Demo Program\n\r");
- while(TRUE)
- {
- //TODO: User Code
- printf("Time In Seconds: %Lu \n\r",cnt);
- output_toggle(LED0);
- cnt++;
- delay_ms(1000);
- }
- }
The board.h file is the same as above.
- #include <30F2010.h>
- #device ICSP=1
- #fuses HS,NODEBUG,NOWDT,PR,CKSFSM
- #use delay(crystal=20000000)
- #define LED0 PIN_D0
- #define LED1 PIN_D1
- #define SW0 PIN_C13
- #define SW1 PIN_C14
- #define DELAY 500
It will print the following text. LED connects to RD0 toggle every time the UART send data.
![]() |
CCS PICC Serial Input Output Monitor |
Click here to download this sample program.
Analog to Digital Converter
There are one potentiometer and LM35 temperature sensor on this PCBA. The following C example use the 10-bit ADC module of dsPIC30F2010 to read the ADC value from these two on-board devices.
The following demo program shows a simple ADC reading and sending data over serial port terminal.
- #include "board.h"
- void main()
- {
- unsigned int16 adc_value = 0;
- float analog=0;
- set_pullup(TRUE,PIN_C13);
- set_pullup(TRUE,PIN_C14);
- output_high(LED0);
- setup_adc_ports(sAN4 | sAN5);
- setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_31);
-
- printf("dsPIC30F2010 CCS PICC ADC and UART Example\n\r");
- printf("Using dsPIC30F2010 Prototype Board\n\r");
- printf("Wednesday 10-Sept-2025\n\r");
- printf("**************************************************\n\r");
- delay_ms(100);
-
- while(TRUE)
- {
- //TODO: User Code
- set_adc_channel(4);
- delay_us(50);
- adc_value = read_adc();
- analog = (5.0*adc_value)/1023;
- printf("AN4: %4d Decimal %f Volts\n\r",adc_value, analog);
- output_toggle(LED0);
-
- set_adc_channel(5);
- delay_us(50);
- adc_value = read_adc();
- analog = (500.0*adc_value)/1023;
- printf("AN5: %4d Decimal %f Degree Celsius\n\r",adc_value, analog);
- printf("**************************************************\n\r");
- output_toggle(LED1);
- delay_ms(1000);
- }
- }
I put some definition and declaration in the "board.h" header file.
- #include <30F2010.h>
- #device ADC=10
- #device ICSP=1
- #fuses HS,NODEBUG,NOWDT,PR,CKSFSM
- #use delay(crystal=20000000)
- #use FIXED_IO( D_outputs=PIN_D1,PIN_D0 )
- #use rs232(UART1, baud=9600, stream=UART_PORT1)
- #define LED0 PIN_D0
- #define LED1 PIN_D1
- #define SW0 PIN_C13
- #define SW1 PIN_C14
- #define DELAY 500
Two on-board LEDs blink every time the ADC reading and data transmitting completed.
![]() |
on-board ADC reading and data transmission |
![]() |
Received data on serial port terminal of CCS PICC IDE |
Click here to download this sample program.
The HD44780 16x2 Character LCD Interfacing
The Hitachi HD44780 industrial standard alphanumeric LCD interfacing is very interesting for most of novice micro-controller programming. However there are many new replacing controller chip for this device that operate in the same way. They are available in many forms and at very low price.
![]() |
A 16x2 HD44780 based LCD |
![]() |
A 16x2 HD44780 based LCD |
CCS PIC has its own LCD driver library for its C compiler. It works in most of device. Its 4-bit bi-directional interfacing doesn't rely on fixed pin mode. The programmer can select any available micro-controller pins.
- #include "board.h"
- #define LCD_ENABLE_PIN PIN_E5
- #define LCD_RS_PIN PIN_E4
- #define LCD_RW_PIN PIN_C14
- #define LCD_DATA4 PIN_E0
- #define LCD_DATA5 PIN_E1
- #define LCD_DATA6 PIN_E2
- #define LCD_DATA7 PIN_E3
- #include <LCD.C>
- void main()
- {
- long run_time=0;
- lcd_init();
- lcd_putc("\f");
- printf(LCD_PUTC,"HELLO WORLD!\n");
- printf(LCD_PUTC,"dsPIC30F2010 LCD");
- delay_ms(5000);
- lcd_putc("\f");
- printf(LCD_PUTC,"CCS PICC\n");
- printf(LCD_PUTC,"Example....");
- delay_ms(5000);
- lcd_putc('\f');
-
- while(TRUE)
- {
- //TODO: User Code
- lcd_putc('\a');
- printf(LCD_PUTC,"ON TIME: \n%Lu Seconds",run_time);
- run_time++;
- delay_ms(1000);
- }
- }
Its "board.h" header file is the same as above example. Click here to download this sample program.
![]() |
Start-Up Screen #2 |
![]() |
Start-Up Screen #1 |
![]() |
Running Program |
Click here to download this sample program.
Using The TC1604A-04 16x4 LCM Module
I have a TC1604A-04 (16x4) LCM module that work in almost the same way. It bases on the HD44780 LCD controller but with 4 lines. We can use CCS PICC "lcd.c" C driver to control this module.
![]() |
A TC1604A-04 LCM Module |
![]() |
A TC1604A-04 LCM Module |
It uses the SPLC780D1 controller IC instead of a conventional HD44780 controller chip.
![]() |
The TC1604A-04 Block Diagram |
The original "lcd.c" driver file able to handle only two lines of LCD. To control a four-line LCD module we just add the LCD command.
![]() |
TC1604A-04 Display Data RAM (DD RAM) |
We just send the LCD command that's the DDRAM Address of each lines. For instance, the lcd_send_byte(0,0xD0) of "lcd.c" driver set the display line to line 4 of this LCD. I optionally write some macros for new lines and LCD clearance.
- #include "board.h"
- #define LCD_ENABLE_PIN PIN_E5
- #define LCD_RS_PIN PIN_E4
- #define LCD_RW_PIN PIN_C14
- #define LCD_DATA4 PIN_E0
- #define LCD_DATA5 PIN_E1
- #define LCD_DATA6 PIN_E2
- #define LCD_DATA7 PIN_E3
- #include <LCD.C>
- #define line_1() lcd_send_byte(0,0x80);
- #define line_2() lcd_send_byte(0,0xC0);
- #define line_3() lcd_send_byte(0,0x90);
- #define line_4() lcd_send_byte(0,0xD0);
- #define lcd_clear() lcd_putc('\f');
- void main()
- {
- long run_time=0;
- lcd_init();
- lcd_clear();
- printf(LCD_PUTC,"dsPIC30F2010 LCD\n");
- printf(LCD_PUTC,"20x4 Characters");
- line_3();
- printf(LCD_PUTC,"Example With");
- line_4()
- printf(LCD_PUTC,"CCS PICC 5.119");
- delay_ms(5000);
- lcd_putc('\f');
- while(TRUE)
- {
- //TODO: User Code
- lcd_putc('\a');
- printf(LCD_PUTC,"ON TIME: \n%Lu Seconds",run_time);
- run_time++;
- delay_ms(1000);
- }
- }
It also depends on the "board.h" header file.
- #include <30F2010.h>
- #device ICSP=1
- #fuses HS,NODEBUG,NOWDT,PR,CKSFSM
- #use delay(crystal=20000000)
- #use FIXED_IO( D_outputs=PIN_D1,PIN_D0 )
- #use rs232(UART1, baud=9600, stream=UART_PORT1)
- #define LED0 PIN_D0
- #define LED1 PIN_D1
- #define SW0 PIN_C13
- #define SW1 PIN_C14
- #define DELAY 500
It works fine with my prototype board.
Click here to download this sample program.
On-board ADC and 16x4 Interfacing
A 16x4 LCD is suitable for reading two ADC channel inputs. I connect this PCBA to an external TC1604A-04 character LCD module to display ADC reading, one is an analog voltage while another is the LM35DZ temperature sensor.
- #include "board.h"
- #define LCD_ENABLE_PIN PIN_E5
- #define LCD_RS_PIN PIN_E4
- #define LCD_RW_PIN PIN_C14
- #define LCD_DATA4 PIN_E0
- #define LCD_DATA5 PIN_E1
- #define LCD_DATA6 PIN_E2
- #define LCD_DATA7 PIN_E3
- #include <LCD.C>
- #define line_1() lcd_send_byte(0,0x80);
- #define line_2() lcd_send_byte(0,0xC0);
- #define line_3() lcd_send_byte(0,0x90);
- #define line_4() lcd_send_byte(0,0xD0);
- #define lcd_clear() lcd_putc('\f');
- void main()
- {
- long adc_value = 0;
- float analog=0;
- lcd_init();
- setup_adc_ports(sAN4 | sAN5);
- setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_31);
- lcd_clear();
- printf(LCD_PUTC,"dsPIC30F2010 ADC");
- line_2();
- printf(LCD_PUTC,"and TC1604A-04");
- line_3();
- printf(LCD_PUTC,"LCD Interfacing");
- line_4()
- printf(LCD_PUTC,"With CCS PICC");
- delay_ms(5000);
- lcd_clear();
- while(TRUE)
- {
- //TODO: User Code
- line_1();
- printf(LCD_PUTC,"ADC Reading(DEC)");
- set_adc_channel(4);
- delay_us(10);
- adc_value = read_adc();
- analog = (5.0*adc_value)/1023;
- line_2();
- printf(LCD_PUTC, "AN4: %4d %fV\n",adc_value, analog);
- set_adc_channel(5);
- delay_us(10);
- adc_value = read_adc();
- analog = (5.0*adc_value)/1023;
- line_3();
- printf(LCD_PUTC, "AN5: %4d %fV",adc_value, analog);
- analog = (500.0*adc_value)/1023;
- line_4();
- printf(LCD_PUTC, "LM35DZ: %f%cC",analog,223);
- delay_ms(1000);
- }
- }
Its "board.h" header file is listed below.
- #include <30F2010.h>
- #device ADC=10
- #device ICSP=1
- #fuses HS,NODEBUG,NOWDT,PR,CKSFSM
- #use delay(crystal=20000000)
- #use FIXED_IO( D_outputs=PIN_D1,PIN_D0 )
- #use rs232(UART1, baud=9600, stream=UART_PORT1)
- #define LED0 PIN_D0
- #define LED1 PIN_D1
- #define SW0 PIN_C13
- #define SW1 PIN_C14
- #define DELAY 500
The LM35DZ that I bough was a fake product. The output voltage is not correct.
![]() |
On-board ADC and 16x4 Interfacing |
![]() |
On-board ADC and 16x4 Interfacing |
Click here to download this sample program.
Wiring the R/W of LCD to GND
Using the R/W pin can make the program stuck whenever the LCD has problem, or the LCD is not inserted. However we can connect the LCD R/W pin to GND to send command or data to this character LCD that is most common for most programmer. We don't need to read and wait for LCD respond for polling the LCD busy flag.
So I modify the "lcd.c" C driver to by pass the LCD R/W pin. We just wire this pin to GND. We need to copy the "lcd.c" from "..\Program Files (x86)\PICC\Drivers" to project folder and import it by using the #include "lcd.c" directive.
In project IDE we need to comment out the line while ( bit_test(lcd_read_byte(),7) ) ; and add the delay_us(1000) and delay_us(10) statement.
![]() |
Modifying the "lcd.c" driver |
The source code is almost the same but the "lcd.c" locates in project folder.
- #include "board.h"
- #define LCD_ENABLE_PIN PIN_E5
- #define LCD_RS_PIN PIN_E4
- #define LCD_RW_PIN PIN_C14
- #define LCD_DATA4 PIN_E0
- #define LCD_DATA5 PIN_E1
- #define LCD_DATA6 PIN_E2
- #define LCD_DATA7 PIN_E3
- #include "lcd.c"
- #define line_1() lcd_send_byte(0,0x80);
- #define line_2() lcd_send_byte(0,0xC0);
- #define line_3() lcd_send_byte(0,0x90);
- #define line_4() lcd_send_byte(0,0xD0);
- #define lcd_clear() lcd_putc('\f');
- void main()
- {
- long adc_value = 0;
- float analog=0;
- lcd_init();
- setup_adc_ports(sAN4 | sAN5);
- setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_31);
- lcd_clear();
- printf(LCD_PUTC,"dsPIC30F2010 ADC");
- line_2();
- printf(LCD_PUTC,"and TC1604A-04");
- line_3();
- printf(LCD_PUTC,"LCD Interfacing");
- line_4()
- printf(LCD_PUTC,"With CCS PICC");
- delay_ms(5000);
- lcd_clear();
- while(TRUE)
- {
- //TODO: User Code
- line_1();
- printf(LCD_PUTC,"ADC Reading(DEC)");
- set_adc_channel(4);
- delay_us(10);
- adc_value = read_adc();
- analog = (5.0*adc_value)/1023;
- line_2();
- printf(LCD_PUTC, "AN4: %4d %fV\n",adc_value, analog);
- set_adc_channel(5);
- delay_us(10);
- adc_value = read_adc();
- analog = (5.0*adc_value)/1023;
- line_3();
- printf(LCD_PUTC, "AN5: %4d %fV",adc_value, analog);
- analog = (500.0*adc_value)/1023;
- line_4();
- printf(LCD_PUTC, "LM35DZ: %f%cC",analog,223);
- delay_ms(1000);
- }
- }
The firmware operation is OK.
Click here to download this sample program.
Great DIY project! It's impressive how you've detailed the setup with dsPIC30F2010 and dsPIC30F1010. Projects like this really highlight the importance of well-structured PCB layouts. For those looking to take their custom electronics further, professional PCB designing services can really streamline the process and enhance performance. Thanks for sharing this resourceful post!
ReplyDelete