Pinouts go low after PORTC AND operation

Thread Starter

DR4DR4

Joined Aug 5, 2012
2
Hi, this is my first post. I'm new to programming and micro controllers but have started using a few PIC's with MPLAB X and the HITEC C version9..? something compiler.

This is only a query as I would like to know why I'm getting this particular behaviour which I will try to explain. I'm using a 16F690 PIC on a low pin count board and a pickit 2 programmer.
I also made myself a hardware tfla-01 logic analyzer, the design with it's own power and resistors and an isolating chip. I made it a little while ago so can't remember details but it's not relevant to my question.

I read an article about left shifting a binary and OR' ing it with the port register to turn pins high and AND'ing a two's complimented version for low. I have walked the below code through using MPLAB's simulator. Viewing the PORTC register contents goes like I would have thought it should.

PORTC
starts – 000000 ...→ 000001 → 000011 → 000111 → 001111 → 001110...[the final &=~]

Also when I use the software logic analyzer in the simulator to trace RC0-RC3 they go up as I would expect consistent with the above. What should happen then is rc0 goes up, then rc1..rc2..rc3.
Then rc0 should go low.. this loops so rc0 toggles of and on but the other pins stay high.

Now I program my PIC and get each led light in sequence from rc0 to rc3 turn on individually.
When I trace using the hardware tfla-01 analyzer this confirms after each shift operation only the shifted bit brings that pin high, the other 1's that remain in the PORTC register don't keep their respective pins high. The time delay between shifts is set to 500ms. Code snippet below.



Portc set for ouput and initialized all pins low...+ #define delay 500
...
PORTC|=(1<<0);//enable rc0 - zero shift 1 then OR with portc register
__delay_ms(delay);
PORTC|=(1<<1);//rc1 up
__delay_ms(delay);
PORTC|=(1<<2);//rc2 up
__delay_ms(delay);
PORTC|=(1<<3);//rc3 up
__delay_ms(delay);

PORTC&=~(1<<0);//disable rc0
__delay_ms(delay);
...loops

So my query is why when bit's are set to 1 in the PORTC register do they not hold the pin high. They only hold the individually shifted bit place pin high, the rest go low. The 16F690 does not support in circuit debugging without a header so I can't know that on the chip this is also the case and it may differ from the simulated register.

I'm aware that the software simulation is just that already after trying to trace clkout signal, this signal does not exist on the simulator but does when using the chip.

This may be very obvious to someone with more experience but at this time of writing I would have thought all 1's in the register would keep the pinouts high.
Any explanations welcomed.

Doug.
 

BMorse

Joined Sep 26, 2009
2,675
Might have something to do with the uC's "write then read" on the ports (dont really have time to go through datasheet), try assigning the values to a variable then transfer data to port pins. . .
 

JohnInTX

Joined Jun 26, 2012
4,787
Have you cleared the ANSELH and ANSEL registers to make the port pins digital? They are analog when the PIC is reset. You can output a 1 but when you do a r-m-w on the port for the next pattern the 1 you just wrote will be read back as 0 and clear the LED pin when the new pattern is written to the port.

try assigning the values to a variable then transfer data to port pins. . .
A secondary point here perhaps but yeah, in my world, that's the ONLY way I do midrange I/O.. for lots of good reasons.
 
Last edited:

ErnieM

Joined Apr 24, 2011
8,377
Your code is doing what you told it to do. Here's the terms broken out to show what values are really being used:
Rich (BB code):
PORTC = 0

PORTC   |= (1<<0);
        |= 000001
         = 000001

PORTC   |= (1<<1)
        |= 000010
         = 000011

PORTC   |= (1<<2)
        |= 000100
         = 000111


PORTC   |=(1<<3)
        |= 001000
         = 001111

PORTC   &= ~(1<<0)
        &= ~000001
         =  111110 & 001111
         =  001110
Note this is not C code, just the actual data being used.
 

Thread Starter

DR4DR4

Joined Aug 5, 2012
2
Thanks to everybody for the replies.

The ANSEL & ANSELH analogue select registers were at their default enabled.
I cleared these registers and the lights stayed on as I had first thought they would.
So this was in fact the thing stopping my lights from staying on and my port pins from staying high.

I see lots of references to use another register when setting the port registers for reliable behaviour and to avoid any read-modify-write issues so I will use this method in the future.

My issue is solved so thanks for that
#####################################################################

Not really an issue but…


The RC4 port is not an analogue port and was the one port that went high and stayed high. This makes sense because it’s digital i/o and behaved like the other ports when they were analogue disabled.

When I disabled analogue via ANSEL this port behaved differently, which I did not expect. With the same program it blipped high for half a millisecond or so and stayed low ‘maybe’ pulling the rest of the pins low as well until the next instruction to clear RC0. At this time it went high along with the rest of the port pins that were supposed to be staying high.

Maybe it’s down to my circuit, rc4 is not connected to anything, the leds are on ports rc0-rc3. Or maybe it’s some other fuse setting, should ANSEL&ANSELH only affect the analogue pins.

Again to summarize by setting ANSEL & ANSELH to zero the shift to enable RC4 pulls all up pins low until the next shift to clear RC0 when RC1-RC4 all go high again.

Code snippet:-
https://dl.dropbox.com/u/83933129/code_snippet.txt

Analyzer output with RC4 enable commented out [ch3-ch7=RC0-RC4]:-
https://dl.dropbox.com/u/83933129/rc4excluded.png

Output with RC4 statement uncommented:-
https://dl.dropbox.com/u/83933129/rc4included.png


Just curious if anybody knows why that happens?

Thanks again Doug.
 
Last edited:
Top