Cypress Perform

Home > Design Support > Cypress Developer CommunityTM > Cypress Forums > PSoC® 1 > Reading current status of output values on a port on a CY8C9560A

Bookmark and Share
Cypress Developer CommunityTM
Forums | Videos | Blogs | Training | Rewards Program | Community Components



Reading current status of output values on a port on a CY8C9560A
Moderator:
ARVI

Post Reply
Follow this topic



Reading current status of output values on a port on a CY8C9560A

ianlee74 posted on 16 May 2012 11:02 PM PST
Senior Member
11 Forum Posts

Suppose all the pins on port 7 are configured for output and some are high & some are low.  What are the correct commands to send to read the current state of the port?  Everything I've tried returns 0xFF.  Thanks.




Re: Reading current status of output values on a port on a CY8C9560A

Bob Marlowe posted on 16 May 2012 06:55 AM PST
Top Contributor
1768 Forum Posts

Datasheet says:

Input Port Registers (00h - 07h)

 

These registers represent actual logical levels on the pins and

are used for I/O port reading operations. They are read only.

So a read from register 0x07 will present you with the actual states of the pins, no need to use the Port-Select-Register first.   Bob



Re: Reading current status of output values on a port on a CY8C9560A

ianlee74 posted on 28 May 2012 12:21 AM PST
Senior Member
11 Forum Posts

 Bob,  thanks.  That one was easy.  Now I'm having a stranger problem.  I can set the pin value and read it back and it comes back as I expect.  However, no current seems to be delivered to the pin (most of the time).  I have LEDs set on all the pins on port 7 to test this and on rare cases it works but most of the time the LEDs stay low although reading the pin values through the register says they are high.  Any ideas what's going on here?

My high-level test code is simply this...

 

const byte PORT = 7;

io60p16.SetPortMode(PORT, PORT_DRIVEMODE.RES_PULLDOWN);

io60p16.SetPortDirection(PORT, 0xff);

byte v = io60p16.GetPortOutput(PORT);

if (v == 0) v = 0xff;

else v = (byte)(v >> 1);              // cycle through the pins...

io60p16.SetPortOutput(PORT, 0x00);

io60p16.SetPortOutput(PORT, v);

Thread.Sleep(1000);

Debug.Print(io60p16.GetPortOutput(PORT).ToString());

Debug.Print(io60p16.GetPortInput(PORT).ToString());

 



Re: Reading current status of output values on a port on a CY8C9560A

Bob Marlowe posted on 28 May 2012 12:56 AM PST
Top Contributor
1768 Forum Posts

Ian, i cannot see that you really loop through the port-pins (no while(), no for())

There is a difference between the logic state of a pin and the value red back: independently of the logic state the output has, the value red is the actual voltage on the pin interpeted as a logic state.

Imagine your LED connected to light as active low (as in your example) when the output is driven low, due to the input resistance of the pin-circuit there will be a voltage (depending on LED-Type and resistor) that can be high enough to be interpreted as a logic "High" although the output is driven "Low". 

Give it a try with a DMM (NO SHORTS, PLEASE!).

An approach to come out of this io-trap is to use a "shadow-register" which buffers the wanted output-state and manipulations (bit-set and resets) and is written completely after alterations out to the port.

Give yourself a "Keyword Search" (upper right-hand corner of this window) for "read modify write".

Bob



Re: Reading current status of output values on a port on a CY8C9560A

zeta posted on 28 May 2012 08:26 AM PST
Top Contributor
174 Forum Posts

also make sure you are not drawing more current than the combined 40mA  maximum on PORT7



Re: Reading current status of output values on a port on a CY8C9560A

ianlee74 posted on 28 May 2012 09:30 AM PST
Senior Member
11 Forum Posts

