News:

Let's find out together what makes a PIC Tick!

Main Menu

PORTB.0 & 1 as digital on 18F2550

Started by RGV250, Aug 10, 2026, 10:58 AM

Previous topic - Next topic

RGV250

Hi,
I am tearing my hair out here, The code worked on 18F25K20 so I tried converting it to 18F2550 which will be the actual device as i have a few spare.
I am pretty sure it is going to be a peripheral setting but for the life of me I cannot figure out what one.
It could also be a VSM issue but hope not. The issue is that PORTB.0 & 1 do not appear to be digital whatever I try.
PortB.JPG

;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings

Device = 18F2550

Declare Reminders Off
@ CONFIG_REQ = 0 ; Override Compiler's configuration settings
Asm-
Config PLLDIV = 1 ;No prescale (4 MHz oscillator input drives PLL directly)
Config CPUDIV = OSC1_PLL2 ;[Primary Oscillator Src: /1][96 MHz PLL Src: /2]
Config USBDIV = 1 ;USB clock source comes directly from the primary oscillator block with no postscale
Config FOSC = HSPLL_HS ;HS oscillator, PLL enabled (HSPLL)
Config FCMEN = OFF ;Fail-Safe Clock Monitor disabled
Config IESO = OFF ;Oscillator Switchover mode disabled
Config PWRT = OFF ;PWRT disabled
Config BOR = On ;Brown-out Reset enabled in hardware only (SBOREN is disabled)
Config BORV = 3 ;Minimum setting 2.05V
Config VREGEN = OFF ;USB voltage regulator disabled
Config WDT = On ;WDT enabled
Config WDTPS = 32768 ;1:32768
Config CCP2MX = On ;CCP2 input/output is multiplexed with RC1
Config PBADEN = OFF ;PORTB<4:0> pins are configured as digital I/O on Reset
Config LPT1OSC = OFF ;Timer1 configured for higher power operation
Config MCLRE = On ;MCLR pin enabled; RE3 input pin disabled
Config STVREN = On ;Stack full/underflow will cause Reset
Config LVP = On ;Single-Supply ICSP enabled
Config XINST = OFF ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
Config Debug = OFF ;Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
Config Cp0 = OFF ;Block 0 (000800-001FFFh) is not code-protected
Config CP1 = OFF ;Block 1 (002000-003FFFh) is not code-protected
Config CP2 = OFF ;Block 2 (004000-005FFFh) is not code-protected
Config CP3 = OFF ;Block 3 (006000-007FFFh) is not code-protected
Config CPB = OFF ;Boot block (000000-0007FFh) is not code-protected
Config CPD = OFF ;Data EEPROM is not code-protected
Config WRT0 = OFF ;Block 0 (000800-001FFFh) is not write-protected
Config WRT1 = OFF ;Block 1 (002000-003FFFh) is not write-protected
Config WRT2 = OFF ;Block 2 (004000-005FFFh) is not write-protected
Config WRT3 = OFF ;Block 3 (006000-007FFFh) is not write-protected
Config WRTC = OFF ;Configuration registers (300000-3000FFh) are not write-protected
Config WRTB = OFF ;Boot block (000000-0007FFh) is not write-protected
Config WRTD = OFF ;Data EEPROM is not write-protected
Config EBTR0 = OFF ;Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks
Config EBTR1 = OFF ;Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks
Config EBTR2 = OFF ;Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks
Config EBTR3 = OFF ;Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks
Config EBTRB = OFF ;Boot block (000000-0007FFh) is not protected from table reads executed in other blocks
Endasm-
Declare Reminders On

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

    Declare Xtal = 48
   
    TRISB = 255

    INTCON2.7 = 0  ' Enable all Port B pull ups
 
' Not sure what else to try
' Port B.0..4 should be digital on power up (PBADEN in config settings above)
' It appears Port B.0 & 1 are not being set as digital as they are grey in the VSM 
' Running out of ideas 
    SSPCON1.5 = 0
    INTCON2.7 = 0
    INTCON.4 = 0
    INTCON3.3 = 0
    ADCON0.0 = 0

;-------------------------------------------------------------------------------

    Declare Watchdog = On                             ' Tell the compiler that the watchdog timer is enabled
   
' Setup USART1
    Declare Hserial1_Baud = 9600                     ' Set the default Baud rate for the USART
    Declare HRSOut1_Pin = PORTC.6                    ' Tell the compiler what pin to use for the USART TX
    Declare HRSIn1_Pin = PORTC.7                     ' Tell the compiler what pin to use for the USART RX
    Declare Hserial_Clear = On                       ' Enable Error clearing on received bytes
