How do I read individual pins from a grouped pin block?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hello PSOC people!

I am currently working on a project which requires at least 16 pin interrupts, and I have been trying to implement this. 

The idea is that a set of pins are grouped in one component (number of pins = 7 in the topdesign file) , and they share an ISR which will check the previous values across these pins against the current logic levels.
My 'block' of pins is labeled 'Pin_D' and I would assume that to read the pins it would be as simple as using  "value = Pin_D_N_Read();", where N is the pin number I want to reference but when I try to do this I get an "Implicit declaration of function 'Pin_D_N_Read' is invalid in c99" warning.


Am I doing something wrong or should I just ignore this warning and pray that it doesn't come back to haunt me later?

0 Likes
1 Solution
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Easiest when reading digital pins will be

Pin_D_Read() & (0x01 << PinNumber)

which will return FALSE when the selected pin is low.

Bob

View solution in original post

20 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Easiest when reading digital pins will be

Pin_D_Read() & (0x01 << PinNumber)

which will return FALSE when the selected pin is low.

Bob

Anonymous
Not applicable

Yep this works great!

Heads up to anyone else trying this, if you test this method with something like a switch on just a single pin , if you move the wire connected to the switch and connect it to the next pin in the group your PSOC may interpret button presses as happening on the original socket due to what I can assume is some kind of coupling effect. Stablising the line by connecting it to circuitry resolves this behaviour.

0 Likes

Floating pins are always prone to changes due to stray capacitance influence.  Pins connected to switches should be defined as resistive pull up and the switch should close to GND. Safest solution.

Bob

Anonymous
Not applicable

So I currently have the following code called by an interrupt.
Pins 0-6 are grouped and 7 is on its own.  The function successfully switches on a debug LED after this is done so I know this function runs.
I am expecting whatever combination of buttons I hold to be be reflected in the LEDs, but only LED 0 and 7 seem to respond.
I have also tried shifting the result of the logic operation to the right by the number of bits they are shifted to the left but to no avail.

         uint8 rawDigital = Pin_D_Read();

   

         moduleStatusD[0] = rawDigital & (0x00000001);

         moduleStatusD[1] = rawDigital & (0x01 << 1);

         moduleStatusD[2] = rawDigital & (0x01 << 2);

         moduleStatusD[3] = rawDigital & (0x01 << 3);

         moduleStatusD[4] = rawDigital & (0x01 << 4);

         moduleStatusD[5] = rawDigital & (0x01 << 5);

         moduleStatusD[6] = rawDigital & (0x01 << 6);

         moduleStatusD[7] = Pin_D_7_Read();

   

         LED_Extern_0_Write(moduleStatusD[0]);

         LED_Extern_1_Write(moduleStatusD[1]);

         LED_Extern_2_Write(moduleStatusD[2]);

         LED_Extern_3_Write(moduleStatusD[3]);

   

         LED_Extern_4_Write(moduleStatusD[4]);

         LED_Extern_5_Write(moduleStatusD[5]);

         LED_Extern_6_Write(moduleStatusD[6]);

         LED_Extern_7_Write(moduleStatusD[7]);

0 Likes
Anonymous
Not applicable

how do I get each LED to reflect the button state?

0 Likes
Anonymous
Not applicable

Fixed:

uint8 rawDigital = Pin_D_Read();

   

    if ( (rawDigital & (0b00000001) )  == 0b00000001){moduleStatusD[0] = 1;}

    else {moduleStatusD[0] = 0;}

    if  ( (rawDigital & (0b00000010) ) == 0b00000010){moduleStatusD[1] = 1;}

    else {moduleStatusD[1] = 0;}

    if  ( (rawDigital & (0b00000100) ) == 0b00000100){moduleStatusD[2] = 1;}

    else {moduleStatusD[2] = 0;}

    if  ( (rawDigital & (0b00001000) ) == 0b00001000){moduleStatusD[3] = 1;}

    else {moduleStatusD[3] = 0;}

    if  ( (rawDigital & (0b00010000) ) == 0b00010000){moduleStatusD[4] = 1;}

    else {moduleStatusD[4] = 0;}

    if  ( (rawDigital & (0b00100000) ) == 0b00100000){moduleStatusD[5] = 1;}

    else {moduleStatusD[5] = 0;}

    if  ( (rawDigital & (0b01000000) ) == 0b01000000){moduleStatusD[6] = 1;}

    else {moduleStatusD[6] = 0;}

    moduleStatusD[7] = Pin_D_7_Read();

   

   

    LED_Extern_0_Write(moduleStatusD[0]);

    LED_Extern_1_Write(moduleStatusD[1]);

    LED_Extern_2_Write(moduleStatusD[2]);

    LED_Extern_3_Write(moduleStatusD[3]);

   

    LED_Extern_4_Write(moduleStatusD[4]);

    LED_Extern_5_Write(moduleStatusD[5]);

    LED_Extern_6_Write(moduleStatusD[6]);

    LED_Extern_7_Write(moduleStatusD[7]);

