Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC16F631 and Port not going low again

Status
Not open for further replies.
Have you read this it part of CC5X
// INT16CXX.H: saving and restoring registers during interrupt
/*
IMPORTANT: CC5X will AUTOMATICALLY check that the registers W,
STATUS, PCLATH and FSR are saved and restored during interrupt.

CC5X also supports CUSTOM save and restore sequences. If you want
to use your own register save and restore during interrupt, please
read the following CUSTOM INTERRUPT SAVE AND RESTORE section.


// DEFAULT INTERRUPT STRUCTURE (RECOMMENDED)

#include "int16CXX.h"

#pragma origin 4

interrupt serverX( void)
{
/* W and STATUS are saved by the next macro. PCLATH is also
saved if necessary. The code produced is CPU-dependent. */

int_save_registers // W, STATUS (and PCLATH if required)

//char sv_FSR = FSR; // save FSR if required

// handle the interrupt (insert application code here)

//FSR = sv_FSR; // restore FSR if saved

int_restore_registers // W, STATUS (and PCLATH if required)

/* IMPORTANT : GIE should normally NOT be set or cleared in
the interrupt routine. GIE is AUTOMATICALLY cleared on
interrupt entry by the CPU and set to 1 on exit (by
RETFIE). Setting GIE to 1 inside the interrupt service
routine will cause nested interrupts if an interrupt is
pending. Too deep nesting may crash the program ! */

/* IMPORTANT : It is NOT recommended to specify the interrupt
save style (i.e. INT_xxx_style) in the application. This
is done in the chip HEADER file (f.ex. 16F877.h). Wrong
register save style may cause strange problems and is very
difficult to trace. */
}

The compiler will detect if the FSR register is modified during
interrupt processing without being saved and restored. The
supplied macros for saving and restoring registers will not save
FSR. This have to be done by user code when needed. If FSR is
modified by a table or pointer access, or by direct writing, the
compiler will check that FSR is saved and restored, also in
nested function calls. Note that the FSR saving and restoring
can be done in a local region surrounding the indexed access,
and does not need to be done in the beginning and end of the
interrupt routine.

A warning is printed if FSR is saved but not changed.

The error and warning messages printed can be removed:

#pragma interruptSaveCheck n // no warning or error
#pragma interruptSaveCheck w // warning only
#pragma interruptSaveCheck e // error and warning (default)

Note that the above pragma also change the checking done on W,
STATUS and PCLATH.


// CUSTOM INTERRUPT SAVE AND RESTORE:

It is not required to use the above save and restore macros. CC5X
also supports custom interrupt structures.

A) You may want to use your own save and restore sequence. This
can be done by inline assembly. Take a look at the macros at
the end of this file to get an idea on how to do this. If CC5X
does not accept your code, just insert (on your own risk):

#pragma interruptSaveCheck n // no warning or error

B) No registers need to be saved when using the following
instructions in the interrupt routine. The register save
checking should NOT be disabled.
 
Do you observe the same issue if you apply 0 V to RA4 instead of ~1V? It looks like the applied voltage is not low enough.

1V is in the "undefined" region for a TTL input (which RA4 is). TTL inputs are undefined between 0.8V and 2.0V.

Mike
 
1V is in the "undefined" region for a TTL input (which RA4 is). TTL inputs are undefined between 0.8V and 2.0V.

Mike

I know :) 1 V is not a good '0' for a TTL input.
The voltage of about 1 V he is applying is very likely the cause of the problem. However, 'about 1 V' doesn't give the exact idea of what is the low input level.

On a side note, isn't RA4 a Schmitt trigger input by default on this PIC? unless you clear the CM2CON1 register, I believe it works as ST (if that is the case, the voltage thresholds are dependent on Vdd, Vl=0.2Vdd, Vh=0.8Vdd). Having Vl=1 V (if Vdd=5) could not be enough either.
 
Last edited:
I know :) 1 V is not a good '0' for a TTL input.
The voltage of about 1 V he is applying is very likely the cause of the problem. However, 'about 1 V' doesn't give the exact idea of what is the low input level.

On a side note, isn't RA4 a Schmitt trigger input by default on this PIC? unless you clear the CM2CON1 register, I believe it works as ST (if that is the case, the voltage thresholds are dependent on Vdd, Vl=0.2Vdd, Vh=0.8Vdd). Having Vl=1 V (if Vdd=5) could not be enough either.

If you look at the RA4 block diagram in the datasheet, you will see that RA4 is only a Schmitt trigger as used to gate timer1. When read as PORTA, it is always a normal TTL input regardless of whether it is also being used to gate timer1. So changing CM2CON1 (to change the T1GSS bit) has no affect on RA4 as read via PORTA.

Mike
 