'
' Setup the LCD
'
    Declare LCD_Data4_Pin = PORTC.0                   ' Connect PORTC.0 to the LCD's D4 line
    Declare LCD_Data5_Pin = PORTC.1                   ' Connect PORTC.1 to the LCD's D5 line
    Declare LCD_Data6_Pin = PORTC.2                   ' Connect PORTC.2 to the LCD's D6 line
    Declare LCD_Data7_Pin = PORTC.4                   ' Connect PORTC.4 to the LCD's D7 line
    Declare LCD_ENPin = PORTA.0                       ' Connect PORTA.0 to the LCD's EN line
    Declare LCD_RSPin = PORTA.1                       ' Connect PORTA.1 to the LCD's RS line
    Declare LCD_Interface = 4                         ' Use a 4-line interface to the LCD
    Declare LCD_Lines = 2                             ' Tell the compiler that the LCD has two lines
    Declare LCD_Type = Alphanumeric                   ' Tell the compiler that the LCD is a Hitachi alphanumeric type
    Declare LCD_CommandUs = 2000                      ' Delay for 2000us between sending command bytes to the LCD
    Declare LCD_DataUs = 50                           ' Delay for 50us between sending data bytes to the LCD

'
' Create some variables
'
    Dim BAUD_Select As Byte                           ' Used to determine which pin is selected for BAUD selection.
    Dim ByteIn As Byte                                ' Holds the received byte to send to the LCD

'------------------------------------------------------------------------------------------------
' The main program starts here
' Wait in a loop and send bytes received via the USART directly to the LCD
'
Main:
    Setup()                                           ' Setup the program and any peripherals
    BaudCheck()                                       ' Check for Baud rate selection on power up.

    Do                                                ' Create a loop
        ByteIn = HRSIn, {1024, Continue}              ' Receive a byte serially into ByteIn, with a timeout of approx 1 second
        Print ByteIn                                  ' Send the byte received to the LCD
 
 ' Just for testing       
        HRSOut1  ByteIn                             
       
    Loop                                              ' Do it forever

'------------------------------------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Output    : None
'
Proc Setup()
' Set the pin conditions for BAUD rate selection.
    PinMode(PORTB.0, Input)                    ' Make the Baud change pin an input
    PinMode(PORTB.1, Input)                    ' Make the Baud change pin an input   
    PinMode(PORTB.2, Input)                    ' Make the Baud change pin an input   
    PinMode(PORTB.3, Input)                    ' Make the Baud change pin an input     
    PinMode(PORTB.4, Input)                    ' Make the Baud change pin an input

    HRSOutLn ""                                       ' Transmit a dummy byte to settle the PPS and the USART
    Cls                                               ' Clear the LCD's display
    Print At 1, 1, "    Positron    ",                ' \
          At 2, 1, " Serial LCD 1.2 "                 ' / Transmit a start-up message on the LCD
    DelayMS 1000
    Cls
EndProc

'------------------------------------------------------------------------------------------------
' Check PortB pins for the rate selected on power up.
'
Proc BaudCheck()
    BAUD_Select = PORTB & %00011100
Select BAUD_Select
Case 30 'Is PortB.0 low?
    HSerial1_ChangeBaud(9600)                   
    Swap SPBRGH,SPBRG 
    Print At 1, 1, "BAUD = 9600 "       
    DelayMS 1000 
    Cls                   

Case 29 'Is PortB.1 low?
    HSerial1_ChangeBaud(19200)                 
    Swap SPBRGH,SPBRG 
    Print At 1, 1, "BAUD = 19200 "       
    DelayMS 1000 
    Cls                     

Case 27 'Is PortB.2 low?
    HSerial1_ChangeBaud(38400)                 
    Swap SPBRGH,SPBRG 
    Print At 1, 1, "BAUD = 38400 "       
    DelayMS 1000 
    Cls                     

Case 23 'Is PortB.3 low?
    HSerial1_ChangeBaud(57600)                 
    Swap SPBRGH,SPBRG
    Print At 1, 1, "BAUD = 57600 "       
    DelayMS 1000 
    Cls                     

Case 15 'Is PortB.4 low?
    HSerial1_ChangeBaud(115200)                 
    Swap SPBRGH,SPBRG 
    Print At 1, 1, "BAUD = 115200 "       
    DelayMS 1000 
    Cls                     
     
Case 31 'No pins are low.
    Print At 1, 1, "No BAUD selected "       
    Stop
   
Case Else 'More than one pin is low.
    Print At 1, 1, "Selection error "       
    Stop   
                 
EndSelect       
EndProc

Regards,
Bob

John Lawton

Take a look at the ADCON1 register settings.

