pia-468x60

pia-728x90

Showing posts with label CCS PICC. Show all posts
Showing posts with label CCS PICC. Show all posts

Monday, August 18, 2025

DIY PIC18F4550 Prototype Board

Overview

Using a prototype board for microcontroller hardware and firmware testing is quicker and safer than solely placing and wiring all components on breadboard. We can design and make our own simple prototype board by hand with a conventional single side PCB.

DIY PIC18F4550 Prototype Board
Finished PCBA

I have some PIC microcontrollers and a dozen of components that left from previous projects. So I decide to make my own test board for PIC18F4550 microcontroller with those components. Conventionally I use a single sided PCB with toner transfer method to make a PCB. However PCBWay offers sponsors PCB projects for electronics hobbyists and students. So it's possible to make a standard multilayer PCB.

I designed a small size PCB for PIC18F4550 or other 40-pin compatible PIC microcontrollers with an on-board PICKit2 device programmer because I have a dozen of PIC18F2550 for making a PICKit2 USB programmer.

On this board I putted some major functional blocks,

  1. +5.0VDC and +3.3VDC regulated power supply
  2. clock and reset pin
  3. RS-232 to TTL converter using max232
  4. USB connector for USB communication for PIC18F4550
  5. ADC inputs using variable resistors and LM35 analog temperature sensor
  6. I2C RTC (ds1307) and AT24C08 EEPROM
  7. Four-bit LCD (HD44780 compatible) 
  8. output LEDs
  9. input switches
  10. 40-pin male header for external circuit connections.

I also placed a male rectangle box header for programming any AVR microcontrollers using PICKit2 and AVRDude IDE.

Schematic

I use protues VSM to design schematic for this PCB because it's light-weight, user-friendly and simple to use. Its schematic contains three A4-size sheets.

DIY PIC18F4550 Prototype Board
Schematic Sheet #1


DIY PIC18F4550 Prototype Board
Schematic Sheet #2


DIY PIC18F4550 Prototype Board
Schematic Sheet #3


Some components are duplicated because they are IC socket and IC.

Printed Circuit Board

Protues also has PCB design with many device symbols and footprints. However we can install our preferred device from third party company such as snapeda.

This double-sided PCB is no worry about DIY fabrication because it's sponsored by PCBWay. The size of this PCB is 15cmx20cm that is affordable to fabricate.

DIY PIC18F4550 Prototype Board
Top Side


DIY PIC18F4550 Prototype Board
Bottom Side


DIY PIC18F4550 Prototype Board
Top Silk



Some electronics hobbyists can fabricate this double PCB at home but it's complex and hazardous. 

DIY PIC18F4550 Prototype Board
Top 3D View


DIY PIC18F4550 Prototype Board
Front 3D View


DIY PIC18F4550 Prototype Board
Back 3D View


DIY PIC18F4550 Prototype Board
Left 3D View


DIY PIC18F4550 Prototype Board
Right 3D View


Some devices doesn't exist in Protues VSM. Hence I download them from snapeda. Snapeda has over one million device libraries including schematic symbols, footprints and 3D objects. Their libraries are compatible with Protues, Cardence, Altium, KiCAD, Eagle etc. Their 3D objects are compatible with Solidwork, FreeCAD, etc. They are free of charge but we have to register an account before we get it.

PCB Fabrication

This PCB is offered by PCBWay since it's a sponsor project. PCBWay is a long term and well known one-stop service provider including PCB fabrication, PCB assembling (PCBA) etc. Their service and price are reasonable. Beside their standard PCB they offer advanced PCB, flex PCB, CNC parts and 3D printing parts.

DIY PIC18F4550 Prototype Board



Most of PCBs are fabricated within 24 hours with a few days of delivery time. All PCB are checked and verify before sending to fabrication process (pre-production check). Their engineer contact us very soon if their are any problem or doubt.

PCBWay also offer a low cost PCB fabrication of the size 10cmx10cm. We can order it between 5 and 10 units for only 5USD. They are standard double sided PCB with solder mask, silkscreen, circuit testing etc.

DIY PIC18F4550 Prototype Board


For a large scale demand we can order their PCB assembly service at reasonable price for any projects.

DIY PIC18F4550 Prototype Board


It took no more than one week to get my PCB order. It was shipped using DHL.

DIY PIC18F4550 Prototype Board
DHL package


The package is well prepared and the PCBs are well protected.

