News:

;) This forum is the property of Proton software developers

Main Menu

PIC16F18877: LCD initialization problem with DB4-DB7 on lower bits of PORTB

Started by GianGielett, Aug 01, 2026, 02:49 PM

Previous topic - Next topic

GianGielett

Hi everyone,

I'm having an intermittent LCD initialization problem with a PIC16F18877 and a C216-05 display (ST7066U controller, HD44780 compatible) and I need some advice.
This is the code :
'=======================================================
' CONFIGURAZIONE DEVICE E CLOCK
'=======================================================
Device = 16F18877
Declare Xtal = 16

#define Config3 WDTCPS_WDTCPS_2 & WDTE_OFF
#define Config1 RSTOSC_EXT1X & FEXTOSC_HS & FCMEN_OFF & CSWEN_OFF & CLKOUTEN_OFF
#define Config2 MCLRE_ON & BOREN_ON & ZCD_OFF & PWRTE_ON & LPBOREN_OFF & PPS1WAY_OFF & DEBUG_OFF & ZCDDIS_OFF
#define Config4 WRT_OFF & LVP_OFF & SCANE_NOT_AVAILABLE
#define Config5 CP_OFF & CPD_OFF

All_Digital = TRUE

'=======================================================
' CONFIGURAZIONE PORTE ANALOGICHE
' RA0=AN0 tensione 24V (partitore 150K/22K)
' RA1=AN1 tensione 12V (partitore 100K/22K)
'=======================================================
ANSELA = %00000011
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000
WPUB = %00001111   ' abilita pull-up su RB0-RB3
'=======================================================
' CONFIGURAZIONE ADC
'=======================================================
ADCON0 = %00000000
ADCON1 = %00000000
ADCON2 = %01100110
ADCON3 = $00
ADACT  = 0
ADRPT  = 16

'=======================================================
' CONFIGURAZIONE DIREZIONE PORTE
'=======================================================
'TRISE  = %00000001
'TRISA  = %00100011
'WPUA   = %00000000
'WPUB   = %00000000
'INTCON = %00000000
TRISE  = %00000001
TRISA  = %00100011
TRISB  = %00000000   ' RB0-RB3 output (dati LCD)
                     ' RB4-RB7 input
TRISC  = %00000000   ' RC6=EN RC7=RS output
TRISD  = %00000000   ' RD0=B12V RD1=LcdOn output
PORTB  = %00000000   ' RB0-RB3 a zero subito
WPUA   = %00000000
'WPUB   = %00000000
INTCON = %00000000

'=======================================================
' CONFIGURAZIONE PIN RW DISPLAY LCD
' RW fisso a GND — Proton non usa mai la lettura display
' Sulla scheda definitiva RW collegato a GND sul PCB
'=======================================================
TRISC.5 = 0
PORTC.5 = 0

'=======================================================
' CONFIGURAZIONE LCD
'=======================================================
Declare LCD_Data4_Pin = PORTB.4   ' DB4 (pin 11 LCD) -> RB0 (pin 8 PIC)
Declare LCD_Data5_Pin = PORTB.1   ' DB5 (pin 12 LCD) -> RB1 (pin 9 PIC)
Declare LCD_Data6_Pin = PORTB.2   ' DB6 (pin 13 LCD) -> RB2 (pin 10 PIC)
Declare LCD_Data7_Pin = PORTB.3   ' DB7 (pin 14 LCD) -> RB3 (pin 11 PIC)
Declare LCD_ENPin     = PORTC.6   ' EN  (pin 6 LCD)  -> RC6
Declare LCD_RSPin     = PORTC.7   ' RS  (pin 4 LCD)  -> RC7
Declare LCD_Interface = 4         ' modalità 4 bit
Declare LCD_Lines     = 2         ' display 2 righe
Declare LCD_Type      = 0         ' HD44780 alfanumerico
Declare LCD_CommandUs = 2000      ' delay tra comandi (µs)
Declare LCD_DataUs    = 50        ' delay tra dati (µs)
 