John
-----------------------------------------------------------------------------------------
Amicus 8 and 16A/16B dev boards
Especially created for Positron development
https://www.easy-driver.co.uk/Amicus

RGV250

Thanks John,
I did look at that but not that well obviously. I assumed that as I had disabled analogs in ADCON0 that was not relevant.

Regards,
Bob

trastikata

To me looks like a VSM issue, and the code looks correct - you set at POR PORTB 0..4 as digital, you set it as input and enabled the weak pull-ups.

What might be confusing the VSM is that you have disabled INT0 and INT1 but the INT0IF and INT1IF will be set regardless the enable bit and you have no interrupt handling label to go, I am just guessing here ... but in my experience PORTB works perfectly fine as digital input.


trastikata

Few things worth noting:

Config USBDIV = 1 should be Config USBDIV = 2

Config MCLRE = On - if you are not using it for reset, declare it as RE3 input to avoid accidental reset.

Config LVP = On - doesn't always work so well on these devices, depending what you have on the programming bus.

Regards

top204

#5
I've just created a code template for a PIC18F2550 device operating at 48MHz, using a 4MHz crystal or resonator, to test the PORTB mechanism, and it seems to be working as expected.

The compiler sets the pins to digital mode in the device's .def file (see the bottom section of each devices's .def file). However, with the USB devices, it is always better to disable the USB peripherals, 'just in case', as well. Also, tell the compiler not to setup the USB RAM. This clears the path for them to be used as standard devices.

Below is the code listing I used, and in the Isis simulator, PORTB.0 to PORTB.3 show as standard inputs, with external pull-up resistors added.

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' A test code template for a PIC18F2550 device to operate at 48MHz, using a 4MHz crystal or resonator.
'
' Written for the Positron8 BASIC compiler by Les Johnson.
'
    Device = 18F2550                                ' Tell the compiler what device to compile for
    Declare Xtal = 48                               ' Tell the compiler, the device will be operating at 48MHz (using a 20MHz crystal)
    Declare Onboard_USB = False                     ' Free up the USB RAM for general use
    Declare Auto_Heap_Arrays = On                   ' Make all arrays "Heap" types, so they always get placed after standard variables
    Declare Auto_Heap_Strings = On                  ' Make all Strings "Heap" types, so they always get placed after standard variables
    Declare Auto_Variable_Bank_Cross = On           ' Make sure all multi-byte variables remain within a single RAM bank
'
' Setup USART1
'
    Declare Hserial_Baud  = 115200
    Declare HSerout1_Pin  = PORTC.6
    Declare HSerin1_Pin    = PORTC.7
    Declare Hserial1_Clear = On                     ' Enable Error clearing on received bytes
'
' Create any global variables here
'
    Dim bPORTB As Byte

'---------------------------------------------------------------------------------
' The main program starts here
'
Main:
    Setup()                                         ' Setup the program and any variables or peripherals

    HRSOutLn "Start"
    Do
        bPORTB = PORTB                              ' Read PORTB
        HRSOutLn "bPORTB = ", Bin4 bPORTB           ' Transmit the first 4 bits of PORTB
        DelayMS 100
    Loop

'---------------------------------------------------------------------------------
' Setup the program and any variables or peripherals
' Input    : None
' Output    : None
' Notes    : None
'
Proc Setup()
    OSCCON = %00000000                              ' Make sure the device knows it is using an external oscillator
    UCON  = %00000000                               ' \ Disable the USB tranceiver (just in case)
    UCFG  = %00000000                               ' /
    PinInput PORTB.0                                ' \
    PinInput PORTB.1                                ' | Make the relevant pins of PORTB inputs
    PinInput PORTB.2                                ' |
    PinInput PORTB.3                                ' /
EndProc