Bob, I should have explained my setup better.  The code posted actually executes within a timer that get's fires every 2s.  I'm not concerned about previous values for this test.  I'm treating all pins on the port as output and the code should simply read the number of bits that are high then turn off the high bit so that the LEDs cycle from 8 pins high to 7, 6, 5...0, 8...  I'm familiar with the shadow register technique but I don't think that applies here.  Correct me if I'm wrong.

If I change the (C#) code slightly to this...

            var timer = new GT.Timer(2000);
            timer.Tick += timer1 =>
                              {
                                const byte PORT = 7;
                                io60p16.SetPortMode(PORT, PORT_DRIVEMODE.RES_PULLDOWN);

                                io60p16.SetPortDirection(PORT, 0xff);
                                byte v = io60p16.GetPortOutput(PORT);
                                if (v == 0) v = 0xff;
                                else v = (byte)(v >> 1);              // cycle through the pins...
                                io60p16.SetPortOutput(PORT, 0x00);
                                io60p16.SetPortOutput(PORT, v);
                                Thread.Sleep(500);
                                byte n = io60p16.GetPortOutput(PORT);
                                Debug.Print("Setting to: " + v + "\tReads as: " + n);
                              };
            timer.Start();    

Then I get this output...

Setting to: 255 Reads as: 255
Setting to: 127 Reads as: 127
Setting to: 127 Reads as: 127
Setting to: 63  Reads as: 63
Setting to: 31  Reads as: 31
Setting to: 15  Reads as: 15
Setting to: 127 Reads as: 255
Setting to: 63  Reads as: 63
Setting to: 31  Reads as: 31
Setting to: 15  Reads as: 15
Setting to: 7 Reads as: 7
Setting to: 3 Reads as: 3
Setting to: 1 Reads as: 1
Setting to: 0 Reads as: 0
Setting to: 255 Reads as: 255
Setting to: 127 Reads as: 127
Setting to: 63         Reads as: 255
Setting to: 127 Reads as: 127
Setting to: 63  Reads as: 63
Setting to: 31  Reads as: 31
Setting to: 15  Reads as: 255
Setting to: 7 Reads as: 7
Setting to: 3 Reads as: 3
Setting to: 1 Reads as: 1
Setting to: 0 Reads as: 255
Setting to: 255 Reads as: 255
Setting to: 127 Reads as: 127
Setting to: 63         Reads as: 63

You can see that in most cases the values being written are also be read back correctly.  However, none of my LEDs lighting.  I should also note that if I first enable all the pullup resistors for the port before doing the pulldown then they will all light up.  So, I know there's not a wiring problem.

Am I not fully understanding what you're telling me or is there really something weird going on here?

 



Re: Reading current status of output values on a port on a CY8C9560A

ianlee74 posted on 28 May 2012 09:38 AM PST
Senior Member
11 Forum Posts

"also make sure you are not drawing more current than the combined 40mA  maximum on PORT7"

Now that is useful information!  I don't recall seeing that in the datasheet.  I was making an assumption that it was 40mA per pin and not per port.  Each LED is ~20mA and since I'm lighting them all I've probably messed it up :(  What happens in this case?  Is the chip smart enough to just do nothing I need to get a new chip :(



Re: Reading current status of output values on a port on a CY8C9560A

Bob Marlowe posted on 28 May 2012 10:59 AM PST
Top Contributor
1768 Forum Posts

The first thing I notice is that you set the pin's mode within the timer-interrupt routine which you should do outsides in a hardware-initialization because there is no need to set that over and over again.

The second you're referring to a variable v and reading the port. Here exactly happens what I tried to explain in my last post. Imagine, you short a pin to GND. Although you wrote a "1" to the pin, You'll read back a "0" because it's tied to GND!!!

To overcome that:

Declare v as static byte v = 0xff;

Do NOT read back v but shift and set it as before

Set your port with v as usual.

By the way: To save a byte and some code, make your const byte PORT = 7    - to

#define PORT 7

Bob



Re: Reading current status of output values on a port on a CY8C9560A

ianlee74 posted on 28 May 2012 02:28 PM PST
Senior Member
11 Forum Posts

Bob, I appreciate the code criticism but this is by no means meant to be production code.  I am just trying to verify some very basic functionality of the chip which so far I'm unable to do.  You may recall helping me on another post a week or so back where I was able to blink and LED but was not able to read the value back.  Now, I can read the value back but the LED doesn't light.  So, let's simplify this a little so there's no distractions...  My circuit is nothing except an LED + 56 ohm resistor connected to Port #7 Pin #2.  There's no chance that anything is shorted anywhere and I don't care about the state of any other pins.  The following code should cause the LED to blink and me be able to read the port's current value after setting it.

const byte PORT = 7;
io60p16.SetPortMode(PORT, PORT_DRIVEMODE.RES_PULLDOWN);
io60p16.SetPortDirection(PORT, 0xff);

var timer = new GT.Timer(2000);
timer.Tick += timer1 =>
                    {
                    io60p16.SetPortOutput(PORT, 0x00);
                    Thread.Sleep(500);
                    io60p16.SetPortOutput(PORT, 0x04);
                    Thread.Sleep(500);
                    byte n = io60p16.GetPortOutput(PORT);
                    Debug.Print("Setting to: 0x04 \tReads as: " + n);
                    };
timer.Start();            

The first thing I notice is that you set the pin's mode within the timer-interrupt routine which you should do outsides in a hardware-initialization because there is no need to set that over and over again.

Agreed.  But for this simple test it shouldn't hurt anything.  I've moved it outside the thread for this new test.

 

By the way: To save a byte and some code, make your const byte PORT = 7    - to

#define PORT 7

 

 

This is C# code, not C.  "const" is the C# equivalent of "#define".



Re: Reading current status of output values on a port on a CY8C9560A

Bob Marlowe posted on 28 May 2012 03:39 PM PST
Top Contributor
1768 Forum Posts

OK, next step: any reason why you use resistive pull-down-mode? A pin usually can sink a lot more than it may source.

I'd choose open drain low and connect the LED and the limiting resistor (5V-1.7V)/20mA = 165Ohms to VCC.and driving low the pin to turn on the LED.

I do not want you to tinker with your project, but afaik this is the usual way to light an LED.

BTW: what is the reason you want to read-back the port-values? Experimental?? Or do you have something special in mind which you may talk about?.

Bob



Re: Reading current status of output values on a port on a CY8C9560A

ianlee74 posted on 28 May 2012 07:42 PM PST
Senior Member
11 Forum Posts

 Bob, I'm building a high-level driver for this Gadgeteer platform module:

http://www.ghielectronics.com/catalog/product/363

There is no specific project at this time.  This is an open source task that I volunteered to do.  So, the idea is to build a driver model that abstracts out all of the I2C goodness into something friendlier to hobbyist that's more suitable of a C# Gadgeteer environment.  I agree that in a real project, I would definitely sink to the pin.  However, in this case I only want to see that the pin is actually going high.  So, it was easier to just plug in a LED as in the attached pic and use the pulldown.  All I'm trying to accomplish at this point is to create the basic I2C functions to read/write/SetPulse etc.  So far, this has proven to be much more difficult than I ever expected.  Much of the problem has been with the software based I2C that I'm having to use.  I don't think that's the case in this problem since I can read that the values are being set but there simply appears to be no current being delivered.  

Thanks for hangin' in there with me.



Re: Reading current status of output values on a port on a CY8C9560A

Bob Marlowe posted on 29 May 2012 11:20 PM PST
Top Contributor
1768 Forum Posts

OK Ian,

let's get out the calculator and sharpen the pencil. You are providing an output port (when the port is stil alife despite overloading it) resistive pull-down to a diode and a 56-ohms resistor to Gnd. So we can assume, that the voltage on the pin to drive the diode is something like the diode's forward voltage which is something like 1.7V because it's a red one.

Now we come to the datasheet of the Cy8C9560 http://www.cypress.com/?docID=31413 . At page 18 which tells us something about the REQUIRED voltages for High (Vih) and Low (Vil). Here we see that Vih MINIMUM is 2.1V which compared to the 1.7V would be a near miss. So reading back your written values will not work all the time, it will sometimes fail as you already proved.

Some more examination of the datasheet  shows a max current on port7 as 80mA (which is far less than your 8 LEDs sinked) and per-pin 10 mA sourcing  ((5.0V -1.7V)/56Ohms)=59mA) which you have overdone a bit as well. If possible, try your tests with some appropriate LED/resistor combination on another port, so you do not have to use another module. I would suggest a 5mA LED and a (at least!!!) 560 Ohms resistor.