'=======================================================
' CONFIGURAZIONE ADC SOFTWARE
'=======================================================
Declare Adin_Res   = 10
Declare Adin_Tad   = FRC
Declare Adin_Stime = 50

'=======================================================
' DICHIARAZIONE PIN SIMBOLICI
'=======================================================
Input  PORTA.0
Symbol LivBat24  = PORTA.0  ' AN0: tensione 24V (B1+B2 serie)
Input  PORTA.1
Symbol LivBat12  = PORTA.1  ' AN1: tensione 12V (B2)
Output PORTA.2
Symbol CarBatOFF = PORTA.2  ' MC34167: HIGH=disabilita LOW=abilita
Output PORTA.3
Symbol RelBatKO  = PORTA.3  ' rele' batterie: HIGH=KO
Input  PORTA.4
Symbol Verifica  = PORTA.4  ' comparatore U2 (1=batt scarica)
Input  PORTA.5
Symbol TestExt   = PORTA.5  ' test manuale esterno
Input  PORTE.0
Symbol OnOff     = PORTE.0  ' ponticello attivazione
Output PORTC.0
Symbol B24V      = PORTC.0  ' parte partitore feedback MC34167
Output PORTC.1
Symbol Scarica   = PORTC.1  ' HIGH=attiva MOSFET Q3 carico
Input  PORTC.2
Symbol Test24h   = PORTC.2  ' DIP: test ogni 24 ore
Input  PORTC.3
Symbol Test48h   = PORTC.3  ' DIP: test ogni 48 ore
Output PORTD.0
Symbol B12V      = PORTD.0  ' parte partitore feedback MC34167
Output PORTD.1
Symbol LcdOn     = PORTD.1  ' HIGH=backlight display acceso

'=======================================================
' INIZIALIZZAZIONE USCITE IN STATO SICURO
'=======================================================
Low Scarica
Low RelBatKO
Low B12V
Low B24V
Low CarBatOFF

'=======================================================
' INIZIALIZZAZIONE LCD
' CRITICO: prima di Timer0 e interrupt
' Doppio Cls garantisce init corretta HD44780
'=======================================================
'DelayMS 200
'Cls
'DelayMS 200
'Cls
'DelayMS 200

'=======================================================
' TIMER0 — conteggio 72 ore
' Fosc=16MHz, Fosc/4=4MHz, prescaler 1:256
' tick ogni 64us, overflow ogni 16.384ms
' 61 overflow = 1 secondo
' 60 secondi  = 1 minuto
' 60 minuti   = 1 ora
' 72 ore      = trigger test automatico
'=======================================================
Symbol TMR0_Interrupt = PIR0.5
Symbol TMR0IE         = PIE0.5
Symbol GIE            = INTCON.7

T0CON0 = %10000000
T0CON1 = %01000111
TMR0L  = 0
PIR0.5 = 0
PIE0.5 = 1
INTCON.7 = 1
INTCON.6 = 1

On_Hardware_Interrupt GoTo Isr_HoursCounter

'=======================================================
' DICHIARAZIONE VARIABILI
'=======================================================
Dim i             As Byte   ' contatore generico For/Next
Dim AdcDat24      As Word
Dim AdcDat12      As Word
Dim Lbatt24       As Float
Dim Lbatt12       As Float
Dim RisAdc24      As Float
Dim RisAdc12      As Float
Dim V24_pre       As Float
Dim V12_pre       As Float
Dim V24_sotto     As Float
Dim V12_sotto     As Float
Dim DeltaV_serie  As Float
Dim DeltaV_B2     As Float
Dim Rint_B1       As Float
Dim Rint_B2       As Float
Dim Stato_B1      As Byte
Dim Stato_B2      As Byte
Dim Rete_assente  As Bit
Dim T_start       As Word
Dim T_float       As Word
Dim T_ricarica    As Word
Dim Cap_residua   As Float
Dim Asimmetria    As Float
Dim Tmr0_Counter  As Byte
Dim Sec_Counter   As Byte
Dim Min_Counter   As Word
Dim Hour_Counter  As Byte
Dim test_ready    As Bit
Dim TestExt_Old   As Bit
Dim Batt_Verificata As Bit  ' 0=non verificata 1=gia verificata