You could try something like

uint8 Mask = 0x01;

uint8 ii;

uint8 rawDigital = Pin_D_Read();

for(ii = 0; ii < 6;ii++)

{

    moduleStatus[ii] = (rawDigital & Mask )  == Mask:

    Mask = Mask << 1;

}

moduleStatusD[7] = Pin_D_7_Read();

Bob   

0 Likes
Anonymous
Not applicable

Having some weird issues using this with Timer interrupts.
When I use this method to read the status of the buttons normally or from a hardware interrupt it works fine, However when using it within an interrupt triggered by a timer the status of pin 0 is not recognised.
If I trigger the interrupt by pressing another button whilst holding button 0 the state of button 0 is registered as normal.

0 Likes

Wasn't there a restriction to max. 7 pins of a port + interrupt? I think I can remember...

Bob

0 Likes
Anonymous
Not applicable

Sorry that previous message was code spangled brain slop.


What I meant to say is:

1) When a button is pressed a variable is set stating that this button is currently being debounced.  (Works fine)
2) if it is not already running a timer is started (works fine)
3) every ms (I have tried various other rates) all of the buttons are sampled.
4) if 3 matching samples in a row are found the state is considered to be open or closed

5) Button state is sent over I2C

The problem seems to creep in at step 4.
I have tried having LEDs light up to reflect the button state.

Button 0 - Does nothing
Button 1 - 50% chance of packet received light toggling
Button 2 - Main unit correctly updates to display button state about 90% of the time
button 3 - Like Button 2 but only works about 75% of the time
button 4 - 7: Like button 2 but only approximately 60% of transitions are picked up and main unit always sees them as unpressed.

I'm pretty sure it's not my I2C function as I am sending 3 bytes at a time, the middle byte being the status of the button, either 255u or 0u (forced values, not 'read')
The first and third bytes are always perfect (displaying on a screen), but the second byte just seems to get 0 no matter what (except with buttons 2 and 3).

Would anyone be willing to take a look at my code if I make a workspace bundle and forward it to you?
I don't particularly want to make all of it public in this case.

0 Likes

Can you please post your complete project or a shortened version that shows the error so that we all can have a look at all of your settings. To do so, use

Creator->File->Create Workspace Bundle (minimal)

and attach the resulting file.

Which kind of board do you use? Self made? Cypress Kit Cy8CKITxxxx?? Which one???

Bob

0 Likes
Anonymous
Not applicable

I actually seem to have fixed this since, I believe it was due to the allocated size of my stack, and was resolved when the stack size was increased.

0 Likes
GeIo_1586191
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

I ahve the same issue but I would like to know how do you read an individual pin state using a Pin alias rather than Pin Number.

I have the following configuration:

pastedImage_0.png

I then see this creates the following for each pin alias, but what do each of these mean and how do you use them (i.e. in what context):

#define Pin_D_INTR_ALL ((uint16)(Pin_D_0_INTR| Pin_D_1_INTR| Pin_D_2_INTR))

#define Pin_D_AliasName1 (Pin_D__AliasName1__PC)

#define Pin_D_AliasName1 _PS (Pin_D__AliasName1__PS)

#define Pin_D_AliasName1 _PC (Pin_D__AliasName1__PC)

#define Pin_D_AliasName1 _DR (Pin_D__AliasName1__DR)

#define Pin_D_AliasName1 _SHIFT (Pin_D__AliasName1__SHIFT)