'---------------------------------------------------------------------------------
' Setup the config fuses for a PIC18F2550 device to operate at 48MHz, using a 4MHz crystal
'
Config_Start
    PLLDIV = 1                                      ' No prescale. 4 MHz oscillator input drives PLL directly
    CPUDIV = OSC1_PLL2                              ' [Primary Oscillator Src: /1][96 MHz PLL Src: /2]
    USBDIV = 1                                      ' USB clock source comes directly from the primary oscillator block with no postscale
    FOSC = HSPLL_HS                                 ' HS oscillator, PLL enabled (HSPLL)
    FCMEN = Off                                     ' Fail-Safe Clock Monitor disabled
    IESO = Off                                      ' Oscillator Switchover mode disabled
    PWRT = On                                       ' PWRT enabled
    BOR = ON_ACTIVE                                 ' Brown-out Reset enabled in hardware only and disabled in Sleep mode (SBOREN is disabled)
    BORV = 2                                        ' Brown-out set for maximum voltage
    VREGEN = Off                                    ' USB voltage regulator disabled
    WDT = Off                                       ' Watchdog Timer disabled
    WDTPS = 128                                     ' Watchdog Timer ratio is 1:128
    MCLRE = On                                      ' MCLR pin enabled
    LPT1OSC = Off                                   ' Timer1 configured for higher power operation
    PBADEN = Off                                    ' PORTB<4:0> pins are configured as digital I/O on reset
    CCP2MX = On                                     ' CCP2 input/output is multiplexed with RC1
    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                                     ' Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
    Cp0 = Off                                       ' Block 0 (000800-001FFF) not code-protected
    CP1 = Off                                       ' Block 1 (002000-003FFF) not code-protected
    CP2 = Off                                       ' Block 2 (004000-005FFF) not code-protected
    CP3 = Off                                       ' Block 3 (006000-007FFF) not code-protected
    CPB = Off                                       ' Boot block (000000-0007FF) not code-protected
    CPD = Off                                       ' Data EEPROM not code-protected
    WRT0 = Off                                      ' Block 0 (000800-001FFF) not write-protected
    WRT1 = Off                                      ' Block 1 (002000-003FFF) not write-protected
    WRT2 = Off                                      ' Block 2 (004000-005FFF) not write-protected
    WRT3 = Off                                      ' Block 3 (006000-007FFF) not write-protected
    WRTB = Off                                      ' Boot block (000000-0007FF) not write-protected
    WRTC = Off                                      ' Configuration registers (300000-3000FF) not write-protected
    WRTD = Off                                      ' Data EEPROM not write-protected
    EBTR0 = Off                                     ' Block 0 (000800-001FFF) not protected from table reads executed in other blocks
    EBTR1 = Off                                     ' Block 1 (002000-003FFF) not protected from table reads executed in other blocks
    EBTR2 = Off                                     ' Block 2 (004000-005FFF) not protected from table reads executed in other blocks
    EBTR3 = Off                                     ' Block 3 (006000-007FFF) not protected from table reads executed in other blocks
    EBTRB = Off                                     ' Boot block (000000-0007FF) not protected from table reads executed in other blocks
Config_End

A screenshot of the above program running in Proteus is shown below:

PORTB_18F2550.jpg

Regards
Les



RGV250

Hi Les,
That worked, the issue I am having appears to be with the internal pull ups which I enabled with INTCON2.7 = 0.
B.0 & B.1 do not appear to work, is this down to the way I enabled them or an issue with the VSM?

Regards,
Bob

Pepe

demo proteus

RGV250

Hi Pepe,
Can you try it with internal pull ups as you have them enabled   INTCON2.7 = 0  ' Enable all Port B pull ups  but the VSM has external pull ups.

Regards,
Bob

top204

You are correct Bob.

The proteus simulator does not seem to be enabling the pull-up resistors on pins RB0 and RB1.

I added the line:

INTCON2bits_RBPU = 0                        ' Enable PORTB pull-up resistors

To the Setup procedure, after the pins are set to inputs.

Pins 0 and 1 of PORTB, do not respond to them.

I've checked the device's datasheet and can see no reason why they do not work on PORTB.0, and PORTB.1

Regards
Les


RGV250

Thanks for confirming that Les, at least I know the code works on Amicus18 and the pull ups are the only thing I had to change (apart from the configuration) for the 18F2550. I will try it on real hardware now.

Thanks to all for the help and suggestions for the config as this is the first time I have used a USB enabled device, not sure where I got them from but I have had them for donkeys years. I also have lots of Alpha displays so good to be able to use them as well.

One question, I used this format for the input which is what the manual shows.
    PinMode(PORTB.0, Input)                    ' Make the Baud change pin an input
 
where your example uses this format which I couldn't find in the manual.
    PinInput PORTB.0

Is there a difference or is it just personal preference?

Regards,
Bob
 

Pepe

On actual hardware, you cannot use `Declare LCD_Data7_Pin = PORTC.4` because that pin functions only as an input in 18f2550. While it might work as an output in Proteus, doing so is incorrect; that is why I switched it to PORTA in the attached Proteus demonstration.

RGV250

QuoteOn actual hardware, you cannot use `Declare LCD_Data7_Pin = PORTC.4
Thanks, I did wonder why you had done that, it does work in the sim.

Bob

top204

There is no difference in the operation of:

PinMode(PORTB.0, Input)

and

PinInput PORTB.0

Except on the newer devices that have control of the pull-up resistors per pin.

Then the PinMode comes into its own, as:

PinMode(PORTB.0, Input_Pullup)

And the pin is made an input, and its internal pull-up resistor is enabled, with a single command.

Regards
Les