Problem with program using pic 16F690

Thread Starter

Cristian Cox

Joined May 13, 2017
18
Hi, I have a question that I would like if someone can help me to answer it.

I am using a pic 16F690, and when I use the following program:

Code:
#include <p16F690.inc>
    __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)

Start:
     bsf   STATUS,RP0
     bcf   TRISC,0x1
     bcf   TRISC,0x3
     bcf   STATUS,RP0
     bsf   PORTC,0x1  ;turn on LED C0
     bsf   PORTC,0x3  ;turn on LED C0
   
     End

I am able to turn ON just port C, bit 3 and stay ON.
But I dont see port C, bit 1, ON, it may be that bit 1 turns on too fast?, if this is the case, why it does not happen
the same with bit 3?

For me, it would make sense that when the following code is executed: bsf PORTC,0x1 ;turn on LED C0
should stay ON?

If I make the following change, bit 3 and 1 turn ON without problem:

Code:
#include <p16F690.inc>
    __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)

Start:
     bsf   STATUS,RP0
   
     bcf   TRISC,0x1
     bcf   STATUS,RP0
     bsf   PORTC,0x1  ;turn on LED C0

     bsf   STATUS,RP0
   
     bcf   TRISC,0x3
     bcf   STATUS,RP0
     bsf   PORTC,0x3  ;turn on LED C0

     bsf   STATUS,RP0
   
     bcf   TRISC,0x2
     bcf   STATUS,RP0
     bsf   PORTC,0x2  ;turn on LED C0

     goto Start
 
     End
Mod edit: code tags
 
Last edited by a moderator:

AlbertHall

Joined Jun 4, 2014
12,345
You have the LED connected directly to the pin, with no current limiting resistor don't you?
When PICs write to a port they actually do a read-modify-write (look in the datasheet). They read the port, modify the value, then write the new value back to the port.

So you set C1. The LED lights, but it is pulling down the voltage on the pin.
Now you attempt to set a different bit in port c.
When it reads the port, it reads a logic zero on C1 because of the LED.
It sets bit 3, bit 1 remains zero, and the value is written back to the port, so now C1 is zero!

You can fix this in code by keeping a register holding the value that you want in port c, set or clear bits in that register, and then write the hlding register to the port.

If you put a resistor in series with the LED so the voltage on the pin is higher than the logic one threshold then your code as it stands will work.

Later PICs have a series LAT registers as well as PORT and TRIS. You would use LAT to output to the port, and to read from the port you would read PORT. The PIC16F690 does not have LAT registers.
 

Thread Starter

Cristian Cox

Joined May 13, 2017
18
Albert, thanks for helping.
I understood about the other solutions you gave me and I will implement them.

But just for trying to understand well your explanation:

Actually, I am using a pickit 2 board that has the C port connected to 4 leds through serial resistors.

When you say:

So you set C1. The LED lights, but it is pulling down the voltage on the pin.
Now you attempt to set a different bit in port c.
When it reads the port, it reads a logic zero on C1 because of the LED.
It sets bit 3, bit 1 remains zero, and the value is written back to the port, so now C1 is zero!


and if I see my code:


  1. #include <p16F690.inc>
  2. __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)

  3. Start:
  4. bsf STATUS,RP0
  5. bcf TRISC,0x1
  6. bcf TRISC,0x3
  7. bcf STATUS,RP0
  8. bsf PORTC,0x1 ;turn on LED C0
  9. bsf PORTC,0x3 ;turn on LED C0
  10. End

Do you mean that when PIC executes line 11 (refered only to bit 3 in C port), it reads again port C, bit 1 (where it finds the Zero (down voltage) ? even that line 11 is only for writting to bit 3? (like reading-modify-write the entire port C?), like in other words, if you want to write a specific bit, it does not matter and both ports of port C are red first?
 

JohnInTX

Joined Jun 26, 2012
4,787
You can fix this in code by keeping a register holding the value that you want in port c, set or clear bits in that register, and then write the hlding register to the port.
That is actually the ONLY way to ensure reliable outputs on those ports. As you can see from the linked material, some of which I wrote, there is lots of discussion about delays after writing, re-reading after bit flipping etc. Ignore them. As AH correctly points out, the real issue is that r-m-w on a port uses a corruptible copy of the initial data to modify. Simple as that, garbage in, garbage out. TRIS registers can be affected as well. Microchip now recommends that TRIS registers should be written as a byte, not bit-diddled.

Note that it is not just bsf/bcf either. Things like andwf,F, iorwf,F or any other instruction, or sequence of instructions, that takes the current value of a register, modifies it then writes the result back to the register is exposed to the r-m-w issue when the file register is a port or TRIS.
 

Thread Starter

Cristian Cox

Joined May 13, 2017
18
Thank you very much Albert and John, it is amazing how valuable is this place and the knowledge around here
best regards
Cristian
 
Top