'=======================================================
' INIZIALIZZAZIONE VARIABILI
'=======================================================
' Risoluzioni ADC calibrate empiricamente sul prototipo
' da ricalibrate con valori reali misurati
RisAdc24      = 0.04417
RisAdc12      = 0.03591
AdcDat24      = 0
AdcDat12      = 0
Lbatt24       = 0.0
Lbatt12       = 0.0
V24_pre       = 0.0
V12_pre       = 0.0
V24_sotto     = 0.0
V12_sotto     = 0.0
DeltaV_serie  = 0.0
DeltaV_B2     = 0.0
Rint_B1       = 0.0
Rint_B2       = 0.0
Asimmetria    = 0.0
Stato_B1      = 0
Stato_B2      = 0
Rete_assente  = 0
T_start       = 0
T_float       = 0
T_ricarica    = 0
Cap_residua   = 0.0
Tmr0_Counter  = 0
Sec_Counter   = 0
Min_Counter   = 0
Hour_Counter  = 0
test_ready    = 0
TestExt_Old   = 0
Batt_Verificata = 0

'=======================================================
' INIZIALIZZAZIONE LCD ALL AVVIO
' Eseguita una sola volta al power-on del PIC.
' Il controller HD44780 richiede tempo dopo
' l accensione prima di accettare comandi.
' REGOLA FISSA: questo blocco non va mai rimosso
' ne spostato — deve stare sempre qui.
'=======================================================
Init_LCD:
    Cls
    DelayMS 5000
    Cls
    DelayMS 2500
   
GoTo main

'=======================================================
' MAIN — loop scheda spenta
' MC34167 in tampone a tensione default 27.2V
' CarBatOFF=LOW, B12V=LOW, B24V=LOW
'=======================================================
main:
    Do
        Low CarBatOFF
        Low B12V
        Low B24V
        Low Scarica
        Low LcdOn
        Batt_Verificata = 0  ' reset flag per prossima accensione
        DelayMS 100
        Print At 1,4, "GNG AL 9000"
        Print At 2,5, "Spento!!!"
        DelayMS 1000
        DelayMS 1000
        If OnOff = 1 Then GoTo acceso
    Loop

'=======================================================
' ACCESO — loop scheda attiva
'
' Sequenza primo ingresso:
' 1) Attiva carica 28Vdc
' 2) Leggi tensioni una sola volta (flag Batt_Verificata)
' 3) Verifica connessione batterie
' 4) Mostra tensioni sul display
'
' Sequenza cicli successivi:
' 1) Attiva carica 28Vdc
' 2) Salta Leggi_Tensioni (flag gia settato)
' 3) Mostra tensioni con valori gia in memoria
' 4) Gestione test manuale e automatico
'=======================================================
acceso:
    Low CarBatOFF
    Low B24V
    High B12V
    High LcdOn
    DelayMS 100
    Cls
    DelayMS 50
    Print At 1,4, "GNG AL 9000"
    Print At 2,6, "Acceso"
    DelayMS 1000

    If OnOff = 0 Then GoTo main

    ' Leggi tensioni solo al primo ingresso in acceso
    ' Flag Batt_Verificata evita la lettura ad ogni ciclo
    ' (lettura richiede 5 secondi di attesa)
    If Batt_Verificata = 0 Then
        GoSub Leggi_Tensioni

        ' Verifica connessione batterie
        ' V24 < 19V o V12 < 9V = batterie scollegate
        If Lbatt24 < 19.0 Or Lbatt12 < 9.0 Then
            High RelBatKO
            Cls
            Print At 1,1, "BATT.SCOLLEGATE"
            Print At 2,1, "Verif.connett. "
            DelayMS 2000
            If OnOff = 0 Then GoTo main
            GoTo acceso
        EndIf

        ' Batterie OK — reset allarme
        Low RelBatKO
        Batt_Verificata = 1  ' flag: verifica eseguita
    EndIf

    ' Mostra tensioni — usa valori gia in memoria
    GoSub Mostra_Tensioni

    If OnOff = 0 Then GoTo main

    ' Test manuale con antirimbalzo
    If TestExt = 1 And TestExt_Old = 0 Then
        Test_Batteria()
    EndIf
    TestExt_Old = TestExt

    ' Metodo 2: monitoraggio rete
    GoSub Monitor_Rete

    ' Test automatico ogni 72 ore
    If test_ready = 1 Then
        test_ready = 0
        Test_Batteria()
    EndIf

    DelayMS 1000
    GoTo acceso

