CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

output_high() DOES NOT STAY HIGH
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

output_high() DOES NOT STAY HIGH
PostPosted: Wed Aug 22, 2012 12:51 pm     Reply with quote

Hi All,

Hopefully a simple answer. If during pre-processor directives and main I had:

Code:
#define latch  PIN_B7

void main ()
output_high(latch); 

go and do program 1 ();
go and do program 2 ();
.....
go and do program x ();


When I enter different programs - pin_B7 does not stay high - it resets to low. I presume this in normal??

I thought that it would stay high unitil i pulled it low with:
Code:

output_low(latch); 


but this is not happening.

Can anyone confirm that this is actually what is supposed to happen and more importantly a way around it - so that a pin stays high regardless, untill it is pulled low by a command.

Thanks
Carl
Ttelmah



Joined: 11 Mar 2010
Posts: 19348

View user's profile Send private message

PostPosted: Wed Aug 22, 2012 1:04 pm     Reply with quote

You may well be suffering from the PIC RMW problem.
When another pin in the same port is written, the hardware performs the following operations:

1) read the levels on the other pins.
2) change the new pin, and write the levels back.

Problem comes if a pin is not actually going 'high'. If (for instance), a pin is connected to an LED without a current limiting resistor, though it goes 'up', it does not reach the voltage the port pin considers to be 'high', so when the 'read levels' operation is done, it is wrongly read as low.....

This is called the 'read modify write' problem. A search here will find a lot about it (and at Microchip).

There are a number of fixes, but the first one is to ensure the pin is not overloaded, since this will cause overheating, and possible damage to the chip....

Best Wishes
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Wed Aug 22, 2012 1:28 pm     Reply with quote

Thanks Ttelmah,

I think this is whats happening.
I have just read briefly now and it seems to indicate that if when another pin is changed on the same port as a pin that has been 'set' - if that 'set' pin is now under the switching thresholds for TTL (because of the load it is connected to) then it could possibly reset the pin.

I have a few pins that need to stay high for different functions - so it might happen to a few of them. The function that initially caused this question was for a relay - and when 'active' the voltage reads 3.6V.
So this has probably been read by the port and then reset it to 0V.

Not good. I will read further. One brief thing I read was that writing to the latch register instead of the port is a good plan.

Thanks
Carl
Ttelmah



Joined: 11 Mar 2010
Posts: 19348

View user's profile Send private message

PostPosted: Wed Aug 22, 2012 1:34 pm     Reply with quote

Yes there are several possible fixes like writing to the latch register (if this is a PIC18 - on PIC16's you can't do this).
It also depends on the input threshold for the pin (TTL for many pins, but Schmitt levels for some). If it is happening at 3.6v, then this is probably the case for this pin (depends on the PIC). Reducing the drive though is the 'better' solution. Smile

Best Wishes
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Fri Aug 24, 2012 7:54 am     Reply with quote

Hi Ttelmah,

I think I am going to have to go down the write and read to the latch registors. Could you advise if this is a good way to do do it:
Code:
#byte PORTD_DIRECT = getenv("SFR:PORTD")
#bit portd0 = PORTD_DIRECT.0
#bit portd1 = PORTD_DIRECT.1
#bit portd2 = PORTD_DIRECT.2
#bit portd3 = PORTD_DIRECT.3
#bit portd4 = PORTD_DIRECT.4
#bit portd5 = PORTD_DIRECT.5
#bit portd6 = PORTD_DIRECT.6
#bit portd7 = PORTD_DIRECT.7


And then I can just write or read to the the individual latch bits like:
Code:

void main()
{
int8 value;

value = portd5;  // Read the latch register for Port D pin 5
portd6 = 1;  // write '1' to the latch register for Port D pin 6

while(1);
}

Is this the best way of doing it?
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Fri Aug 24, 2012 9:44 am     Reply with quote

