PDA

View Full Version : A way to define specific ports for output bits? start output in middle port?



wdmagic
- 2nd January 2013, 11:43
say I wanted to output binary numbers (4bit, or 3 bit, or 5 bit) my choice- but lets say 3bit right now so I want to output a number (0-7). the trick is I dont want to start with PORTx.0 to PORTx.2, say i want to use PORTx 3 - 5. is this possible and how would I do it. ???

also if this is possible can you use any ports to build an output, say you need 8 ports to build a byte output could you build 8 seperate I/O's from different ports like


MYBYTE VAR BYTE

MYBYTE.0 = PORTA.7
MYBYTE.1 = PORTA.3
MYBYTE.2 = PORTB.4
MYBYTE.3 = PORTB.5
MYBYTE.4 = PORTB.6
MYBYTE.5 = PORTC.2
etc....

the first question is primary, the second is elective, just curious

wdmagic
- 12th January 2013, 06:44
Ok right now Im having a problem, On PORTB.0 = INT0
now I want to use PORTB.1-3 as a binary output from 0-7
but since my portb.0 isnt available, how do i set it to start my output at bit 2 (portb.1)
my only available pins right now is portb 1-5, I need a 3bit binary output that will go to a 3bit to 8decimal chip that drives 8 leds.
I was hoping theres a command like in the LCD commands to say start bit = ?

HenrikOlsson
- 12th January 2013, 08:56
Hi,
A bit convoluted but it hopefully shows what's happening:

Temp = PortB.0 & %11110001 ' Read PortB into Temp and clear bits 1-3 ( & is bitwise AND)
Value = 5 ' This is the value that will be written to bits 1-3
Value = Value << 1 ' Shift value to the left one place to "align it" with bits 1-3
PortB = Temp | Value ' Write new value back to PortB. ( | is bitwise OR )


Or

Temp = PortB.0
Value = 5
Temp.1 = Value.0
Temp.2 = Value.1
Temp.3 = Value.2
PortB.0 = Temp

Or, if a bit bitflipping on the port doesn't matter

Value = 5
PortB.1 = Value.0
PortB.2 = Value.1
PortB.3 = Value 2

And I'm sure there are other ways.

/Henrik.

Acetronics2
- 12th January 2013, 09:08
Hi,

I think Darrel wrote something about that ... some times ago.

this was the origin of "LCD on Any pin" !

Here it is ...



'************************************************* ***************
'* Name : VirtualPort.bas *
'* Author : Darrel Taylor *
'* Date : 3/20/2006 *
'* Version : 1.1 *
'* Notes : Allows you to control non-contiguous PINs/BITs *
'* : as if they were a contiguous PORT/Register *
'************************************************* ***************
'* See this Webpage for more info *
'* http://www.picbasic.co.uk/forum/showthread.php?t=4074 *
'************************************************* ***************
'* with assistance from: *
'* 1.1 SteveB *
'* 1.2 ? *
'************************************************* ***************

disable debug


VP_DelayCount VAR WORD BANK0 ; Used for internal Delay only

ASM
PortVar set 0
; nolist

;----[Defines a Virtual PIN in a Virtual PORT]--------------------------------
Vpin macro Vb, P, Pbit
local Vaddr, VarBit
if (Vb < 16) ; If Var bit# is < 16
if (Pbit < 8) ; and Port bit# is < 8
if (PortAction < 2)
if (Vb > 7) ; Var Bit > 7, use high word
Vaddr = PortVar + 1
VarBit = Vb - 8
else
Vaddr = PortVar
VarBit = Vb
endif
endif
if (PortAction == 0) ; read
MOVE?TT P, Pbit, Vaddr, VarBit
else
if (PortAction == 1) ; write
MOVE?TT Vaddr, VarBit, P, Pbit
else
if (PortAction == 2) ; output
PhysicalPort P ; only if it's a Real PORT
if (Found == 1)
OUTPUT?T P, Pbit
endif
else
if (PortAction == 3) ; input
PhysicalPort P ; only if it's a Real PORT
if (Found == 1)
INPUT?T P, Pbit
endif
endif
endif
endif
endif
else
error Vpin - PORT BIT [Pbit] Out of Range
endif
else
error Vpin - Variable BIT [Vb] Out of Range
endif
endm

;----[Copy a bit to a Pin]----------------------------------------------------
Vbit macro Rin,Bin, Rout,Bout
MOVE?TT Rin,Bin, Rout,Bout
endm

;----[Read a Virtual Port]----------------------------------------------------
ReadPort macro PortVar, PinMacro
; nolist
PortAction = 0 ; Read
PinMacro
list
endm

;----[Write a variable to a Virtual Port]-------------------------------------
WritePort macro PortVar, PinMacro
; nolist
PortAction = 1
PinMacro
list
endm

;----[Set ALL pins of a virtual Port to OUTPUT]-------------------------------
OutputPort macro PinMacro
; nolist
PortAction = 2
PinMacro
list
endm