DIY PIC18F4550 Prototype Board
PCB Package from pcbway.com


DIY PIC18F4550 Prototype Board
Received PCBs


DIY PIC18F4550 Prototype Board
Received PCBs


DIY PIC18F4550 Prototype Board
Five Units of PCB


We can choose other solder mask and silk screen colors.

PCB Assembling

It takes one day of solder this board by hand with some tools, electrical solder iron, tin lead, etc. After I finished soldering I need to clean all flux residue left from tin lead soldering, using gasoline or thinner with a smooth brush.

DIY PIC18F4550 Prototype Board
PCB pre-soldering


I already test the circuit but the firmware has not yet been tested. So need to write some sample codes for this prototype board.

DIY PIC18F4550 Prototype Board
Finished PCBA #1

DIY PIC18F4550 Prototype Board
Finished PCBA #2


DIY PIC18F4550 Prototype Board
Finished PCBA #3


DIY PIC18F4550 Prototype Board
Finished PCBA #4


DIY PIC18F4550 Prototype Board
Finished PCBA #5

Click here to download its PCB design.

CCS PICC Demo Programs

CCS PICC is very easy to use. It's light-weight, fast, and effective. It targets 8-bit and 16-bit PIC microcontroller. Its free version support only some base-line 8-bit PIC micro-controllers. I start with CCS PICC due to time constraint.

LED Blinking

PIC18F4550 has both internal and external oscillator clock modes. Internal oscillator could run up to 8MHz while the external clock mode could run up to 48MHz.

The example uses its internal 8MHz oscillator to blink the LED. It will toggles all 8 pins of PORTD.

  1. #include <18F4550.h>
  2. #fuses intrc_io
  3. #use delay(clock=8M)
  4. void main(){
  5. output_d(0x00);
  6. set_tris_d(0x00);
  7. while(1){
  8. output_d(0x00);
  9. delay_ms(1000);
  10. output_d(0xFF);
  11. delay_ms(1000);
  12. }
  13. }

There's an on-board 20MHz crystal oscillator. So we can use it at 20MHz without PLL.


  1. #include <18F4550.h>
  2. #fuses HSPLL,PLL5,CPUDIV1,NOLVP,NOWDT,PUT
  3. #use delay (clock=20000000)
  4. void main(){
  5. output_d(0x00);
  6. set_tris_d(0x00);
  7. while(1){
  8. output_d(0x00);
  9. delay_ms(500);
  10. output_d(0xFF);
  11. delay_ms(500);
  12. }
  13. }


We can use its PLL that can clock up to 48MHz from and external 20MHz crystal oscillator.


  1. #include <18F4550.h>
  2. #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
  3. #use delay(clock=48000000)
  4. void main(){
  5. output_d(0x00);
  6. set_tris_d(0x00);
  7. while(1){
  8. output_d(0x00);
  9. delay_ms(1000);
  10. output_d(0xFF);
  11. delay_ms(1000);
  12. }
  13. }

 

I need to remove the 16x2 LCD from the PCBA because it effect the LCD.

UART Send Text 

There's a RS-232 to TTL converter that's driven from an MAX232 level converter chip. The code below prints some texts on serial terminal. The baud rate is 9600bps.


  1. #include <18F4550.h>
  2. #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
  3. #use delay(clock=48000000)
  4. #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
  5. void main(){
  6. long second_counts=0;
  7. output_d(0x00);
  8. set_tris_d(0x01);
  9. printf("\n\rPIC18F4550 DIY USB Prototype Board.");
  10. printf("\n\rWednesday 03 September 2025");
  11. delay_ms(1000);
  12. while(1){
  13. printf("\n\rCounts in Seconds: %Lu ", second_counts);
  14. second_counts++;
  15. output_d(0x01);
  16. delay_ms(500);
  17. output_d(0x00);
  18. delay_ms(400);
  19. }
  20. }

The clock rate is 48MHz.

DIY PIC18F4550 Prototype Board
PIC18F4550 CCS PICC UART TEST 