Tried this as well but no change:
Code:
#byte LATA_DIRECT = getenv("SFR:LATA")
#byte LATB_DIRECT = getenv("SFR:LATB")
#byte LATC_DIRECT = getenv("SFR:LATC")
#byte LATD_DIRECT = getenv("SFR:LATC")
#byte LATE_DIRECT = getenv("SFR:LATE")
#bit portd0 = LATD_DIRECT.0
#bit portd1 = LATD_DIRECT.1
#bit portd2 = LATD_DIRECT.2
#bit portd3 = LATD_DIRECT.3
#bit portd4 = LATD_DIRECT.4
#bit portd5 = LATD_DIRECT.5
#bit portd6 = LATD_DIRECT.6
#bit portd7 = LATD_DIRECT.7
#bit porta0 = LATA_DIRECT.0
#bit porta1 = LATA_DIRECT.1
#bit porta2 = LATA_DIRECT.2
#bit porta3 = LATA_DIRECT.3
#bit porta4 = LATA_DIRECT.4
#bit porta5 = LATA_DIRECT.5
#bit porta6 = LATA_DIRECT.6
#bit porta7 = LATA_DIRECT.7
#bit portb0 = LATB_DIRECT.0
#bit portb1 = LATB_DIRECT.1
#bit portb2 = LATB_DIRECT.2
#bit portb3 = LATB_DIRECT.3
#bit portb4 = LATB_DIRECT.4
#bit portb5 = LATB_DIRECT.5
#bit portb6 = LATB_DIRECT.6
#bit portb7 = LATB_DIRECT.7
#bit portc0 = LATC_DIRECT.0
#bit portc1 = LATC_DIRECT.1
#bit portc2 = LATC_DIRECT.2
#bit portc3 = LATC_DIRECT.3
#bit portc4 = LATC_DIRECT.4
#bit portc5 = LATC_DIRECT.5
#bit portc6 = LATC_DIRECT.6
#bit portc7 = LATC_DIRECT.7
#bit porte0 = LATE_DIRECT.0
#bit porte1 = LATE_DIRECT.1
#bit porte2 = LATE_DIRECT.2
#bit porte3 = LATE_DIRECT.3
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Aug 24, 2012 12:01 pm     Reply with quote

What's your PIC and your compiler version ?
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Fri Aug 24, 2012 1:20 pm     Reply with quote

HI PCM,
CCS Version: 4.038.
PIC is 4550.

I know that 4.038 is not good, and may be the cause for numerous errors, but I also dont know if I am carrying out the function correctly either.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Aug 24, 2012 1:26 pm     Reply with quote

Quote:
Tried this as well but no change:

#byte LATA_DIRECT = getenv("SFR:LATA")
#byte LATB_DIRECT = getenv("SFR:LATB")
#byte LATC_DIRECT = getenv("SFR:LATC")
#byte LATD_DIRECT = getenv("SFR:LATC")
#byte LATE_DIRECT = getenv("SFR:LATE")

See the typo shown in bold above.



Quote:
value = portd5; // Read the latch register for Port D pin 5

Not sure why you want to read the latch. It holds what you wrote to it.
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Fri Aug 24, 2012 1:37 pm     Reply with quote

Deary me
Been at it too long!!!

Thanks
I will give it a go tomorrow and see if it clears things up.

I am having problems with the rmw issue - and therefore need to ensure that I write to the Latch's - because writing to the ports with output_high() is not working - keeps resetting.

I understand what Ttelmah has said about reducing the power consumption of the load, but tried without success at the moment. It is not a capacitive issue either - Its voltage being dropped across a load (relay in this particular case). Other peripherals will also probably do the same thing (I try to protect as much as possible - resistors, drivers etc).

So I need a sure-fire way of writing and reading to the pins which won't reset due to the rmw issue. Is the way I suggest correct??
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Aug 24, 2012 2:02 pm     Reply with quote

Make a test program and compile it and look at the .LST file.
It did that with vs. 4.038 and I got this:
Code:

.................... output_high(LATCH);   
001C:  BCF    TRISD.6
001E:  BSF    LATD.LATD6
....................   
.................... output_low(LATCH);   
0020:  BCF    TRISD.6
0022:  BCF    LATD.LATD6

The compiler is writing to the latch register. So therefore, the problem
is not a RMW issue. It's likely related to your load. Don't drive high
current loads directly with a PIC pin. Use a relay driver chip, such as
ULN2003A. Or any relay driver.

Test program:
Code:

#include <18F4550.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4M)

#define LATCH  PIN_D6

//==========================
void main()
{

output_high(LATCH); 
 
output_low(LATCH); 

while(1);
}



Thread on relay drivers:
http://www.ccsinfo.com/forum/viewtopic.php?t=34119

There could also be power supply track layout issues, or other issues:
http://www.ccsinfo.com/forum/viewtopic.php?t=34352
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Fri Aug 24, 2012 2:15 pm     Reply with quote

for the same program you wrote I would get the same as you have shown - and the pin would go high and low.

It only occurs when other programs are accessed - which rmw to the port, and then the pin does not stay high.

It is such a good learning curve though - now I know that for many output pin fucntions (connected to different loads) - to absolutely ensure that they are protected (driver, resistor etc).

Thanks anyway
Carl
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Aug 25, 2012 5:16 am     Reply with quote

