PDA

View Full Version : Strange behavior on PORTB on a PIC18F26K20



Dosbomber
- 28th September 2016, 03:31
Greetings everyone, this will be my first post on this forum (please be gentle).

I'm hoping someone can give me some insight into what's causing a weird behavior in a test circuit I've been using on a PIC I've been introducing myself to recently.

The PIC in question is a PIC18F26K20.
Using PBP3, PBPX 3.0.7.4 on MicroCode Studio v5.0.0.5.

As a test, I've hooked up a few LEDs directly to PortB.0, .1, .2, and .3 (pins 21-24), with nothing else but the normal stuff (2x ground, 1x +5VDC, 4700ohm resistor on pin 1, and the data and clock pins hooked up to my PICKit3. Genuine PICKit3.

What the test program should do is simply flash each LED one at a time, with a 500ms delay during each LEDs lit phase. Only one LED is lit at any time. Simple enough.

Just to clarify, I've already configured the GPIO as outputs (DDR) with the TRISB = 000000 statement, set those pins as digital with the ANSELH = 000000 statement just to be sure (I don't think this was actually necessary), and set up aliases for those pins, renaming them led1, led2, led3, and led4.

Here's where the weirdness starts:

Normally, I change pin states to high or low with a statement such as PORTB.0 = 1 and PORTB.0 = 0, and usually use an alias for the pin name. This has always worked well for me in the past.

This time, and only for PortB, and only when operating at 20 MHz, it won't cycle through the LEDs properly unless I use the HIGH and LOW PBP commands.

What it does instead is light up each of the first three LEDs (PortB.0, .1, and .2) at the appropriate times, but never turns any of them off. The fourth LED (PortB.3) works as it should.

If I move everything to PortC, including the DDR preset, etc. just as I had set up for PortB, it works fine.
If I change the defined OSC from 20 to 4 and replace the 20MHz resonator with a 4MHz resonator, it works fine (this one really surprised me).
If I add a second PORTB.0 = 0 immediately after the intended PORTB.0 = 0 statement, it works fine (yes, this is two identical commands as if I'm telling the port to do it twice in a row).
If I use LOW PORTB.0, it works fine.

So it seems to be something going on with the first three pins on PortB that is requiring the strange workarounds in the code. Some pretty strange workarounds, it seems to me. I do notice that the pins affected are all INT pins. So I tried disabling Interrupts entirely with both the DISABLE and INTCON.7 = 0 commands, to no effect. I admit I don't currently know much about interrupts, as I've never needed to use them before, although I think this may have been a red herring. I could be wrong, but don't you have to intentionally enable interrupts to use them, so both of these commands are pointless without specifically turning the interrupts on?

I can work around it by changing my coding convention, but I'd really like to know what's going on that's causing the difference in behavior.

Can anyone shed some light on this for me?

Thanks,
Dos


Note: Please excuse the crudity of this code, it's something I threw together one night as a quick test of the new PIC. The Serial LCD and buttons are not currently connected to the breadboard, but the code relevant to them has been left in the program.



'************************************************* ***************
'* Name : 18F26K20test.PBP *
'* Author : ************* *
'* Notice : Copyright (c) 2016 ************* *
'* : All Rights Reserved *
'* Date : 7/31/2016 *
'* Version : 1.0 *
'* Notes : PIC18F26K20 - Test *
'* : *
'************************************************* ***************

#MSG "Compiling code for " + __PROCESSOR__

' Device fuses configuration - PIC18F26K20
#CONFIG
CONFIG FOSC = HS ; HS oscillator
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled
CONFIG IESO = OFF ; Oscillator Switchover mode disabled
CONFIG PWRT = OFF ; PWRT disabled
CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
CONFIG BORV = 18 ; VBOR set to 1.8 V nominal
CONFIG WDTEN = ON ; WDT is always enabled. SWDTEN bit has no effect
CONFIG WDTPS = 512 ; 1:512
CONFIG CCP2MX = PORTC ; 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 HFOFST = ON ; HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.
CONFIG MCLRE = ON ; MCLR pin enabled; RE3 input pin disabled
CONFIG STVREN = ON ; Stack full/underflow will cause Reset
CONFIG LVP = OFF ; Single-Supply ICSP disabled
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-003FFFh) not code-protected
CONFIG CP1 = OFF ; Block 1 (004000-007FFFh) not code-protected
CONFIG CP2 = OFF ; Block 2 (008000-00BFFFh) not code-protected
CONFIG CP3 = OFF ; Block 3 (00C000-00FFFFh) not code-protected
CONFIG CPB = OFF ; Boot block (000000-0007FFh) not code-protected
CONFIG CPD = OFF ; Data EEPROM not code-protected
CONFIG WRT0 = OFF ; Block 0 (000800-003FFFh) not write-protected
CONFIG WRT1 = OFF ; Block 1 (004000-007FFFh) not write-protected
CONFIG WRT2 = OFF ; Block 2 (008000-00BFFFh) not write-protected
CONFIG WRT3 = OFF ; Block 3 (00C000h-00FFFFh) not write-protected
CONFIG WRTC = OFF ; Configuration registers (300000-3000FFh) not write-protected
CONFIG WRTB = OFF ; Boot Block (000000-0007FFh) not write-protected
CONFIG WRTD = OFF ; Data EEPROM not write-protected
CONFIG EBTR0 = OFF ; Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
CONFIG EBTR1 = OFF ; Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
CONFIG EBTR2 = OFF ; Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
CONFIG EBTR3 = OFF ; Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
CONFIG EBTRB = OFF ; Boot Block (000000-0007FFh) not protected from table reads executed in other blocks

