PDA

View Full Version : Indexing Port Pins



Bruce
- 21st April 2006, 18:58
Melanie posted an excellent article on indexing bits, bytes, words, etc. here
http://www.picbasic.co.uk/forum/showthread.php?t=544

Someone asked how to index port pins in a similar way, so here's one way.

Port file register addresses are sequential. For instance on the 16F876A file
register address for porta is at location 05h, portb is at 06h, and portc is at
07h. All you need is a pointer to the base of the bit index.

Example; SYMBOL PORT_PIN = PORTA ' <- start of bit index or pointer

Now using something like this, you can index all port bits.


X VAR BYTE ' For loop & bit index pointer
ADCON1 = 7 ' All digital
PORTA = 0 ' Clear all port pins
PORTB = 0
PORTC = 0

TRISA = 0 ' Make them all outputs
TRISB = 0
TRISC = 0

FOR X = 0 TO 23
PORT_PIN.0[X] = 1 ' Set all porta, portb, and portc pins high
NEXT X


There aren't 8 pins on porta that can go high, but it's still an 8-bit file register
so we have to treat it as 8-bit and index from 0 to 23 for 24-bits total.

You can do this on any PIC to index all port pins individually just using porta
as the starting index pointer.

PBP doesn't perfom bounds checking, so you can get away with indexing
out of bounds.

Note that also means you could write to a register you may not intend to if
you're not careful.

You could drop porta, and just use portb as the starting address also.


SYMBOL PORT_PIN = PORTB

X VAR BYTE ' For loop & bit index pointer

PORTB = 0
PORTC = 0

' Make them all outputs
TRISB = 0
TRISC = 0

FOR X = 0 TO 15 ' 16-bits total
PORT_PIN.0[X] = 1 ' Set all portb, and portc pins high
NEXT X

sayzer
- 12th September 2006, 14:50
In addition to Bruce's nice examples, and in connection with Melanie's explanations, mixed port pins can be driven in a sequence with the code below. The code is for demonstration purposes and quite easy to figure out.






TRISA = %00000000
TRISB = %00000000
TRISC = %00000000
TRISD = %00000000
TRISE = %00000000
ADCON1 = %00000000
PORTA = 0
PORTB = 0
PORTC = 0
PORTD = 0
PORTE = 0

MYPORT VAR BYTE
LOOP var BYTE

'======Say you have to drive
'these pins in a sequence. They are all mixed.

RelayA VAR PORTA.1
RelayB var PORTA.3
RelayC var PORTB.5
RelayD var PORTC.0
RelayE var PORTD.2
RelayF var PORTD.4
RelayG var PORTE.0

MYPORT=0


Start:

for loop=1 to 7

myport.0[loop]=1 'High
gosub driveport

pause 1000

myport.0[loop]=0 'Low
gosub driveport

next loop


goto start



DrivePort:
RELAYA = myport.1
RELAYB = MYPORT.2
RELAYC = MYPORT.3
RELAYD = MYPORT.4
RELAYE = MYPORT.5
RELAYF = MYPORT.6
RELAYG = MYPORT.7
return



END






Hope it can be some help to some members.

Regards.

isaac
- 5th December 2006, 15:19
Hi Bruce / sayzer

Just being reading your interesting posts about port indexing
and wanted to know if it was posible to map a variable to different ports
example say like using a word variable to control the 16bits below
How to i go about this? Is it possible ?
RB7 = //MSB
RB6
RB5
RB4
RB3
RB2
RB1
RB0
RA0
RA1
RA2
RA3
RD0
RD1
RD2
RD3 //LSB

Hope you can help

Regards
Isaac

Bruce
- 5th December 2006, 16:25
Hi Isaac,

See this thread for some ideas: http://www.picbasic.co.uk/forum/showthread.php?t=4074

sayzer
- 5th December 2006, 18:30
Hi Bruce / sayzer....
...using a word variable to control the 16bits below
How to i go about this? Is it possible ?...


I do not think you can drive the ports or port pins directly by using alias on them via a the bits of a WORD or BYTE variable.


For example,

MYPORT VAR WORD

PORTA.1 VAR MYPORT.0 is an incorrect arrangement.

MYPORT.0 VAR PORTA.1 is also incorrect.

PORTB VAR MYPORT.HighByte incorrect.

PORTA VAR MYPORT incorrect


But,
PORTB = MYPORT

or

PORTB = MYPORT.HighByte or PORTB = MYPORT.LowByte can be ok!



But anyway, in addition to the link that Bruce posted, here I posted an example with the port pins you listed.

See if it is what you needed.




'Assuming you have the ports set up.

Loop VAR BYTE
MYPORT VAR WORD
MYPORT = 0
GOSUB DriveMeCrazy 'Pull all pins low.


