News:

;) This forum is the property of Proton software developers

Main Menu

How to create a small server on a LAN network

Started by Mapo, Today at 12:19 PM

Previous topic - Next topic

Mapo

Hello everyone,
I have always wanted the ability to put some small projects on a LAN, but I could never find clear information on how to set this up—specifically, how the PIC should respond to a browser's request.
With some help from Claude, I've put together a practical example of how to create an interactive web page that allows you to turn an LED on and off.
I thought it might be helpful to share the code here.
For the LAN interface, I used an inexpensive module based on the CH9121 chip, which communicates with the PIC via a serial connection.


            Device = 18F26K22
            Declare Xtal = 64

Config_Start
            FOSC = HSHP    ;HS oscillator (high power > 16 MHz)
            PLLCFG = On    ;Oscillator multiplied by 4
            PRICLKEN = On    ;Primary clock enabled
            FCMEN = OFF    ;Fail-Safe Clock Monitor disabled
            IESO = OFF    ;Oscillator Switchover mode disabled
            PWRTEN = OFF    ;Power up timer disabled
            BOREN = OFF    ;Brown-out Reset disabled in hardware and software
            BORV = 190    ;VBOR set to 1.90 V nominal
            WDTEN = OFF    ;Watch dog timer is always disabled. SWDTEN has no effect.
            WDTPS = 32768    ;1:32768
            CCP2MX = PORTC1    ;CCP2 input/output is multiplexed with RC1
            PBADEN = OFF    ;PORTB<5:0> pins are configured as digital I/O on Reset
            CCP3MX = PORTB5    ;P3A/CCP3 input/output is multiplexed with RB5
            HFOFST = OFF    ;HFINTOSC output and ready status are delayed by the oscillator stable status
            T3CMX = PORTC0    ;T3CKI is on RC0
            P2BMX = PORTC0    ;P2B is on RC0
            MCLRE = INTMCLR    ;RE3 input pin enabled; MCLR disabled
            STVREN = On    ;Stack full/underflow will cause Reset
            LVP = OFF    ;Single-Supply ICSP disabled
            XINST = OFF    ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
            Debug = OFF    ;Disabled
            Cp0 = OFF    ;Block 0 (000800-003FFFh) not code-protected
            CP1 = OFF    ;Block 1 (004000-007FFFh) not code-protected
            CP2 = OFF    ;Block 2 (008000-00BFFFh) not code-protected
            CP3 = OFF    ;Block 3 (00C000-00FFFFh) not code-protected
            CPB = OFF    ;Boot block (000000-0007FFh) not code-protected
            CPD = OFF    ;Data EEPROM not code-protected
            WRT0 = OFF    ;Block 0 (000800-003FFFh) not write-protected
            WRT1 = OFF    ;Block 1 (004000-007FFFh) not write-protected
            WRT2 = OFF    ;Block 2 (008000-00BFFFh) not write-protected
            WRT3 = OFF    ;Block 3 (00C000-00FFFFh) not write-protected
            WRTC = OFF    ;Configuration registers (300000-3000FFh) not write-protected
            WRTB = OFF    ;Boot Block (000000-0007FFh) not write-protected
            WRTD = OFF    ;Data EEPROM not write-protected
            EBTR0 = OFF    ;Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
            EBTR1 = OFF    ;Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
            EBTR2 = OFF    ;Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
            EBTR3 = OFF    ;Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
            EBTRB = OFF    ;Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
Config_End

;**** End of Fuse Configurator Settings ****
;-------------------------------------------------------------------------------

            Declare Hserial_Baud  = 115200
            Declare Hserial_Clear = On

            Symbol LED = PORTB.0

            Dim Conteggio As Word
            Dim LedState  As Bit
            Dim Ch        As Byte
            Dim Dummy     As Byte
            Dim Lung      As Word
            Dim Dinamica  As String * 255          ' max 255!

            Dim Pag_Inizio As Flash8 = "<!DOCTYPE html><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width'><title>PIC18F26K22</title></head><body style='background:#e8e8e8'><h1>Scheda PIC + CH9121</h1>", 0
            Dim Pag_Fine   As Flash8 = "<p><a href='/1'>Accendi</a> | <a href='/0'>Spegni</a> | <a href='/'>Aggiorna</a></p></body></html>", 0

'------------------------------------------------
Init:
              OSCCON = %01110000        ' oscillatore interno 16 MHz
              OSCTUNE.6 = 1             ' PLL x4 -> 64 MHz
              ANSELB = 0 : ANSELC = 0
              TRISB.0 = 0
              Low LED
              LedState = 0
              Conteggio = 0


'------------------------------------------------
Main:
              HSerIn [Wait("GET /"), Ch]     ' aspetta una richiesta, legge il 1° carattere dell'URL
              GoSub Flush_Request            ' scarta il resto delle intestazioni del browser

              Select Ch
                Case "1"                     ' http://ip/1
                  High LED : LedState = 1
                Case "0"                     ' http://ip/0
                  Low LED  : LedState = 0
                Case "f"                     ' /favicon.ico -> 404 vuoto
                  HSerOut ["HTTP/1.1 404 Not Found", 13, 10, "Content-Length: 0", 13, 10, 13, 10]
                  GoTo Main
              EndSelect

              Inc Conteggio
              GoSub Build_Page
              GoSub Send_Page
              GoTo Main

'------------------------------------------------
Flush_Request:                   ' legge finché la seriale resta muta per 20 ms
              HSerIn 20, Flush_End, [Dummy]
              GoTo Flush_Request
Flush_End:
              Return

'------------------------------------------------
'------------------------------------------------
Build_Page:                      ' solo la parte che cambia
              Dinamica = "<p>Richieste servite: " + Str$(Dec Conteggio) + "</p>"
              If LedState = 1 Then
                Dinamica = Dinamica + "<p>LED: <b>ACCESO</b></p>"
              Else
                Dinamica = Dinamica + "<p>LED: <b>SPENTO</b></p>"
              EndIf
              Return

'------------------------------------------------
Send_Page:
              Lung = Len(Pag_Inizio)
              Lung = Lung + Len(Dinamica)
              Lung = Lung + Len(Pag_Fine)
              HSerOut ["HTTP/1.1 200 OK", 13, 10]
              HSerOut ["Content-Type: text/html", 13, 10]
              HSerOut ["Content-Length: ", Dec Lung, 13, 10, 13, 10]
              HSerOut [Pag_Inizio]
              HSerOut [Dinamica]
              HSerOut [Pag_Fine]
              Return[attach id=6355]Pic_Web.txt[/attach][attach id=6355]Pic_Web.txt[/attach] 

Screenshot 2026-10-21 165856.png
Screenshot browser

Screenshot 2026-10-22 141823.png


▲