PDA

View Full Version : Accessing pins with a variable



Desterline
- 13th August 2004, 14:57
Hello all,

I've been working on a project that uses a 16f877a to display some data on some multiplexed 5x7 matrix displays. It's working OK, but I was hoping there was a better way of doing this.

Right now I have the rows driven with bits 0..6 of port B and D (bi-color displays), but the columns are driven with all the leftover pins:
ColA var portd.7
ColB var porte.0
ColC var porta.5
ColD var portc.5
ColE var portc.3
ColF var portc.4
ColG var portb.7
ColH var portc.0
ColI var porte.2
ColJ var porte.1

I'm using a timer interrupt to handle the actual multiplexing:
ISR:

branch currentcol, [INT0,INT1,INT2,INT3,INT4,INT5,INT6,INT7,INT8,INT9]
INT0: 'activate colA only
high colj 'turn off the last column
portb = greendata[0] | %10000000 'mask out the high bit, it controls a colunm drive
portd = reddata[0] | %10000000 'mask out the high bit, it controls a colunm drive
low colA ' turn on new column
currentcol = 1
GOTO INTEND

INT1: 'activate colB only
high cola 'turn off the last column
portb = greendata[1] | %10000000
portd = reddata[1] | %10000000
low colb
currentcol = 2
goto intend

>eight more snipped, you get the idea<

INTEND:
tmr0 = 57
intcon.2 = 0

Resume

Originaly I tried a select case structure for this, but I found that the different cases took different amounts of time to proccess. That led to a very noticable brightness variation accross the display. To counter that I added a different size pause to each case. (as much as 70us). Not suprisingly, performance was kinda crappy :-)

Eventualy I turned to this branch structure, it doesn't have the brightness problem, it runs faster (about 40us, for all cases) and took less code (>80 words less), but it's still ugly. I was hoping for somthing more like:

ISR:
CurrentColumn = CurrentColumn + 1
'add some if-then bounds checking here...

HIGH (CurrentColumn - 1 )
portb = greendata[CurrentColumn] | %10000000
portd = reddata[CurrentColumn] | %10000000
LOW CurrentColumn

tmr0 = 57
intcon.2 = 0

Resume

I know it doesn't work exactly like this, but I was hoping someone might have a way of grouping various pins into an array or something such? (or some other better way to solve this)

Thanks,
-Denny

Ioannis
- 17th August 2004, 07:20
First of all you may replace the High and Low commands with:

variable=1 or variable=0

Memory and speed gain with this trick.


Now for the pin addressing (this was posted long ago by Dennis Saputelli):

pin_index var byte

pin_index=12

porta.0[pin_index]=1 'Sets PortB.4 high.

for a PIC 16F877 pin_index values are:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 pin_index
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 port bit
Port A Port B


16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 pin_index
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 port bit
Port C Port D


32 33 34 pin_index
0 1 2 port bit
Port B


Note that even though the Port A register does not have the upper bits physically, they do count.


Hope that helps,
Ioannis

Melanie
- 17th August 2004, 11:30
I don't think this works in all cases... I posted a similar thread earlier and had to withdraw the posting after heaps of anomalies... more thorough investigation is needed on this one...

Desterline
- 17th August 2004, 16:17
Originally posted by Ioannis
First of all you may replace the High and Low commands with:

variable=1 or variable=0

Memory and speed gain with this trick.


Why didn't I think of that. Seems obvious enough knowing that HIGH X also sets the relevant TRIS bit, but I hadn't considered it takes time and code to do that...

This got me thinking so I did a little test. Just a little programm that blinks an LED

define LOADER_USED 1
define OSC 4
ADCON1 = 7 ' Set PORTA and PORTE to digital

Pin_Index var byte

trisa = 0 'all outputs
trise = 0 'all outputs
pin_index = 0
Main:

'high porta.0
'porta.0 = 1
porta.0[pin_index] = 1 'Sets PortB.4 high

pause 500

'porta.0 = 0
'low porta.0
porta.0[pin_index] = 0

pause 500
goto main

Using the HIGH/LOW comands (others commented out) this compiled to 75 words. But using the PORTA.0 = X it compled to 69 words. (looks like a savings of three words for every HIGH or LOW)
Then I tested the PIN_INDEX method, 115 words. It worked, but it seems to be a lot larger.

Then just for fun I tried compiling them with MPASM instead, I don't understand why (yet :o) but in all cases MPASM compiled to three words less than PM. Anyone know why?


Originally posted by Melanie
I don't think this works in all cases... I posted a similar thread earlier and had to withdraw the posting after heaps of anomalies... more thorough investigation is needed on this one...


Melanie, could you be a little more specific about the anomalies? Was it certain pics, code sequences, phase of the moon, was Mercury in retrograde? ;-)

-Denny

RossW
- 18th August 2004, 19:03
If I do this on a 12f629:

CMCON = 7
TRISIO = 0

LED_0 = GPIO.0

LED_0 = 1


... it doesn't work.

Dwayne
- 18th August 2004, 20:32
Hello Ross,

Ross>>CMCON = 7
TRISIO = 0

LED_0 = GPIO.0

LED_0 = 1
<<

Better Assign LED_0 to a value!

Something like LED_0 var byte

Dwayne

Bruce
- 18th August 2004, 22:05
> If I do this on a 12f629:

> CMCON = 7
> TRISIO = 0

> LED_0 = GPIO.0

> LED_0 = 1


> ... it doesn't work.

Try this and see how it works.

ANSEL = 0 ' Set all digital
CMCON = 7 ' Analog comparators off
TRISIO = 0
LED_0 VAR GPIO.0

Loop:
LED_0 = 1
PAUSE 250
LED_0 = 0
PAUSE 250
GOTO Loop

RossW
- 19th August 2004, 15:03
My post had a mistake, but in my code I had LED_0 var GPIO.0, and it didn't work setting LED_0 = 1

Ross

Melanie
- 19th August 2004, 15:16
That's because you forgot about initialising the ANSEL register. see Bruce's example.

RossW
- 20th August 2004, 16:03
I didn't think there was an ANSEL register on the 12f629, only CMCON ?!?