2024-03-25 06:59 AM - last edited on 2024-04-08 05:19 AM by Amel NASRI
Hello,
I am new to STM world.
I am trying to make an array of GPIO pin in this format {{PIN1_GPIO_PORT, PIN1_PIN}.....
This would then be used in custom function so I can dynamically access this pins.
How should I declare such array and how would i use them with HAL_GPIO_WRITEPIN function.
Main use of this is to select SPI slave to communicate with.
Thanks in advance
Solved! Go to Solution.
2024-03-25 07:14 AM - edited 2024-03-25 07:21 AM
@Huzo wrote:I am new to STM world.
Do you have any experience with any other microcontrollers?
Do you have any experience with programming in general? With C programming?
@Huzo wrote:I am trying to make an array of GPIO pin in this format {{PIN1_GPIO_PORT, PIN1_PIN}.....
I would have a struct for the {port,pin} pair, and then make an array of those structs ...
As you want to use it with HAL_GPIO_WritePin, make the types compatible with what that function requires:
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
So you'd have something like
typedef struct
{
GPIO_TypeDef* GPIOx;
uint16_t GPIO_Pin;
} port_and_pin_t;
port_and_pin_t ports_and_pins[length];
:
:
HAL_GPIO_WritePin( ports_and_pins[x].GPIOx, ports_and_pins[x].GPIO_Pin, value );
You might want to make a "wrapper" function which just takes the struct, breaks-out the 2 elements, and passes them to HAL_GPIO_WritePin ...
2024-03-25 07:07 AM - edited 2024-03-25 07:15 AM
<deleted - the right answer was posted below>
struct pin_ {
GPIO_TypeDef *port;
uint16_t pinmask;
};
2024-03-25 07:11 AM
Create a structure, array the structure. More C than STM32
2024-03-25 07:14 AM - edited 2024-03-25 07:21 AM
@Huzo wrote:I am new to STM world.
Do you have any experience with any other microcontrollers?
Do you have any experience with programming in general? With C programming?
@Huzo wrote:I am trying to make an array of GPIO pin in this format {{PIN1_GPIO_PORT, PIN1_PIN}.....
I would have a struct for the {port,pin} pair, and then make an array of those structs ...
As you want to use it with HAL_GPIO_WritePin, make the types compatible with what that function requires:
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
So you'd have something like
typedef struct
{
GPIO_TypeDef* GPIOx;
uint16_t GPIO_Pin;
} port_and_pin_t;
port_and_pin_t ports_and_pins[length];
:
:
HAL_GPIO_WritePin( ports_and_pins[x].GPIOx, ports_and_pins[x].GPIO_Pin, value );
You might want to make a "wrapper" function which just takes the struct, breaks-out the 2 elements, and passes them to HAL_GPIO_WritePin ...
2024-03-25 07:19 AM - edited 2024-03-25 07:33 AM
Note that the GPIO_Pin parameter of HAL_GPIO_WritePin is a bitmask - not a pin number ...
/** @defgroup GPIO_pins GPIO pins
* @{
*/
#define GPIO_PIN_0 ((uint16_t)0x0001U) /* Pin 0 selected */
#define GPIO_PIN_1 ((uint16_t)0x0002U) /* Pin 1 selected */
#define GPIO_PIN_2 ((uint16_t)0x0004U) /* Pin 2 selected */
#define GPIO_PIN_3 ((uint16_t)0x0008U) /* Pin 3 selected */
#define GPIO_PIN_4 ((uint16_t)0x0010U) /* Pin 4 selected */
#define GPIO_PIN_5 ((uint16_t)0x0020U) /* Pin 5 selected */
#define GPIO_PIN_6 ((uint16_t)0x0040U) /* Pin 6 selected */
#define GPIO_PIN_7 ((uint16_t)0x0080U) /* Pin 7 selected */
#define GPIO_PIN_8 ((uint16_t)0x0100U) /* Pin 8 selected */
#define GPIO_PIN_9 ((uint16_t)0x0200U) /* Pin 9 selected */
#define GPIO_PIN_10 ((uint16_t)0x0400U) /* Pin 10 selected */
#define GPIO_PIN_11 ((uint16_t)0x0800U) /* Pin 11 selected */
#define GPIO_PIN_12 ((uint16_t)0x1000U) /* Pin 12 selected */
#define GPIO_PIN_13 ((uint16_t)0x2000U) /* Pin 13 selected */
#define GPIO_PIN_14 ((uint16_t)0x4000U) /* Pin 14 selected */
#define GPIO_PIN_15 ((uint16_t)0x8000U) /* Pin 15 selected */
#define GPIO_PIN_All ((uint16_t)0xFFFFU) /* All pins selected */
EDIT
As @gbm suggested, calling the member of your struct something like "pinmask" would help.
2024-03-25 07:28 AM
I have some experience with AVR and C programming. I was also thinking about structures but I am not fond of them.
So new structure would use definitions for pins as setup by STM32CUDEide. I have added comments to your code snippet.
typedef struct
{
GPIO_TypeDef* GPIOx; // example PIN1_GPIO_PORT
uint16_t GPIO_Pin; // example PIN1_PIN
} port_and_pin_t;
port_and_pin_t ports_and_pins[length];
:
:
HAL_GPIO_WritePin( ports_and_pins[x].GPIOx, ports_and_pins[x].GPIO_Pin, value );
To be honest right now I am using nested switch case to make changes to 2 SPI chips (I/O expanders). I would need to scale this up to 12 or even 15 of them so nested switch case would be crazy long.
2024-03-25 07:30 AM
@gbm wrote:<deleted - the right answer was posted below>
For one thing, I think your choice of "pinmask" as the name for the pin element is better than mine!
I always find the ST documentation very unclear on whether these HAL functions expect a pin mask or a pin number.
:frowning_face:
2024-03-25 07:33 AM
There is no perfect documentation. I will try to make the structure and use without my function, for testing purposes, and will come here with a reply. Thanks.
2024-03-25 07:38 AM - edited 2024-03-25 07:59 AM
@Huzo wrote:I was also thinking about structures but I am not fond of them.
Why not?
They are exactly the language solution for this type of problem - collecting together items of differing types.
EDIT
If you really can't stand structs, you could just have 2 separate arrays - one array holding ports, and the other holding pins; eg,
GPIO_TypeDef* ports [size]; // example PIN1_GPIO_PORT
uint16_t pinmaps[size]; // example PIN1_PIN
:
:
HAL_GPIO_WritePin( ports[x], pinmaps[x], value );
But then you lose the inherent benefit of structs in keeping the pin and its associated port together.
2024-03-26 02:42 AM
With arrays it works as intended. So next stop is with a structure. If that works than I will go to structured array and to function. That should lower the complexity of the code. The structure would consist of 5 (or more) variables Number of MCP (1st, 2nd..) Ports, pins and PORTA and PORTB (IO expander port register).