The example below the MCU receive ASCII data from serial port terminal. The ASCII code between 0 and 7 toggles each pins of PORTD. The ASCII code of 8 and 9 turn PORT on and off respectively.


  1. #include <18F4550.h>
  2. #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
  3. #use delay(clock=48000000)
  4. //#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
  5. //configure and enable uart, use first hardware UART on PIC
  6. #use rs232(uart1, baud=9600)
  7. void main(){
  8. char rx = 0;
  9. output_d(0x00);
  10. set_tris_d(0x00);
  11. printf("\n\rPIC18F4550 DIY USB Prototype Board.");
  12. printf("\n\rRS-232 To TTL UART Tx and Rx Test");
  13. printf("\n\rFriday 05 September 2025");
  14. printf("\r\n");
  15. delay_ms(1000);
  16. while(1){
  17. if(kbhit()) {
  18. rx = getc();
  19. printf("OK\r\n");
  20. }
  21. switch(rx){
  22. case '0': output_toggle(pin_d0);
  23. break;
  24. case '1': output_toggle(pin_d1);
  25. break;
  26. case '2': output_toggle(pin_d2);
  27. break;
  28. case '3': output_toggle(pin_d3);
  29. break;
  30. case '4': output_toggle(pin_d4);
  31. break;
  32. case '5': output_toggle(pin_d5);
  33. break;
  34. case '6': output_toggle(pin_d6);
  35. break;
  36. case '7': output_toggle(pin_d7);
  37. break;
  38. case '8': output_d(0xFF);
  39. printf("PORTD ON\n\r");
  40. break;
  41. case '9': output_d(0x00);
  42. printf("PORTD OFF\n\r");
  43. break;
  44. }
  45. rx=0;
  46. }
  47. }

I use the serial port terminal of CCS PICC IDE

DIY PIC18F4550 Prototype Board
UART Transmit and Receive Example

We can use the UART tool of PICKIT2 programmer that's already built on board.

ADC Reading

There are three ADC inputs, two potentiometers and one LM35 temperature to voltage converter. Two potentiometers connect to RA0(AN0) and RA1(AN1) respectively. The LM35 connects to RA5(AN4).


  1. #include <18F4550.h>
  2. #DEVICE ADC = 10
  3. #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
  4. #use delay(clock=48000000)
  5. #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
  6. void main(){
  7. long adc_value;
  8. float adc_voltage;
  9. set_tris_a(0xFF);
  10. setup_adc(adc_clock_internal);
  11. setup_adc_ports(AN0_TO_AN4_ANALOG);
  12. printf("\n\rPIC18F4550 DIY USB Prototype Board.");
  13. printf("\n\rWednesday 03 September 2025");
  14. printf("\n\rOn-Board ADC Reading Demo");
  15. delay_ms(1000);
  16. while(1){
  17. set_adc_channel(0);
  18. delay_us(100);
  19. adc_value = read_adc();
  20. adc_voltage = (adc_value*5.0)/1023;
  21. printf("\n\rAN0 ADC Value: %Lu Decimal and %.2f Volts", adc_value,adc_voltage);
  22. set_adc_channel(1);
  23. delay_us(100);
  24. adc_value = read_adc();
  25. adc_voltage = (adc_value*5.0)/1023;
  26. printf("\n\rAN1 ADC Value: %Lu Decimal and %.2f Volts", adc_value,adc_voltage);
  27. set_adc_channel(4);
  28. delay_us(100);
  29. adc_value = read_adc();
  30. adc_voltage = (adc_value*500.0)/1023;
  31. printf("\n\rAN4 LM35 ADC Value: %Lu Decimal and %.2f%cC", adc_value,adc_voltage,248);
  32. delay_ms(1000);
  33. }
  34. }

The original LM35 works very well with a very little reading error. It costs around 1USD. However there many low cost copy of this sensor from a local store, that costs around 0.5USD. The output value has error. So I need to add one 330nF filter capacitor connects to the Vout pin of LM35 to get an appropriate reading value.

DIY PIC18F4550 Prototype Board
PIC18F4550 ADC Reading and UART

Alphanumeric 16x2 LCD