#define Pin_D_AliasName1 _INTR ((uint16)((uint16)0x0003u << (Pin_D__0__SHIFT*2u)))

etc.

0 Likes
Anonymous
Not applicable

Most of those defines are generated by the compiler for usage within APIs, if you right-click the pin and open the datasheet, you should be able to get more information on the Alias usage and how to access pins individually. (Page 36 specifically)

Note: the alias name in your image shown above is the entire string "Pin_D_AliasName1", you can rename this to "AliasName1" or whatever other name you choose to simplify/shorten the string for the alias name

Otherwise, I believe the defines listed above are generated for your individual access to the pins using other functions with the defines passed as arguments to refer to the individual pin for usage.

0 Likes

Thanks so much for the helpful comment.

Here I was stopping on page 29 (pin_read/pin_write) and thinking "this can't be it"... so brilliant I need to read on to page 36.

So, from what I gather from the description on this page I need to use a different API function call altogether (linked to cyPins.h), i.e. CyPins_ReadPin(Pin_MyAlias)

Regarding the shortening of Pin aliases, I do not follow your comment. I clicked on the pin component then clicked on the individual pin and pressed F2. A dialogue box opens and I entered "AliasName1" here. This then appended this name onto Pin_D to form "Pin_D_AliasName1". So I cannot see a shorter method unless I can now use "AliasName1" as Pin_MyAlias reference.

0 Likes
Anonymous
Not applicable

Ah; Yes, I was wrong. For some reason I was thinking you could shorten it further. I forgot that the compiler prefixes the Button name in general on the front.

Referring to the Pin reading, yes that is what the documentation says for reading the pins. When the IDE generates the code however, it also creates the functions: <Pin_Name>_Read(), <Pin_Name>_Write(uint8 value), <Pin_Name>_ReadDataReg(), <Pin_Name>_SetInterruptMode(uint16 position, uint16 mode), <Pin_Name>_ClearInterrupt(), <Pin_Name>_Sleep(), <Pin_Name>_Wake(), and potentially the function <Pin_Name>_SetDriveMode(uint8 mode)

Those are the functions defined on page 29 in the datasheet, and should work as well. If there are Pin coding examples, they may demonstrate the functionality and usage better as well.

0 Likes

Page 29 is a little misleading, in my opinion, as if you read the description (uint8 Pin_Read(void): "Reads the associated physical port (pin status register) and masks the required bits according to the width and bit position of the component instance.") it is my understanding that this function actually applies to the port and not to an individual pin (if grouped). Maybe it should have been labelled as "Port_Read(void)" or "PinStatusReg_Read(void)"

So in my case, I can do a Pin_D_Read(), for example, and this will read the values from any of the three pins assigned to that port. There is no function Pin_D_AliasName1_Read(), for example.

Anyway, what I do not quite understand from page 29 of the documentation is the following "(pin status register) and masks the required bits according to the width and bit position of the component instance.". How does one unravel this to reveal an individual pin status?

0 Likes

I finally resolved this adding a Status Register component (under Digital:Registers catalog folder).

pastedImage_0.png

The nice thing here is that this allows you to determine the status of all pin inputs concurrently (i.e. whether high or low etc.) Nice and neat.

The NOT components are only needed if your default pin input state is 1 and you want your status register output to be zero by default too.

0 Likes

For the benefit of others struggling to grasp how to do this, I discovered that when using a port/pin interrupt there is this handy function,i.e.

PinD_ClearInterrupt();

This gave me the same answer as the status register component, which I found was the method most useful when port/pin polling.

Anonymous
Not applicable

The wording is confusing, but from what I've found playing with the function, it will AND the pin states of the pins associated with the component (if you select two of the 8 pins on a port for example, it will AND 1's with the pins that you have defined as in use by the pin component).

It will then bit shift the value so that the bit 0 of the returned value will be the state of the first pin defined in the pin component.

An example to try to explain it better:

Pin component with pins 0_1, 0_2, 0_3 defined as used by the pin component.

A read value with pins 0_1, 0_3, 0_4 being high will return the value 0x05 with the pin 0_4 being masked out to 0.

The function essentially abstracts away the extra pins on each port that are not included for use in the pins component, and gives them a consistent value of 0 to make math and calculations easier for whatever is done.