In previous posts I wrote about blinking LED and configuring ports. Now it is time to read some buttons.
First we need to generate project in CubeMX, we need to select board as in our Blinky example (I will explain later why we are selecting Nucleo board and not our specific microcontroller):
Next we need to set project settings:
Now we need to generate program (Menu -> Project -> Generate Code) and click on Open Project and now we are ready in SW4STM32 to start coding.
First we need to check if everything is ready. We Build our program (by clicking on hammer on toolbar. We need to get something like …Build finished… in console.
As we can see here, the blue button is connected to pin 13 of PORT C:
We need to configure this pin to be input, internal pull-up resitor is not needed because there is one on the board outside of microcontroller. If you look you can also see R29 and C15 which are used for debouncing.
We need some kind of feedback of button reading so we will be using main.c from Blinky example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
int main(void) { /* USER CODE BEGIN 1 */ __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef Init_LED; /* USER CODE END 1 */ /* MCU Configuration----------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); /* USER CODE BEGIN 2 */ Init_LED.Pin = LD2_Pin; Init_LED.Mode = GPIO_MODE_OUTPUT_PP; Init_LED.Pull = GPIO_NOPULL; Init_LED.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LD2_GPIO_Port, &Init_LED); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET); HAL_Delay(1000); HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET); HAL_Delay(1000); } /* USER CODE END 3 */ } |
You can copy above code and replace main function in main.c if you haven’t gone through blinky example. Build and test program, Green LED should blink with one second interval. And now we start our program for reading Button.
We need to start clock for PORTC, we do this by changing user code 1 in main.c to:
1 2 3 4 5 |
/* USER CODE BEGIN 1 */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); GPIO_InitTypeDef Init_LED; /* USER CODE END 1 */ |
We also need to add one more line for pin initialization:
1 2 3 4 5 6 |
/* USER CODE BEGIN 1 */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); GPIO_InitTypeDef Init_LED; GPIO_InitTypeDef Init_Button; /* USER CODE END 1 */ |
And we need to set pin registers:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* USER CODE BEGIN 2 */ Init_LED.Pin = LD2_Pin; Init_LED.Mode = GPIO_MODE_OUTPUT_PP; Init_LED.Pull = GPIO_NOPULL; Init_LED.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LD2_GPIO_Port, &Init_LED); Init_Button.Pin = B1_Pin; Init_Button.Mode = GPIO_MODE_INPUT; Init_Button.Pull = GPIO_NOPULL; Init_Button.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(B1_GPIO_Port, &Init_Button); /* USER CODE END 2 */ |
B1-Pin and B1_GPIO_Port are fixed values set by CubeMX and are written in main.h under inc folder of our project:
1 2 |
#define B1_Pin GPIO_PIN_13 #define B1_GPIO_Port GPIOC |
They are added by CubeMX. They are added because we selected Nucleo board when we selected new project. If we would be starting new project just by selecting our microcontroller from list, then this defines would not be here.
We also need to replace program inside while() loop in main.c so that LED would show us the button state.
If you look at this picture you see that LED lights when output is high, but if you check higher up, yo see that by pushing button we pul the input low. This means that if the input is low then button is pressed and LED output must be high and vise versa.
We do this with these few commands:
1 2 3 4 5 6 7 |
/* USER CODE BEGIN 3 */ if(HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin)) HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);// else HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET); } /* USER CODE END 3 */ |
To explain these few lines of code:
-first in the line with if statement we check if the pin input is high. If it is, that means that button is not pressed.
-so in next line we “RESET” output to LED.
-if pin input is low, then the first statement inside brackets is not true and the statement after else runs and this one “SETS” LED output and LED light up.
This concludes our input reading example.