An on-board character LCD connects to PORTD in 4-bit mode via a DIP switch. This conventional industrial standard LCD is very easy to control in both 8-bit and 4-bit mode. CCS PICC has an LCD driver that allow us to test this LCD from a little lines of codes.


  1. #include <18F4550.h>
  2. #DEVICE ADC = 10
  3. #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
  4. #use delay(clock=48000000)
  5. #define LCD_ENABLE_PIN PIN_D3
  6. #define LCD_RS_PIN PIN_D2
  7. #define LCD_RW_PIN PIN_D0
  8. #define LCD_DATA4 PIN_D4
  9. #define LCD_DATA5 PIN_D5
  10. #define LCD_DATA6 PIN_D6
  11. #define LCD_DATA7 PIN_D7
  12. #include"lcd.c"
  13. void main(){
  14. long on_time=0;
  15. lcd_init();
  16. lcd_putc('\f');
  17. printf(LCD_PUTC,"HELLO WORLD!");
  18. lcd_gotoxy(1,2);
  19. printf(LCD_PUTC,"PIC18F4550 PCBA");
  20. delay_ms(5000);
  21. lcd_putc('\f');
  22. while(1){
  23. lcd_gotoxy(1,1);
  24. printf(LCD_PUTC,"ON TIME(Seconds)");
  25. lcd_gotoxy(1,2);
  26. printf(LCD_PUTC,"%Lu",on_time);
  27. on_time++;
  28. delay_ms(1000);
  29. }
  30. }


Originally the "lcd.c" driver uses the R/W pin character LCD. However this pin is wired to GND on the prototype board. So I need to modify this C driver to fit this PCBA. In the lcd_send_byte() function I disable the busy flag reading task. And I added a delay_us(1000) statement to by pass the busy time.

DIY PIC18F4550 Prototype Board
The lcd.c LCD driver I edit

In the lcd_getc() function I do the same as above but with a little delay.

DIY PIC18F4550 Prototype Board
The lcd.c LCD driver I edit

I have to copy this lcd.c driver file to my project folder to separate it from the original file.

DIY PIC18F4550 Prototype Board
Program Start Up

DIY PIC18F4550 Prototype Board
Displaying Time Counts in Seconds

On-Board ADC and LCD 

The source code below show the ADC reading from the PCBA on-board potentiometers and the LM35DZ temperature sensor.


  1. #include <18F4550.h>
  2. #DEVICE ADC = 10
  3. #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
  4. #use delay(clock=48000000)
  5. #define LCD_ENABLE_PIN PIN_D3
  6. #define LCD_RS_PIN PIN_D2
  7. #define LCD_RW_PIN PIN_D0
  8. #define LCD_DATA4 PIN_D4
  9. #define LCD_DATA5 PIN_D5
  10. #define LCD_DATA6 PIN_D6
  11. #define LCD_DATA7 PIN_D7
  12. #include"lcd.c"
  13. void main(){
  14. long adc_value;
  15. float adc_voltage;
  16. lcd_init();
  17. setup_adc(adc_clock_internal);
  18. setup_adc_ports(AN0_TO_AN4_ANALOG);
  19. lcd_putc('\f');
  20. printf(LCD_PUTC,"PIC18F4550 PCBA");
  21. lcd_gotoxy(1,2);
  22. printf(LCD_PUTC,"ADC and LCD Demo");
  23. delay_ms(5000);
  24. lcd_putc('\f');
  25. while(1){
  26. set_adc_channel(0);
  27. delay_us(100);
  28. adc_value = read_adc();
  29. adc_voltage = (adc_value*5.0)/1023;
  30. lcd_gotoxy(1,1);
  31. printf(LCD_PUTC,"AN0: %4Lu %fV",adc_value, adc_voltage);
  32. set_adc_channel(1);
  33. delay_us(100);
  34. adc_value = read_adc();
  35. adc_voltage = (adc_value*5.0)/1023;
  36. lcd_gotoxy(1,2);
  37. printf(LCD_PUTC,"AN1: %4Lu %fV",adc_value,adc_voltage);
  38. delay_ms(5000);
  39. lcd_putc('\f');
  40. set_adc_channel(4);
  41. delay_us(100);
  42. adc_value = read_adc();
  43. adc_voltage = (adc_value*500.0)/1023;
  44. printf(LCD_PUTC,"LM35 Temperature:");
  45. lcd_gotoxy(1,2);
  46. printf(LCD_PUTC,"AN4: %3Lu %f%cC",adc_value,adc_voltage,223);
  47. delay_ms(5000);
  48. lcd_putc('\f');
  49. }
  50. }

I use an external LM35DZ wiring on bread board instead because the soldered on-board sensor is a low cost fake IC.

DIY PIC18F4550 Prototype Board
On-Board ADC and LCD 

DIY PIC18F4550 Prototype Board
On-Board ADC and LCD 

DIY PIC18F4550 Prototype Board
On-Board ADC and LCD 


Tactile Switches

Tactile switches are connect to RB4 and RB5 on PCBA respectively. To use these inputs we can use normal software input state testing or even PortB Interrupt On Change feature of PIC18F4550.