Do you observe the same issue if you apply 0 V to RA4 instead of ~1V? It looks like the applied voltage is not low enough.

Before I apply an input to the port it's 0v and after it's ~1v on the resistor side turning away from the PIC and ~5v on the side connected to the port.

This tells me that the ~1v is a result of the resistor cutting down 5v coming from PORTA.4.

Correct me if I'm wrong
 
Before I apply an input to the port it's 0v and after it's ~1v on the resistor side turning away from the PIC and ~5v on the side connected to the port.

This tells me that the ~1v is a result of the resistor cutting down 5v coming from PORTA.4.

Correct me if I'm wrong

That sounds a lot different than what you said before. So, you actually measure 5V at RA4 pin (pin 3), and at the same time measure 1V on the other end of the 47K resistor?

How did you make this measurement?

Mike
 
This tells me that the ~1v is a result of the resistor cutting down 5v coming from PORTA.4.
You have a voltage divider A resistor only drops current the 2.5 is a 2.5k
 

Attachments

  • divider.PNG
    divider.PNG
    4.6 KB · Views: 131
Last edited:
Are you sure you don't have weak pull-ups enabled? If OPTION_REG.7 (RABPU) is 0 then they would be enabled, and the individual pull-up bits in WPUA default to 1 (on). A weak pull-up could supply enough current to keep the pin ~5V even if the other side of the 47K resistor was grounded. You show a commented out line in your init routine that would have enabled weak pull-ups if it weren't commented out.

//OPTION_REG = 0b00001111;

I suspect that some code that you execute after the first time RA4 goes high sets OPTION_REG.7 to zero. That would enable the weak pull-up, and with the 47K resistor, would hold the pin high.

BTW, there is no weak pull-up on RC7

Mike
 
Last edited:
I have set OPTION_REG.7 = 1 and it dosn't help, the port still stays high once I've had an input on it.

Turns out that it's my delay rutine

Code:
void delay10( char n) //delay10( 100);  /* 1 second */
/*
  Delays a multiple of 10 milliseconds using the TMR0 timer
  Clock : 4 MHz   => period T = 0.25 microseconds
  1 IS = 1 Instruction Cycle = 1 microsecond
  error: 0.16 percent
*/
{
    char i;

    OPTION = 7;
    do  {
        clrwdt();  // only if watchdog enabled
        i = TMR0 + 39; /* 256 microsec * 39 = 10 ms */
        while ( i != TMR0)
            ;
    } while ( --n > 0);
}

If I disable a call to this function that is being called from my Running_Led() function it all works, except for the fact that there's no delay in the lights being turned off and on, so they look like they are all turned on at the same time, when in fact they are turning on and off faster than I can see it.

I think it has something to do with the OPTION = 7, but I am not totally sure.
 
I have set OPTION_REG.7 = 1 and it dosn't help, the port still stays high once I've had an input on it.

Turns out that it's my delay rutine

Code:
void delay10( char n) //delay10( 100);  /* 1 second */
/*
  Delays a multiple of 10 milliseconds using the TMR0 timer
  Clock : 4 MHz   => period T = 0.25 microseconds
  1 IS = 1 Instruction Cycle = 1 microsecond
  error: 0.16 percent
*/
{
    char i;

    OPTION = 7;
    do  {
        clrwdt();  // only if watchdog enabled
        i = TMR0 + 39; /* 256 microsec * 39 = 10 ms */
        while ( i != TMR0)
            ;
    } while ( --n > 0);
}

If I disable a call to this function that is being called from my Running_Led() function it all works, except for the fact that there's no delay in the lights being turned off and on, so they look like they are all turned on at the same time, when in fact they are turning on and off faster than I can see it.

I think it has something to do with the OPTION = 7, but I am not totally sure.

OPTION is the OPTION_REG register; that IS your problem.

Setting OPTION_REG to 7 means setting it to 0b00000111, which sets OPTION_REG.7 to 0, thus enabling the weak pull-ups.

Mike
 
Last edited:
Would it be possible to add OPTION_REG.7 = 1 to the code after the OPTION = 7 or change OPTION = 7 to OPTION = 135 which should be 0b10000111?
 
Would it be possible to add OPTION_REG.7 = 1 to the code after the OPTION = 7 or change OPTION = 7 to OPTION = 135 which should be 0b10000111?

Certainly. The best thing to do would be to use

Code:
OPTION = 0b10000111;

That will do the right thing and documents what you are doing much better than OPTION = 135;

I would also look through the source code to see if there are any other places where you modify OPTION.

Mike
 
Nice, thanks for the help.

Works perfect now that I set it to 0b10000111 in my delay rutine.

Thanks again all :)
 
Status
Not open for further replies.

Latest threads

Back
Top