;----[Set ALL pins of a virtual Port to INPUT]--------------------------------
InputPort macro PinMacro
; nolist
PortAction = 3
PinMacro
list
endm

; These 4 are useful for Port Control Pins, such as Enable and Direction pins
; They don't change the TRIS state during INPUT/OUTPUT calls, which makes
; bi-directional ports a lot easier.

;----[Make a Pin LOW]---- Does not change TRIS bit ---------------------------
PinHigh macro P, B
; nolist
if (PortAction < 2) ; Don't do anything on Input or Output pass
MOVE?CT 1, P, B ; Make Pin HIGH
endif
list
endm

;----[Make a Pin LOW]---- Does not change TRIS bit ---------------------------
PinLow macro P, B
; nolist
if (PortAction < 2) ; Don't do anything on Input or Output pass
MOVE?CT 0, P, B ; Make Pin LOW
endif
list
endm

;----[Similar to PAUSEUS, but ASM interrupt compatible]---(accurate to 1uS)---
DelayUS macro T
; nolist
local InstCount, LoopCount, DelayLoop, LoopsDone, LeftOver, Offset
; -- Calculate number of 3 cycle loops plus leftover nop's to execute --
InstCount = ((OSC*10/4)*T+5)/10 ; Inst cycles required for delay (Rounded UP)
LoopCount = InstCount / 3
if (LoopCount > 255)
Offset = (LoopCount >> 8) * 7 + 4
else
Offset = 0
endif
; -- Adjust for HighByte --
InstCount = InstCount - Offset
if (Offset > (LoopCount & 0FFh))
InstCount = InstCount - 4
endif
LoopCount = InstCount / 3
if (LoopCount > 255)
Offset = (LoopCount >> 8) * 7
else
Offset = 0
endif
LeftOver = InstCount % 3
;-------------------------------------------
if (LoopCount > 0)
MOVE?CW LoopCount, _VP_DelayCount
DelayLoop
decfsz _VP_DelayCount, F ; 1
goto DelayLoop ; 2 3 per loop, under 256

if (LoopCount > 255)
movf _VP_DelayCount + 1, W ; 1
btfsc STATUS, Z ; 1
goto LoopsDone ; 2 4 on last loop

decf _VP_DelayCount + 1, F ; 1
goto DelayLoop ; 2 7 per highbyte count
LoopsDone
endif
endif
if (LeftOver > 0)
nop
endif
if (LeftOver > 1)
nop
endif

list
endm

;----[Pulse a Pin LOW for a specified number of uS]---------------------------
PulseLow macro P, B, Time
; nolist
PhysicalPort P
if (Found == 1) ; only if it's a Real PORT
if (PortAction < 2)
MOVE?CT 0, P, B
DelayUS Time
MOVE?CT 1, P, B
endif
else
error "PulseLow - Can only Pulse a Physical Pin"
endif
list
endm

;----[Pulse a Pin HIGH for a specified number of uS]---------------------------
PulseHigh macro P, B, Time
; nolist
PhysicalPort P
if (Found == 1) ; only if it's a Real PORT
if (PortAction < 2)
MOVE?CT 1, P, B
DelayUS Time
MOVE?CT 0, P, B
endif
else
error "PulseHigh - Can only Pulse a Physical Pin"
endif
list
endm

;----[Is the PIN a Physical PIN or just a register?]-----(Compile Time Only)--
PhysicalPort macro P
; nolist
Found = 0
ifdef GPIO
if P == GPIO
Found = 1
endif
endif
ifdef PORTA
if P == PORTA
Found = 1
endif
endif
ifdef PORTB
if P == PORTB
Found = 1
endif
endif
ifdef PORTC
if P == PORTC
Found = 1
endif
endif
ifdef PORTD
if P == PORTD
Found = 1
endif
endif
ifdef PORTE
if P == PORTE
Found = 1
endif
endif
ifdef PORTF
if P == PORTF
Found = 1
endif
endif
ifdef PORTG
if P == PORTG
Found = 1
endif
endif
ifdef PORTH
if P == PORTH
Found = 1
endif
endif
ifdef PORTI
if P == PORTI
Found = 1
endif
endif
ifdef PORTJ
if P == PORTJ
Found = 1
endif
endif
ifdef PORTK
if P == PORTK
Found = 1
endif
endif

list
endm

list
ENDASM

disable debug
;----[Trick PBP into including certain macro's]---Doesn't use any code space--
@ ifdef NotCompiled
@DummyPort = 0
DummyPort VAR BYTE EXT
OUTPUT DummyPort.0 ; OUTPUT?T
INPUT DummyPort.0 ; INPUT?T
@ endif

enable debug




Alain

Ioannis
- 12th January 2013, 10:11
OK, Alain. Very nice idea to set or reset a bit!

:)

Ioannis