The CCS PICC source code below uses simple software input testing to read input logic state from RB4 and RB5.


  1. #include <18F4550.h>
  2. #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
  3. #use delay(clock=48000000)
  4. void main(){
  5. output_d(0x00);
  6. set_tris_d(0x00);
  7. output_b(0x00);
  8. set_tris_b(0xFF);
  9. setup_adc_ports(NO_ANALOGS);
  10. port_b_pullups(true);
  11. while(1){
  12. output_toggle(pin_d0);
  13. if(input(pin_b4)==0) output_toggle(pin_d6);
  14. if(input(pin_b5)==0) output_toggle(pin_d7);
  15. delay_ms(250);
  16. }
  17. }

However we can use interrupt-on-change of PortB to detect button press. Interrupt is very fast and efficient. 

DIY PIC18F4550 Prototype Board
Switches and LEDs using both programs

These two programs works in the same way.

  1. #include <18F4550.h>
  2. #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
  3. #use delay(clock=48000000)
  4. #int_rb
  5. void rb_interrupt(){
  6. char value = input_b();
  7. if((value&0x10)==0) output_toggle(pin_d6);
  8. if((value&0x20)==0) output_toggle(pin_d7);
  9. clear_interrupt(int_rb);
  10. }
  11. void main(){
  12. output_d(0x00);
  13. set_tris_d(0x00);
  14. output_b(0x00);
  15. set_tris_b(0xFF);
  16. setup_adc_ports(NO_ANALOGS);
  17. port_b_pullups(true);
  18. enable_interrupts(INT_RB);
  19. ext_int_edge(INT_RB,H_TO_L);
  20. //interrupt_active(int_rb);
  21. enable_interrupts(GLOBAL);
  22. clear_interrupt(INT_RB);
  23. while(1){
  24. output_toggle(pin_d0);
  25. delay_ms(500);
  26. }
  27. }

The working function is identical to above program but the button pressing detection responds very fast.

USB Communication

PIC18F4550 has a high speed USB communication module allowing this chip connects to a host PC in many ways HID, CDC etc. 

The example below I got it from CCS PICC for USB exercise book for PIC18F4550.

  1. #include <18F4550.h>
  2. #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
  3. #use delay(clock=48000000)
  4. #define LED1 PIN_D0
  5. #define LED2 PIN_D1
  6. #define LED3 PIN_D2
  7. #DEFINE BUTTON PIN_A4
  8. #define LED_ON output_low
  9. #define LED_OFF output_high
  10. #define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT
  11. #define USB_EP1_TX_SIZE 8
  12. #define USB_EP1_RX_ENABLE USB_ENABLE_INTERRUPT
  13. #define ne USB_EP1_RX_SIZE 8
  14. #include <pic18_usb.h>
  15. #include <usb_desc_hid.h>
  16. #include <usb.c>
  17. void main(void) {
  18. LED_ON(LED1);
  19. LED_OFF(LED2);
  20. LED_OFF(LED3);
  21. usb_init();
  22. while (TRUE) {
  23. if (usb_enumerated())
  24. LED_ON(LED3);
  25. else
  26. LED_OFF(LED3);
  27. }
  28. }

 If it's not recognize by a host PC we can check hardware for problem.

DIY PIC18F4550 Prototype Board
USB Test #1

We can check its status on device manager.


DIY PIC18F4550 Prototype Board
Host Computer Device Manager










Labels

ADC (10) Analog (15) Arduino (12) Atmega16 (19) Audio (2) AVR (20) CCS PICC (1) Charger (1) Cortex-M0 (1) Counter (10) CPLD (25) Digital I/O (22) Display (34) EEPROM (2) Environment Sensor (1) esp8266 (2) Experiment Board (10) I2C (4) Interrupt (8) LCD (2) LDmicro (29) measurement and instrumentation (7) Microchip Studio (3) MikroC (1) One-Shot (3) OpAmp (1) PCB (32) PIC16 Microcontrollers (16) PIC16F877A (2) PIC16F887 MikroC (22) pic18 microcontrollers (1) PIC18F4550 (1) PLC (35) PWM (11) Regulator (1) RTC (3) Sensor (8) Shift Registers (5) SPI (5) Timer (34) UART (2) ultra-sonic sensor (1) USB (1) VHDL (21) xc8 (1) XC95108 (9) XC9536 (15) XC9572 (1) Xilinx (23) Xilinx ISE (22)