|
|
View previous topic :: View next topic |
Author |
Message |
stinky
Joined: 05 Mar 2012 Posts: 99 Location: Central Illinois
|
Power On Reset, Poorly Written Code, Latches, and RA4 |
Posted: Tue Oct 23, 2012 1:31 pm |
|
|
16f684, CCS 4.132
I understand that I need to specify the pin state that I desire or make peace with the wrath that is the PIC.
What I don't understand is why that is.
I have some code, and periodically when the PIC powers up and starts running I will get a high output on RA4. In my application RA4 is unused and I don't want it to be high. However the original author of the code didn't specifically write output_low(PIN_A4); in the code.
I did some leafing through the datasheet and I haven't found an answer that satisfies me. The pin is specified as an output. The analog pins are correctly set. What circumstances would allow this pin to be set high on powerup even though it is not explicitly set either way?
I believe that simply writing OUTPUT_A(0x00); OUTPUT_C(0x00); at the top of my code will alleviate these symptoms, but I'm too curious to not seek answers from you more experienced folks.
Thanks
example code:
Code: |
#include <16F684.h>
#device adc=8
#FUSES IESO
#FUSES NOFCMEN
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPUT //Power Up Timer
#FUSES NOMCLR //Master Clear Internal
#FUSES BROWNOUT //No brownout reset
#FUSES NOCPD //No EE protection
#FUSES NOPROTECT //Code not protected from reading
#use delay(clock=8000000)
void main()
{
//******** INITS ***************
output_low(PIN_C0);
output_low(PIN_C1);
output_low(PIN_C2);
output_low(PIN_C0);
setup_adc(ADC_CLOCK_INTERNAL);
SETUP_ADC_PORTS(sAN2 | sAN7 | VSS_VDD);
setup_oscillator(OSC_8MHZ);
port_A_pullups(0x03);
set_tris_a(0x2F);
set_tris_c(0x18);
setup_ccp1(CCP_OFF);
#ASM //setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
movlw 0x01
movwf 0x10
#ENDASM
setup_timer_1(T1_INTERNAL);
set_timer1(63869);
ext_int_edge(L_TO_H);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
output_low(PIN_C1);
output_low(PIN_C2);
while(TRUE)
{
;
} // end of WHILE
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19490
|
|
Posted: Tue Oct 23, 2012 2:16 pm |
|
|
Random.
The contents of the output data latches are specified in the data sheet as 'u' - undefined. They will be sort of random, depending on all sorts of things - the speed the power rail rises, temperature, charge left in the cells from previous operations, the state of the tide, etc. etc....
When you set the pin to output, this is what appears on the pin.
Best Wises |
|
|
stinky
Joined: 05 Mar 2012 Posts: 99 Location: Central Illinois
|
|
Posted: Tue Oct 23, 2012 2:38 pm |
|
|
Thanks Ttelmah,
As I read more I wonder about the ccs function output_high(x)
Do we know if this is writing to the PORT register or the LATCH register? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19490
|
|
Posted: Tue Oct 23, 2012 2:41 pm |
|
|
On the 16 chips, the output latch is the port register. Output_high, clears the TRIS bit, and sets the latch bit.
Best Wishes |
|
|
stinky
Joined: 05 Mar 2012 Posts: 99 Location: Central Illinois
|
|
Posted: Tue Oct 23, 2012 2:52 pm |
|
|
I neglected to add this in my example code but I have #USE FAST_IO in my code.
My understanding is that means that output_high does NOT clear the TRIS bit. Does that still mean that it writes directly to the port/latch? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19490
|
|
Posted: Wed Oct 24, 2012 2:42 am |
|
|
I think you need to get your head round what a 'port' is.
On the PIC 16, there is an output latch register.
When you 'write' in any way to the 'port address', you write to this register.
Every bit in this register, which has the corresponding bit in TRIS set to zero, connects to the output driver hardware.
When you 'read' from the port address, you read the logic level on the external pins of the PIC, whether they are driven by the latch or not.
Now, this differs from the PIC 18.
Here the output latch register is on a separate address, and can be directly read as well as written.
On the PIC 16, when you update any bit of the output register, the chip performs what is called a 'read modify write' cycle (RMW). What it reads is the actual port pins, not the latch.
So if you set bit 4 of the 'port', what happens is that the logic levels on all eight pins are read. Then bit 4 is set, and the resulting byte is written back to the output latch.
Where this causes problems, is if (for instance) you are using a port with Schmitt input levels (so a logic '1' required the pin to be above 4v, on a 5v system), and you have a pin driving something like an LED. Say bit 5.
Now you turn this on, and the pin goes up to just over 3v say because of the LED load. Then you turn on bit 4. What happens is that the chip reads the pins, and looks at bit 5, and says 'this is below 4v, so the pin is low'. Then turns on bit 4, and turns off bit 5 (since it read as low). This is known as the 'RMW' problem of the PIC.
On the PIC 18, since the output latch is separate, you can instead just turn on the bit in the latch, and this won't happen.
All output writes on the PIC16, write to the output latch, there is nowhere else to go. However the key is that this is not what you see if you read the same address, which returns the actual pin state instead, which can differ.
With standard_io, or fixed_io, the TRIS is also updated. With fast_io, it isn't.
The 'port', is actually two sets of registers. The latch when you write, and direct readings from the input gates, when you read. Look at the data sheet, which shows this. In fact there are usually several other output latches involved (from peripherals), and on most chips the inputs are also latched (usually on cycle Q3), so they can't change during a 'read'.
Now I'm not really sure what your problem is understanding what is happening. The value on the output latch is _undefined_. It is not truly 'random', because it will be affected by physical things that have happened to the chip in the past, and spurious differences inside the chip. So you may well find that on two different chips, one wakes up with A4 high 1% of the time, while another does it 90% of the time. This value is sitting there when the chip boots, and will stay as it is, until you change it.
Remember the PIC pins wake up as _inputs_. They are undriven. Your TRIS line, connects specified pins to the output latch, which contains this 'biased semi random number'. Hence sometimes the pin will go high. Key is always to set the latch to the known value _you_ want. How you do this, is entirely up to you. Setting/clearing the individual bits or the byte as a whole. However if you do it bit by bit, you can potentially run into the RMW problems. If instead you just send a byte to the whole port, you avoid this.
Best Wishes |
|
|
stinky
Joined: 05 Mar 2012 Posts: 99 Location: Central Illinois
|
|
Posted: Thu Oct 25, 2012 7:31 am |
|
|
wow. thank you.
I promise to let you go back to work but your post got me curious about another scenario.
When I'm writing to bit 4 of this port the micro reads the logic level of the actual pins. Then it writes that entire byte, with whatever instruction I added to bit 4, to the output latch. Then at the micro's leisure the latch is reproduced on the actual pins.
If the pin connected to bit 2 was being used to measure an analog voltage at this moment and the voltage was within this hysteresis range, the READ would say that pin 2 is ZERO and it would write a zero to the corresponding latch bit. If I were to change that pin to an output later in code, and I didn't specify what state I wanted it to be in, it should be a zero from the previous RMW cycle. Yes?
Because that just made serious sense in my brain. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19490
|
|
Posted: Thu Oct 25, 2012 8:41 am |
|
|
A good point.
In fact key thing is that the TTL inputs, don't like analog inputs connected. They can draw excessive power if in the 'transition region' (between '0' and '1'), so don't want to be connected to the inputs when they are used as analog inputs.
If you look at the data sheet, the input buffer is preceded by an and switch, fed with /ANSEL on it's other input. So when the pin is setup for analog, the input buffer is actually disconnected from the pin, and during the RMW cycle, the input will read as '0', and this is what gets put into the output latch.
So it would be a zero, but it'd be zero, even if the signal on the pin was high during the update cycle, if the pin was set as analog.
Best Wishes |
|
|
|
|
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
|