#ENDCONFIG

define OSC 20 ' Using 20Mhz oscillator - remember to change fuse to HS
INCLUDE "bs2defs.bas"

restart:

TRISA = 011111 ' Set 0-4 pins on PortA to inputs, 5-7 pins to outputs
TRISB = 000000 ' Set all pins on PortB to outputs
TRISC = 000000 ' Set all pins on PortC to outputs

ANSEL = 000000 ' Make AN0 - AN7 Digital (pins RA0, RA1, RA2, RA3, RA5 on PIC18F26K20)
ANSELH = 000000 ' Make AN8 - AN15 Digital (pins RB2, RB3, RB1, RB4, RB0 on PIC18F26K20)

' Set all pins low to reset any pins that went high due to device connection
PORTA = 0 ' Set all pins on PORTA low
PORTB = 0 ' Set all pins on PORTB low
PORTC = 0

' Port alias setup
led1 var PORTB.0
led2 VAR PORTB.1
led3 VAR PORTB.2
led4 VAR PORTB.3
lcd var PORTB.4 ' Serial output to LCD
btnr var PORTA.0 ' Right arrow button
btns vAR PORTA.1 ' Select button
btnu var PORTA.2 ' Up arrow button
btnl var PORTA.3 ' Left arrow button
btnd var PORTA.4 ' Down arrow button

' Variable declaration

start:

SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1

goto ledanims

mainloop:
' For now, as a test of the buttons, just send a test string to the LCD
' After this is proven, send different texts (bluetooth, PIC to PIC, wordlength, etc.)
if btnr = 1 then btnrgt
if btns = 1 then btnsel
if btnu = 1 then btnup
if btnl = 1 then btnlft
if btnd = 1 then btndwn

goto mainloop

' ----------------------------------------------------------------------------

btnrgt:
SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1
serout lcd,N9600,["Right button"]
pause 500
goto start

btnsel:
SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1
serout lcd,N9600,["Select button"]
pause 500
goto start

btnup:
SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1
serout lcd,N9600,["Up button"]
pause 500
goto start

btnlft:
SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1
serout lcd,N9600,["Left button"]
pause 500
goto start

btndwn:
SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1
serout lcd,N9600,["Down button"]
pause 500
goto start


' ================================================== ==========================

ledanims:

'high PORTB.0
'PORTB.0 = 1
led1 = 1
pause 500
led1 = 0
'led1 = 0 ' <--- If I add this back in, this pin works correctly
'PORTB.0 = 0
'low PORTB.0 ' <--- This statement does the job by itself

'high PORTB.1
'PORTB.1 = 1
led2 = 1
pause 500
'led2 = 0
'led2 = 0
PORTB.1 = 0
'PORTB.1 = 0
'low PORTB.1

'high PORTB.2
'PORTB.2 = 1
led3 = 1
pause 500
led3 = 0
'PORTB.2 = 0
'low PORTB.2