wdmagic
- 12th January 2013, 10:22
I kinda like your idea henrik, but im alittle confused on a couple of the terms "bitwise, shifting" I dont normally do this kind of thing in code.
My PORTB.0 is being used as a interupt, is there a way to do something to shift the number over
Sorry ACE i was totally confused by that code.

What I need with very little coding.
MYVAL = 7 ' 00000111
SHIFTCODE MYVAL < ? & make bit.0 1 ' New MYVAL = 00001111
PORTB = MYVAL

now as far as i understand I need to make sure any code that is sent to portb has portb.0 as a 1, since i need to keep it high, until a button is pressed. I dont want to trigger a INT by sending a low to that pin. but I need to shift the first 3 bits to the left and make sure the first bit ends up a 1.

wdmagic
- 12th January 2013, 10:34
heres a copy of an sample program code needs to be fixed, think of it lighting 3 led's in binary sequence


PORTB.0 = INT ' Just a INT Code Placeholder
X VAR Byte : X = 0

MyLOOP:
PORTB.1-3 = X ' Shifting Code Needed
pause 1000
X = X + 1
if X > 7 then X = 0
Goto MyLoop

HenrikOlsson
- 12th January 2013, 11:44
Hi,
First of all, there's an error in my previous example. The shift left operator is of course << and nothing else, sorry about that. The "edit window" is closed so I can't go back and fix it.

With your code as an example, try this:

MyLoop:
Temp = PortB & %11110001
PortB = Temp | (X << 1)
X = X + 1
IF X > 7 THEN X = 0
PAUSE 1000
Goto MyLoop

Lets go thru the two first lines:
Temp = PortB & %11110001 - This reads the state of PortB into a variable called Temp and ANDS it with the value 14. What's happening there is that Temp will be whatever PortB is except for bits 1-3 which will be cleared to 0.
PortB = Temp | (X << 1) - This takes the value of Temp and ORs with the value of X shifted one "step" to the left. Remember that Temp is a copy of what PortB was except bits 1-3 which are now 0. So if X is 3 (%00000011) PortB will be %xxxx011x where x is whatever was there before because X is shifted one "step" before ORing it with Temp.

When doing a bitwise AND on two numbers each bit must be '1' in BOTH numbers for the bit to be '1' in the "result. So when doing a bitwise and with a value where certain bits are '0' those bits will be '0' in the result, example.
%11111111 & %00000000 = %00000000
%11111111 & %11110000 = %11110000
%11001000 & %00001111 = %00001000

When doung a biteise OR on two numbers it's enough that a bit in either number is '1' for that bit to be '1' in the result, example:
%11111111 | %00000000 = %11111111
%00000000 | %00001111 = %00001111
%11110000 | %00001111 = %11110000

So in the above code we read in PortB, clear bits 1-3 and put the value of X in those 3 bits.

/Henrik.

Acetronics2
- 12th January 2013, 13:41
just some MORE browsing job ...

http://www.picbasic.co.uk/forum/showthread.php?p=22065

yes ... relevant threads already exist :rolleyes:

@#14 ... how to use Virtualport.bas

Next step ???

Alain

wdmagic
- 13th January 2013, 02:03
So if i dont care about PORTB's other bits could it work like this?


MyLoop:
Temp = X << 1
TEMP.0 = 1 ' to Keep PORTB.0 High
PortB = Temp
X = X + 1
IF X > 7 THEN X = 0
PAUSE 1000
Goto MyLoop

HenrikOlsson
- 13th January 2013, 09:35
Hi,
Yes, if you don't care what's happening with PortB.4-7 then that should work.

If PortB.4-7 are outputs then your aproach won't work properly since you'll overwrite those bits with the value of Temp. That's the reason for first reading PortB and ANDing it with %11110001 so that we ONLY change the state of bits 1-3 when ORing Temp with X. If all bits except 1-3 are inputs then your aproach should work - which brings me to the next point...

I suspect the purpose with "keeping PortB.0 high" is to prevent it from tripping an interrupt? If so I don't think you need to worry about that.
When PortB.0 is setup as an input, it doesn't matter what you write to PortB.0 - it'll never actually "get to" the actual pin since the output driver is disabled. Look at the block diagram of the pin in the datasheet, this is for the 16F887 it may differ slightly from whatever device you're using:

6814

The "interrupt path" is drawn in blue here. The output driver is circled in red. As you can see the output driver is enabled/disabled by D-type flip-flop which is controlled by writing to TRISB. So, even if you write '0' to PortB.0 it'll never reach the pin and cause an interrupt since that '0' won't "go thru" the output driver.

/Henrik.

wdmagic
- 13th January 2013, 10:25
ok thanks henrik, yes there is nothing connected to portb 4-7, theres no room for me to add those ports to anything as the ports are blocked by other circuit traces. and yes I was thinking of the INT on portb.0 , but I do see your logic there, since ive made it a tris=1 then it shouldnt change state even if I tell it to in code., thanks for the diagram, if I didnt need the INT and if I could get to the other B pins i would just use the 8 leds direct but I dont have that option so this will work, thanks.