Start:

FOR LOOP = 0 TO 15

MYPORT.0[LOOP] = 1 'HIGH
GOSUB DriveMeCrazy

PAUSE 1000 'Give it a pause as an example.

MYPORT.0[LOOP] = 0 'LOW
GOSUB DriveMeCrazy

NEXT LOOP


GOTO START



DriveMeCrazy:

PORTB.7 = MYPORT.15
PORTB.6 = MYPORT.14
PORTB.5 = MYPORT.13
PORTB.4 = MYPORT.12
PORTB.3 = MYPORT.11
PORTB.2 = MYPORT.10
PORTB.1 = MYPORT.9
PORTB.0 = MYPORT.8 'From here to above, "PORTB = MYPORT.HighByte" may also be ok.
PORTA.0 = MYPORT.7
PORTA.1 = MYPORT.6
PORTA.2 = MYPORT.5
PORTA.3 = MYPORT.4
PORTD.0 = MYPORT.3
PORTD.1 = MYPORT.2
PORTD.2 = MYPORT.1
PORTD.3 = MYPORT.0

RETURN

isaac
- 9th December 2006, 18:52
Thanks Bruce /sayzer

Your examples did help me get it sorted
you both have being great

Isaac

Demon
- 5th January 2014, 09:31
Update: Cleaned up logic so LEDs always get same current no matter how many are in use.


When you need to blink a lot of LEDs:

Here's the results of a current test using 32 LEDs on a 18F44K22 using internal oscillator at 64MHz.



portLedA var PORTA ' Define Ports
portLedB var PORTB
portLedC var PORTC
portLedD var PORTD
portLedE var PORTE

byteLoop VAR byte ' Define variables
byteDelay VAR byte

byteActiveA var byte ' Define active pins
byteActiveB var byte
byteActiveC var byte
byteActiveD var byte
byteActiveE var byte

byteRXA var byte ' Define RX data
byteRXB var byte
byteRXC var byte
byteRXD var byte
byteRXE var byte

portLedA = %00000000 ' Initialize Leds off
portLedB = %00000000
portLedC = %00000000
portLedD = %00000000
portLedE = %00000000

byteActiveA = %11111110 ' Determine Active pins Pin A.0 not used
byteActiveB = %11111111
byteActiveC = %00111111 ' RX / TX in use
byteActiveD = %11111111
byteActiveE = %00000111 ' MCLR input only

byteRXA = %11111110 ' RX data from Master PIC
byteRXB = %11111111
byteRXC = %00111111
byteRXD = %11111111
byteRXE = %00000111

byteDelay = 35 ' Tweak this value to control current and frequency

' 1 LED active 668 Hz 2.7 mA LED 14.2 mA circuit
' 32 LEDs active 668 Hz 2.7 mA LED 99.0 mA circuit

' Using 2N2222 NPN transistor, 4K7 base with 680K pull-down,
' LED direct to collector from 5VDC.

mainloop:

For byteLoop = 0 to 7 ' Go through 8 bits
if byteActiveA.0[byteLoop] = 1 then ' Check if pin is used
portLedA.0[byteLoop] = byterxA.0[byteLoop]
PAUSEUS byteDelay
portLedA = %00000000 ' Faster than setting bit to 0
endif
if byteActiveB.0[byteLoop] = 1 then
portLedB.0[byteLoop] = byterxB.0[byteLoop]
PAUSEUS byteDelay
portLedB = %00000000
endif
if byteActiveC.0[byteLoop] = 1 then
portLedC.0[byteLoop] = byterxC.0[byteLoop]
PAUSEUS byteDelay
portLedC = %00000000
endif
if byteActiveD.0[byteLoop] = 1 then
portLedD.0[byteLoop] = byterxD.0[byteLoop]
PAUSEUS byteDelay
portLedD = %00000000
endif
if byteActiveE.0[byteLoop] = 1 then
portLedE.0[byteLoop] = byterxE.0[byteLoop]
PAUSEUS byteDelay
portLedE = %00000000
endif
Next byteLoop

Goto mainloop ' Go back to loop and blink LEDs forever

Use byteActiveA-E variables to determine which bits you want toggled.

Use byteRXA-E variables to receive bits from a Master PIC.

Use byteDelay variable to tweak current and LED brightness.


For my testing, MCLR (can only be input), RX/TX (needed) and A0 (unused) were disabled.

Robert

http://i991.photobucket.com/albums/af37/DemonDNF/Electronics/Alarm/IMG_20140106_002313_zps823f73bb.jpg (http://s991.photobucket.com/user/DemonDNF/media/Electronics/Alarm/IMG_20140106_002313_zps823f73bb.jpg.html)