My questions are:
1) Is LCD_Data4_Pin through LCD_Data7_Pin supported on PIC16F devices
   or only PIC18F?
2) Is there a way to use the bottom 4 bits (RB0-RB3) in 4-bit mode
   with LCD_DTPin? The manual shows PORTB.0 for 8-bit and PORTB.4
   for 4-bit — but says "bottom 4 or top 4 bits" are both supported.
3) Can the BPF variable solve intermittent initialization issues?

Note: RB6 and RB7 are used by ICD3 programmer so I cannot use RB4-RB7.

Thanks in advance for any help or suggestions.
Cheers
Gianluca

RGV250

Hi,
You have data4_pin as portb.4, should this not be portb.0
Also it is a long example, it is better to post very simple examples if you have a problem.

Regards,
Bob

RGV250

Hi,
Having looked at the manual, have you tried this   
Declare LCD_DTPin = PORTB.0
and not used these declares?
'Declare LCD_Data5_Pin = PORTB.1   ' DB5 (pin 12 LCD) -> RB1 (pin 9 PIC)
'Declare LCD_Data6_Pin = PORTB.2   ' DB6 (pin 13 LCD) -> RB2 (pin 10 PIC)
'Declare LCD_Data7_Pin = PORTB.3   ' DB7 (pin 14 LCD) -> RB3 (pin 11 PIC)

I also noticed this
Init_LCD:
    Cls
    DelayMS 5000
    Cls
    DelayMS 2500

which does not make sense, it is duplicated and way too long, I only ever have around 100ms for the display to initialise.

Do you actually need these, I have done quite a few ALCD and never needed them?
Declare LCD_CommandUs = 2000      ' delay tra comandi (µs)
Declare LCD_DataUs    = 50        ' delay tra dati (µs)

Regards,
Bob

Frizie

Ohm sweet Ohm | www.picbasic.nl

GDeSantis