'high PORTB.3
'PORTB.3 = 1
led4 = 1
pause 500
led4 = 0
'PORTB.3 = 0
'low PORTB.3

goto ledanims

richard
- 28th September 2016, 04:52
looks like the classic read modify write issue
check out this video for an explaination [View streaming media version: link]
http://www.microchip.com/webinars.mi...cName=en556253 (http://www.microchip.com/webinars.microchip.com/WebinarDetails.aspx?dDocName=en556253)

HenrikOlsson
- 28th September 2016, 06:00
It looks like you're missing the % in front of all numbers that are to be interpreted as binary by the compiler (or is that just the forum engine dropping that character (again)?)

/Henrik.

timmers
- 28th September 2016, 09:52
Try this. Use LAT instead of PORT for outputs. Inputs must use PORT!

Tim.


'************************************************* ***************
'* Name : 18F26K20test.PBP *
'* Author : ************* *
'* Notice : Copyright (c) 2016 ************* *
'* : All Rights Reserved *
'* Date : 7/31/2016 *
'* Version : 1.0 *
'* Notes : PIC18F26K20 - Test *
'* : *
'************************************************* ***************

#MSG "Compiling code for " + __PROCESSOR__

' Device fuses configuration - PIC18F26K20
#CONFIG
CONFIG FOSC = HS ; HS oscillator
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled
CONFIG IESO = OFF ; Oscillator Switchover mode disabled
CONFIG PWRT = OFF ; PWRT disabled
CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
CONFIG BORV = 18 ; VBOR set to 1.8 V nominal
CONFIG WDTEN = ON ; WDT is always enabled. SWDTEN bit has no effect
CONFIG WDTPS = 512 ; 1:512
CONFIG CCP2MX = PORTC ; 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 HFOFST = ON ; HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.
CONFIG MCLRE = ON ; MCLR pin enabled; RE3 input pin disabled
CONFIG STVREN = ON ; Stack full/underflow will cause Reset
CONFIG LVP = OFF ; Single-Supply ICSP disabled
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-003FFFh) not code-protected
CONFIG CP1 = OFF ; Block 1 (004000-007FFFh) not code-protected
CONFIG CP2 = OFF ; Block 2 (008000-00BFFFh) not code-protected
CONFIG CP3 = OFF ; Block 3 (00C000-00FFFFh) not code-protected
CONFIG CPB = OFF ; Boot block (000000-0007FFh) not code-protected
CONFIG CPD = OFF ; Data EEPROM not code-protected
CONFIG WRT0 = OFF ; Block 0 (000800-003FFFh) not write-protected
CONFIG WRT1 = OFF ; Block 1 (004000-007FFFh) not write-protected
CONFIG WRT2 = OFF ; Block 2 (008000-00BFFFh) not write-protected
CONFIG WRT3 = OFF ; Block 3 (00C000h-00FFFFh) not write-protected
CONFIG WRTC = OFF ; Configuration registers (300000-3000FFh) not write-protected
CONFIG WRTB = OFF ; Boot Block (000000-0007FFh) not write-protected
CONFIG WRTD = OFF ; Data EEPROM not write-protected
CONFIG EBTR0 = OFF ; Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
CONFIG EBTR1 = OFF ; Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
CONFIG EBTR2 = OFF ; Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
CONFIG EBTR3 = OFF ; Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
CONFIG EBTRB = OFF ; Boot Block (000000-0007FFh) not protected from table reads executed in other blocks

#ENDCONFIG

define OSC 20 ' Using 20Mhz oscillator - remember to change fuse to HS
INCLUDE "bs2defs.bas"

restart:

TRISA = %011111 ' Set 0-4 pins on PortA to inputs, 5-7 pins to outputs
TRISB = %000000 ' Set all pins on PortB to outputs
TRISC = %000000 ' Set all pins on PortC to outputs

ANSEL = %000000 ' Make AN0 - AN7 Digital (pins RA0, RA1, RA2, RA3, RA5 on PIC18F26K20)
ANSELH = %000000 ' Make AN8 - AN15 Digital (pins RB2, RB3, RB1, RB4, RB0 on PIC18F26K20)

' Set all pins low to reset any pins that went high due to device connection
LATA = 0 ' Set all pins on PORTA low
LATB = 0 ' Set all pins on PORTB low
LATC = 0

