![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Sam_40
Joined: 07 Jan 2015 Posts: 127
|
TRIS register? [SOLVED] |
Posted: Thu Nov 19, 2015 8:25 pm |
|
|
My understanding is the TRIS register (Tristate) controls the I/O direction.By default the compiler automatically does this for me if I do not use it. The manual states "These functions allow the I/O port direction (TRI-State) registers to be set. This must be used with FAST_IO and when I/O ports are accessed as memory such as when a # BYTE directive is used to access an I/O port. Using the default standard I/O the built in function set the I/O direction automatically."
To set one of the eight bits to 0 mean the pin is output and set it to 1 mean the pin is input. if all the 8 pins on port A needed to be inputs then set_tris_A(0XFF);
To set the TRIS register for an individual pin then:
output_float(PIN_A1); sets the TRIS bit on pin A1, to input.
output_drive(PIN_A1); sets the TRIS bit on pin A1 to output.
Now I have a few questions please help me understand them:
1- I read several posts on the forum and as ccs manual, where the set_tris_X(); is used you must use the #use fast_io(X) before using set_tris_X();. However I also read several posts where the set_tris_X();was used without the #use fast_io(X)?
2- For example; If I am using a crystal or oscillator on pins C0 and C1 as they are the OSC or Timer1 IOs how can I set the set_tris_C(); for C2-C7 without affecting C0 and C1? In this situation, can I use the set_tris_C(); or the output_float() and the output_drive() for C2-C7?
3- If I am low on pin count and I want to use a single pin as input and output how to do that?
4- If in my code, I use the set_tris_A(0XF0); would that affect for example output_high(PIN_A0); and or if ( input(PIN_A4)) even if I set bit 0 to 0 and bit 4 to input in the TRISA register?
Thanks in advance,
Last edited by Sam_40 on Fri Nov 20, 2015 8:48 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Fri Nov 20, 2015 2:22 am |
|
|
A lot of people post code, that has been transferred from other compilers, where you must set TRIS. So they copy the TRIS setup line, even if it is actually just a wasted line.
Hence TRIS settings without using fast_io.
It is quite common to see code where TRIS is set, and then in the very next line an I/O operation is done that overrides this setting.....
"1-"
Modes are:
1) Standard I/O. The default. With this, the TRIS will be set for every operation you perform on the port. Wastes a little code space, is fractionally slower, but _ensures_ that TRIS is set correctly for each operation you do. So you can just output on a pin, and then input on the pin, and TRIS will be set to output for the first, then to input for the second "3-". Makes pretty sure that all the other TRIS bits on a port are correctly set for things like serial, SPI etc., without you having to sit down with the data sheet and work them all out. 99.9% of code can use this, and it is commonly 'pushed', where people are obviously not reading the data sheet to check the TRIS settings for every peripheral. Particularly useful, since some TRIS settings vary between chips for the same peripheral. On a lot of older chips for example, you have to set the TX pin as an output, and the RX pin as input for RS232. Many newer chips instead require you to set both as inputs. Similar little differences exist for most peripherals.....
2) Fixed I/O. With this TRIS is still set when every operation is performed, but the setting is 'fixed' at the values you program. The #use line has to carry a list of the directions for the pins. Very rare. However can be usefully used where (for instance), you want to read the whole of port B, as a single 'byte' read, but leave perhaps B0, still set as an output. Generally though, since this has no speed advantage over standard I/O, and still leaves you having to control the TRIS, this is pretty much never used.
3) Fast I/O. With this the compiler does not generate any TRIS operations for you. Instead you have to do them all yourself. TRIS will only be changed for set_tris, output_float, and output_drive commands, not for any actual I/O operation (output, input etc.).
Now it is possible to directly access the port register, without triggering the 'automatic TRIS' operations, by using #byte as you say. You need to be careful though. For instance on PIC18's, the actual 'port' (PORTB for example), is one register, but the output 'latch' (which actually sets which pins are to drive which way), is LATB. Now if you want to 'read' from the port, you should look at PORTB. However if you want to drive a pin, you should drive LATB. The reason is a classic PIC problem, known as 'RMW' (read, modify, write). Suppose you have a load on a pin on the port, which has a Schmitt input buffer. Now this pin requires the signal to go up to 0.8*Vdd, before it is seen as '1'. Now the load you have is quite heavy, so when the pin is driven 'high', it only actually gets up to 0.7*Vdd. Alternatively there could be a lot of capacitance on a pin, so if changed 'recently', it is slowly climbing 0.1Vdd, 0.2Vdd etc.. Now you access 'PORTB', and turn on another pin. When this instruction is done, the _hardware_ reads the levels on all the other pins, changes the pin you are altering, and writes the result back to PORTB (read, modify, write). Problem is that the pins which have outputs below the Vih of the port are seen as being 'low', so are turned off!.... If instead you access 'LATB' this stores the actual drives being sent to the pins, so you can set your new pin, and the others remain correctly set. However reading this, only reads what is being sent 'out' the pins, not what is actually on them.
Hence the output, and input instructions from CCS automatically 'switch registers' on PIC's that support this (the oldest PIC's did not have separate port and lat registers, so RMW was a perpetual problem. The PIC 18 then added the separate registers, and newer PIC16's also have them).
Now next comment. Some things ignore TRIS. For instance, generally oscillator pins, are not affected by TRIS. If you look at the I/O summary in the data sheet, you will see things like (PORT A on a PIC18F2420), for RA6/RA7 which is commonly the master oscillator, the 'OSC1' and 'OSC2' lines, have 'x' in the TRIS column. If the pins are set as an oscillator, the TRIS bits are ignored. In this case it is important, since otherwise an incorrect TRIS setting could stop the CPU!... Similarly on the same chip port C0, and C1 (Timer 1 oscillator pins), also have the 'x'. The comment reads:
"Timer1 oscillator; enabled when Timer1 oscillator enabled.
Disables digital I/O."
Critical line 'Disables digital I/O'
"2-"
So using any I/O mode you can change pin direction, by just updating the TRIS. "3-".
"4-"
You can set the TRIS any way you want at any time, in any I/O mode. However in 'standard' mode, this setting may be overridden at the very next I/O operation.
Standard mode:
Code: |
set_tris_A(0XF0);
output_high(PIN_A0); //Tris would remain unchanged. bit 0 = 0
output_high(PIN_A4); //Tris would now be 0xE0. bit 4 = 0
output_b(0); //Tris would now be 0 - all pins driving
|
Fast mode:
Code: |
set_tris_A(0XF0);
output_high(PIN_A0);
output_high(PIN_A4);
output_b(0); |
Tris just remains 0xF0 all the way through. The output_high(PIN_A4) instruction will not drive the pin high (but the LAT _will_ be set high), and output_b, will only drive the bottom four pins (but the whole LAT register will be cleared).
Now if you then execute:
Code: |
output_drive(PIN_B0); |
Pin B0 will now drive _low_ (since 'LATB' was cleared by the 'output_b(0)' instruction).
This last, is how you can generate 'open collector' drives with a PIC, where the pin is either driven low, or allowed to float. You just program the corresponding LAT bit 'low', and then use output_drive when you want the pin pulled low, or output_float, when you want to release the pin and let iot be drawn high by an external pull-up. This is also a good way of doing bi-directional I/O (this is how I2C does it), by having a pin that has a pull-up resistor, then is pulled 'low' by more than one device (on I2C, the 'slave' pulls the clock low when it wants to pause a transaction, or the data line low when it is sending data). The problem with any form of bi-directional I/O, is _ensuring_ that both drivers do not try to drive the pin in opposite directions at once. Having each only able to drive the pin 'one way', ensures that this will not cause nasty currents to flow.....
Hope this helps you to get your head round the registers and abilities. |
|
![](templates/subSilver/images/spacer.gif) |
Sam_40
Joined: 07 Jan 2015 Posts: 127
|
|
Posted: Fri Nov 20, 2015 8:47 am |
|
|
Ttelmah,
Thanks a lot for the very detailed information. I appreciate your time and help.
Best regards, |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Fri Nov 20, 2015 9:04 am |
|
|
Have fun playing with the I/O... ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
camerart
Joined: 24 Nov 2019 Posts: 7
|
|
Posted: Sun Nov 24, 2019 11:35 am |
|
|
Hi T,
I use a different compiler, not CCS, but I hope you can shed light on a question for me, please.
Using an 18F4620 PIC and an AK8963C compass chip (Iphone 5)
I'm getting an intermittent fault, where the COMP MISO voltage drops to 1/2 @ 1.65V instead of the required 3.3v for the PIC MISO.
I have tried pull up resistors, with little effect.
I have tried level shifter, which is showing 90% positive results.
My question is:
I set the TRIS = %10010000 MISO
And it was suggested to me, that perhaps the PIC TRIS MISO set as IN, sometimes switches momentarily to OUT, making the incoming signal squash down below the READable voltage.
Do you think this is possible?
Cheers, Camerart. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Sun Nov 24, 2019 12:41 pm |
|
|
You do realise your chip is not rated to run at 3.3v?. 4.2v minimum for
the 18F4620. To run at 3.3v requires the LF chip. I'd not be surprised if
a PIC running below it's rated voltage might do all sorts of odd things.
No, TRIS does not spike. If it did and it was driving, the signal would go
low, not to half voltage. The output drive capabilities of the PIC are
so much greater than those of the AK chip. TRIS is used on far too many
projects for there to be a problem with this.
The voltage out in SPI mode is dependant on the voltage on the VID
pin. Is this dropping?.
Other possibility is the chip is switching to I2C mode. The line would
then be undriven, and could easily float to half voltage. However you
say that pull-ups don't change this much, so it does seem to be 'driven'. |
|
![](templates/subSilver/images/spacer.gif) |
camerart
Joined: 24 Nov 2019 Posts: 7
|
|
Posted: Mon Nov 25, 2019 2:49 am |
|
|
Ttelmah wrote: | You do realise your chip is not rated to run at 3.3v?. 4.2v minimum for
the 18F4620. To run at 3.3v requires the LF chip. I'd not be surprised if
a PIC running below it's rated voltage might do all sorts of odd things.
No, TRIS does not spike. If it did and it was driving, the signal would go
low, not to half voltage. The output drive capabilities of the PIC are
so much greater than those of the AK chip. TRIS is used on far too many
projects for there to be a problem with this.
The voltage out in SPI mode is dependant on the voltage on the VID
pin. Is this dropping?.
Other possibility is the chip is switching to I2C mode. The line would
then be undriven, and could easily float to half voltage. However you
say that pull-ups don't change this much, so it does seem to be 'driven'. |
Hi T,
Thanks for the clarification.
To clarify from my end:
It is the MISO (from the Compass) that is low voltage, not from the PIC.
The VID voltage is not dropping
Of course, I had forgotten about the LF version, since I've been working on this problem for months. I'm also forgetting that this must have been why I tried a level shifter.
I have been maybe erroneously, running the 18F4620 PICs at 3.3V for years, and they have been working ok, but now I see that at any time the problem here could materialise. Having said that I'll carry on with them, while using level shifters, on the MISO track, until I make new final PCBs, when I'll use the LF version.
C.
Last edited by camerart on Mon Nov 25, 2019 6:34 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Mon Nov 25, 2019 3:34 am |
|
|
If your PIC is running at 5v, then you _need_ a level shifter.
The SPI input of the PIC requires the signal to go to 4v to be seen as a
'1'. 3.3v is not enough. Also the PIC output will be overdriving the slave
device input.
No wonder things don't work right.... |
|
![](templates/subSilver/images/spacer.gif) |
camerart
Joined: 24 Nov 2019 Posts: 7
|
|
Posted: Mon Nov 25, 2019 6:37 am |
|
|
Ttelmah wrote: | If your PIC is running at 5v, then you _need_ a level shifter.
The SPI input of the PIC requires the signal to go to 4v to be seen as a
'1'. 3.3v is not enough. Also the PIC output will be overdriving the slave
device input.
No wonder things don't work right.... |
Hi T,
No mention of 5V, the PIC has been running at 3.3V for years. The AK8963C is also 3.3V, but as you said the 18F4620 should not really be used for 3.3V.
I've ordered some 18LF4620 PICs.
Thanks,
C. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9170 Location: Greensville,Ontario
|
|
Posted: Mon Nov 25, 2019 8:03 am |
|
|
You've been extremely LUCKY to have that PIC run perfectly! I have to assume it's indoors in man likeable temperatures and humidiy. I also assume you only have 1 and not 100 of these working ? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Mon Nov 25, 2019 9:04 am |
|
|
Also worth saying that we had another poster a while back doing the same
thing. He was having a really 'odd' failure, and it turned out to be just a single
bit in a register not holding the value correctly. When using the chip this
far outside it's spec, 'inexplicable' failures become common.... |
|
![](templates/subSilver/images/spacer.gif) |
camerart
Joined: 24 Nov 2019 Posts: 7
|
|
Posted: Mon Nov 25, 2019 11:04 am |
|
|
Hi T and T2,
Let's hope the new PICs work ok, I'm sure they will.
Thanks, for the clues that helped me buy the LF version.
Cheers, Camerart. |
|
![](templates/subSilver/images/spacer.gif) |
camerart
Joined: 24 Nov 2019 Posts: 7
|
|
Posted: Sun Dec 08, 2019 9:46 am |
|
|
Hi,
Changed the PIC to 18LF4620, but still having issues.
I have a 1K pull up resistor on the MISO track, then cut the track at the compass end and put a 1K resistor across the cut. Checking the voltage at the Compass side shows 3.3v and if connected to the PIC side shows approx 2.5V quickly snapping back to '0'.
The MISO is set to an input, but the results look like it's set to output.
????
C |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Sun Dec 08, 2019 9:56 am |
|
|
Are you absolutely sure you are connecting to the right pin?.
MISO, should be going to pin 23 on the 4620. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Dec 08, 2019 9:58 am |
|
|
camerart wrote: | Hi T,
I use a different compiler, not CCS.
|
|
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|