Bob



Re: Reading current status of output values on a port on a CY8C9560A

ianlee74 posted on 29 May 2012 06:15 AM PST
Senior Member
11 Forum Posts

Bob, I decided to go back to my very earliest version of the driver where it did nothing except blink an LED and guess what ...it works.  So, I've apparently mucked something up along the way.  I'll do a line by line comparison tonight and see if I can figure this mystery out.  What still doesn't make sense though is why the module would read a high value that obviously isn't true.

 



Re: Reading current status of output values on a port on a CY8C9560A

ianlee74 posted on 30 May 2012 09:38 PM PST
Senior Member
11 Forum Posts

 Bob, I'm in much better shape now.  I can blink an LED and read back it's value.  My setup at the moment is a single (red) 20mA LED + 180ohm resistor sinking to port 7 pin 3.  Running the same loop using resistive pullup drive mode, I get the following.  There are still a fair amount of inaccuracies.  Is there anything else that can be done to making reading the current state values any more accurate?

 

Set: 4 Read: 4

Set: 4 Read: 4

Set: 4 Read: 4

Set: 4 Read: 255

Set: 4 Read: 4

Set: 4 Read: 4

Set: 4 Read: 4

Set: 4 Read: 5

Set: 4 Read: 4

Set: 4 Read: 4