' Port alias setup
led1 var LATB.0
led2 VAR LATB.1
led3 VAR LATB.2
led4 VAR LATB.3
lcd var LATB.4 ' Serial output to LCD
btnr var PORTA.0 ' Right arrow button
btns vAR PORTA.1 ' Select button
btnu var PORTA.2 ' Up arrow button
btnl var PORTA.3 ' Left arrow button
btnd var PORTA.4 ' Down arrow button

' Variable declaration

start:

SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1

goto ledanims

mainloop:
' For now, as a test of the buttons, just send a test string to the LCD
' After this is proven, send different texts (bluetooth, PIC to PIC, wordlength, etc.)
if btnr = 1 then btnrgt
if btns = 1 then btnsel
if btnu = 1 then btnup
if btnl = 1 then btnlft
if btnd = 1 then btndwn

goto mainloop

' ----------------------------------------------------------------------------

btnrgt:
SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1
serout lcd,N9600,["Right button"]
pause 500
goto start

btnsel:
SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1
serout lcd,N9600,["Select button"]
pause 500
goto start

btnup:
SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1
serout lcd,N9600,["Up button"]
pause 500
goto start

btnlft:
SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1
serout lcd,N9600,["Left button"]
pause 500
goto start

btndwn:
SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1
serout lcd,N9600,["Down button"]
pause 500
goto start


' ================================================== ==========================

ledanims:

'high PORTB.0
'PORTB.0 = 1
led1 = 1
pause 500
led1 = 0
'led1 = 0 ' <--- If I add this back in, this pin works correctly
'PORTB.0 = 0
'low PORTB.0 ' <--- This statement does the job by itself

'high PORTB.1
'PORTB.1 = 1
led2 = 1
pause 500
'led2 = 0
led2 = 0
'PORTB.1 = 0
'PORTB.1 = 0
'low PORTB.1

'high PORTB.2
'PORTB.2 = 1
led3 = 1
pause 500
led3 = 0
'PORTB.2 = 0
'low PORTB.2

'high PORTB.3
'PORTB.3 = 1
led4 = 1
pause 500
led4 = 0
'PORTB.3 = 0
'low PORTB.3

goto ledanims

richard
- 28th September 2016, 12:28
there is some bad advise here



lcd var LATB.4 ' Serial output to LCD ;THIS IS WRONG
btnr var PORTA.0 ' Right arrow button
btns vAR PORTA.1 ' Select button
btnu var PORTA.2 ' Up arrow button
btnl var PORTA.3 ' Left arrow button
btnd var PORTA.4 ' Down arrow button

' Variable declaration

start:

SerOut lcd,N9600,[254,1] ' Clear LCD screen
Pause 1





use of LATx ports in "highlevel" commands is incorrect and will not work as expected
lcd var PORTB.4 ' Serial output to LCD , IS CORRECT

HenrikOlsson
- 28th September 2016, 15:49
And there are still digits missing where binary representation is used to set the registers, which can be quite confusing.

Dosbomber
- 28th September 2016, 23:22
It looks like you're missing the % in front of all numbers that are to be interpreted as binary by the compiler (or is that just the forum engine dropping that character (again)?)

/Henrik.

They're in the code, they just didn't copy over into the forum copy/paste for some reason.

Thanks for the reply,
Dos

Dosbomber
- 28th September 2016, 23:31
And there are still digits missing where binary representation is used to set the registers, which can be quite confusing.

If you're referring to the sets of 0's and 1's which would be immediately following the percentage sign, as a bank of 8 bits, there are 8 digits in the original code. I hadn't noticed that they got truncated to 6 digits in the paste... very interesting. Anyway yeah, that's another forum/paste glitch.

Dos



TRISA = %00011111 ' Set 0-4 pins on PortA to inputs, 5-7 pins to outputs
TRISB = %00000000 ' Set all pins on PortB to outputs
TRISC = %00000000 ' Set all pins on PortC to outputs

ANSEL = %00000000 ' Make AN0 - AN7 Digital (pins RA0, RA1, RA2, RA3, RA5 on PIC18F26K20)
ANSELH = %00000000 ' Make AN8 - AN15 Digital (pins RB2, RB3, RB1, RB4, RB0 on PIC18F26K20)