I don't have a PIC16F18877, but here is a program example that uses a PIC16F18323.

    '****************************************************************
    '*  Micro    : PIC16F18323                                      *
    '*  Name     : 2x16 LCD EXAMPLE (NEWHAVEN NHD-0216HZ-FL-YBW)    *
    '*  Date:    : 25 Aug 2025                                      *
    '*  Comment  ; Display is HD44780 Compatible                    *
    '*  Comment  : MCU Clock = 32 MHz Internal RC Oscillator        *
    '*  Version  : 1.0                                              *
    '*                 __________                                   *
    '*                !          !                                  *
    '*  (Vdd)    1  x--Vdd    Vss--x  14  (GND)                     *
    '*           2  x--RA5    RA0--x  13                            *
    '*           3  x--RA4    RA1--x  12                            *
    '*  (MCLR)   4  x--RA3    RA2--x  11                            *
    '*  (EN)     5  x--RC5    RC0--x  10  (DB4)                     *
    '*  (RS)     6  x--RC4    RC1--x   9  (DB5)                     *
    '*  (DB7)    7  x--RC3    RC2--x   8  (DB6)                     *
    '*                !__________!                                  *
    '*                                                              *
    '****************************************************************

    Device         = 16F18323        ;DEFINE DEVICE AS 16F18323
    Declare Xtal   = 32              ;DEFINE MCU CLOCK FREQUENCY

    Config1  FEXTOSC_OFF,RSTOSC_HFINT32,CLKOUTEN_OFF,CSWEN_OFF,FCMEN_OFF
    Config2  MCLRE_ON,PWRTE_ON,WDTE_OFF,LPBOREN_OFF,BOREN_ON,BORV_HIGH,_
             PPS1WAY_OFF,STVREN_OFF,DEBUG_OFF
    Config3  WRT_ALL,LVP_OFF
    Config4  CP_ON,CPD_ON

    OSCFRQ   = %00000110             ;HFINTOSC WITH 2X PLL (32 MHZ)

    TRISA    = %001000               ;PORTA DATA DIRECTION
    TRISC    = %000000               ;PORTC DATA DIRECTION

    PORTA.0  = 0                     ;SET UNUSED PORT PINS TO OUTPUT LOW 
    PORTA.1  = 0                     ;SET UNUSED PORT PINS To Output Low
    PORTA.2  = 0                     ;SET UNUSED PORT PINS To Output Low
    PORTA.4  = 0                     ;SET UNUSED PORT PINS To Output Low
    PORTA.5  = 0                     ;SET UNUSED PORT PINS To Output Low
   
    ANSELA   = 0                     ;DISABLE PORTA ADC Module
    ANSELC   = 0                     ;DISABLE PORTC ADC Module
   
    Declare LCD_Type 0               ;LCD CONTROLLER HD44780 COMPATIBLE
    Declare LCD_DTPin PORTC.0        ;LCD DATA PIN
    Declare LCD_ENPin PORTC.5        ;LCD ENABLE PIN
    Declare LCD_RSPin PORTC.4        ;LCD RS PIN
    Declare LCD_Interface 4          ;LCD INTERFACE: 4-BIT MODE
    Declare LCD_Lines 2
   
    DelayMS 500                      ;POWER UP STABILIZATION DELAY   
   
    MAIN:
        Print At 1,1, "  HELLO WORLD   "
        Print At 2,1, "POSITRON AT WORK"
      End

GianGielett

Hi everyone,

Thank you all for your replies and suggestions really appreciated.

Following Bob's advice I will simplify the code and try this
minimal configuration:
Declare LCD_DTPin = PORTB.0
Declare LCD_ENPin = PORTC.6
Declare LCD_RSPin = PORTC.7
Declare LCD_Interface = 4
Declare LCD_Lines = 2
Declare LCD_Type = 0


Removing:
1)All LCD_DataX_Pin declares
2)LCD_CommandUs and LCD_DataUs (using defaults)
3)The duplicate Cls and long delays in Init_LCD

I will also try the BPF variable suggestion.

I will test everything and report back with the results.

Thanks again,
Gianluca

Pepe


GianGielett

Good morning everyone,

I made the changes you suggested and now everything
is working perfectly.

The solution was the BPF variable combined with a
single Cls in the Init_LCD block no need to duplicate
Cls and long delays.
Declare LCD_DTPin     = PORTB.0
Declare LCD_ENPin     = PORTC.6
Declare LCD_RSPin     = PORTC.7
Declare LCD_Interface = 4
Declare LCD_Lines     = 2
Declare LCD_Type      = 0
.........................
Init_LCD:
    Dim BPF As Byte System
    DelayMS 500
    Clear BPF
    Cls
GoTo main
...........


Many thanks to all of you for your help.

Have a great Positron day! 😊

Cheers,
Gianluca

RGV250

Hi,
QuoteThe solution was the BPF variable
What is this BPF variable, where did you see it suggested.
I have never used it on any display and really do not think it has anything to with your problem.
Also, looking at your code it does not do anything either.

Regards,
Bob

GianGielett

Hi Bob

You are right,looking more carefully at the code,
the BPF variable was not necessary since it is already
zero at power-on.

I believe that the real fix was simply removing the duplicate Cls
and long delays from the Init_LCD block, and using
just a single DelayMS 500 followed by one Cls.

That was the root cause of the problem all along
the duplicate Cls was confusing the ST7066U controller.

Thank you for your advice.

Cheers,
Gianluca