Set: 4 Read: 4

Set: 4 Read: 4

Set: 4 Read: 255

Set: 4 Read: 4

Set: 4 Read: 255

Set: 4 Read: 7

Set: 4 Read: 4

Set: 4 Read: 4

Set: 4 Read: 4

Set: 4 Read: 4

Set: 4 Read: 4



Re: Reading current status of output values on a port on a CY8C9560A

ianlee74 posted on 31 May 2012 10:29 AM PST
Senior Member
11 Forum Posts

 Bob, we've determined that this is actually a problem with the software I2C library we're using.  It seems that the incorrect reads are actually a result of the communications randomly reading the wrong ports.  Using hardware based I2C, we are getting 100% correct reads.  :)  Sorry to have wasted your time.  Thanks.



Re: Reading current status of output values on a port on a CY8C9560A

Bob Marlowe posted on 31 May 2012 11:01 AM PST
Top Contributor
1768 Forum Posts

Congratulations Ian!

Bob






ALL CONTENT AND MATERIALS ON THIS SITE ARE PROVIDED "AS IS". CYPRESS SEMICONDUCTOR AND ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF THESE MATERIALS FOR ANY PURPOSE AND DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THESE MATERIALS, INCLUDING BUT NOT LIMITED TO, ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT OF ANY THIRD PARTY INTELLECTUAL PROPERTY RIGHT. NO LICENSE, EITHER EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, IS GRANTED BY CYPRESS SEMICONDUCTOR. USE OF THE INFORMATION ON THIS SITE MAY REQUIRE A LICENSE FROM A THIRD PARTY, OR A LICENSE FROM CYPRESS SEMICONDUCTOR.

Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms and Conditions of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms and Conditions of this site. Cypress Semiconductor and its suppliers reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

Spec No: None; Sunset Owner: GRAA; Secondary Owner: RAIK; Sunset Date: 01/01/20