I'm getting confused now.

My understanding is what Ttelmah wrote here
Quote:
You may well be suffering from the PIC RMW problem.
When another pin in the same port is written, the hardware performs the following operations:

1) read the levels on the other pins.
2) change the new pin, and write the levels back.

Problem comes if a pin is not actually going 'high'. If (for instance), a pin is connected to an LED without a current limiting resistor, though it goes 'up', it does not reach the voltage the port pin considers to be 'high', so when the 'read levels' operation is done, it is wrongly read as low.....

This is called the 'read modify write' problem. A search here will find a lot about it (and at Microchip).

There are a number of fixes, but the first one is to ensure the pin is not overloaded, since this will cause overheating, and possible damage to the chip....



The key point that I am trying to investigate is that is another pin is WRITTEN to on the same port - then the rwm problem exists. I am seeing this though when the port is READ not WRITTEN TO.

So does the same occur when the port ir read??
something like below:
Code:


void main (){

output_high (relay);     // relay is pin d_4 and reads 3.6V when high.
}

while (true){

rval=input_d();
}


when I read input_d, the latch goes low.
so does the rwm problem also exist when you READ to the port (or pin?) and not just WRITE to the port (or pin?).

Also looking at the rwm issue, everywhere states to WRITE to the LATx register and READ from the ports. OK I first tried to just write to the LAT registers and toggle a pin as below using portc - but it did nothing:
Code:
#byte LATA_DIRECT = getenv("SFR:LATA")
#byte LATB_DIRECT = getenv("SFR:LATB")
#byte LATC_DIRECT = getenv("SFR:LATC")
#byte LATD_DIRECT = getenv("SFR:LATD")
#byte LATE_DIRECT = getenv("SFR:LATE")
#bit portd0 = LATD_DIRECT.0
#bit portd1 = LATD_DIRECT.1
#bit portd2 = LATD_DIRECT.2
#bit portd3 = LATD_DIRECT.3
#bit portd4 = LATD_DIRECT.4
#bit portd5 = LATD_DIRECT.5
#bit portd6 = LATD_DIRECT.6
#bit portd7 = LATD_DIRECT.7
#bit porta0 = LATA_DIRECT.0
#bit porta1 = LATA_DIRECT.1
#bit porta2 = LATA_DIRECT.2
#bit porta3 = LATA_DIRECT.3
#bit porta4 = LATA_DIRECT.4
#bit porta5 = LATA_DIRECT.5
#bit porta6 = LATA_DIRECT.6
#bit porta7 = LATA_DIRECT.7
#bit portb0 = LATB_DIRECT.0
#bit portb1 = LATB_DIRECT.1
#bit portb2 = LATB_DIRECT.2
#bit portb3 = LATB_DIRECT.3
#bit portb4 = LATB_DIRECT.4
#bit portb5 = LATB_DIRECT.5
#bit portb6 = LATB_DIRECT.6
#bit portb7 = LATB_DIRECT.7
#bit portc0 = LATC_DIRECT.0
#bit portc1 = LATC_DIRECT.1
#bit portc2 = LATC_DIRECT.2
#bit portc3 = LATC_DIRECT.3
#bit portc4 = LATC_DIRECT.4
#bit portc5 = LATC_DIRECT.5
#bit portc6 = LATC_DIRECT.6
#bit portc7 = LATC_DIRECT.7
#bit porte0 = LATE_DIRECT.0
#bit porte1 = LATE_DIRECT.1
#bit porte2 = LATE_DIRECT.2
#bit porte3 = LATE_DIRECT.3

void main()

              
   
while(true) { 

portc0 = 1;                      
delay_ms(5000);
portc0 = 0;                                           
delay_ms(5000); 
}
}


and then i wrote to the port first and then it worked
Code:

void main()


output_high(relay);                
   
while(true) { 

portc0 = 1;                      
delay_ms(5000);
portc0 = 0;                                           
delay_ms(5000); 
}
}


I just dont understand how this is supposed to work[/code]
jeremiah



Joined: 20 Jul 2010
Posts: 1323

View user's profile Send private message

PostPosted: Sat Aug 25, 2012 6:48 am     Reply with quote

When you write directly, you need to set the tris direction. When you use output_high() it does that for you (see the LST file listing posted earlier). Writing to the latch of a port set to read only does nothing.
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Aug 25, 2012 7:10 am     Reply with quote

Thanks Jeremiah,

So you cannot use standard_io if you want to write to the port directly?
As standard_io sets the tris automatically.

so every port would have to be set to fast_io (and then the tris can be set) if I intended to write to the latch directly?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group