czwartek, 29 września 2022

[0] STM32 - Project C++

W tym poście chciałbym opisać sposób przygotowania projektu w języku C++ dla układu STM32.

[Źródło: http://www.st.com/en/evaluation-tools/stm32f4discovery.html]

Na samym początku należy standardowo wygenerować projekt za pomocą CubeMx. 

Po wygenerowaniu i załadowaniu np. do STM32CubeIde, projekt należy przekonwertować do C++, przez kliknięcie na niego prawym przyciskiem myszy. 


Po konwersji należy dołożyć plik main.cpp lub zmienić nazwę już umieszczonego pliku main.c.

W tak przygotowanym projekcie można sprawdzić działanie operacji przesyłania danych na terminal:

  1. #include <iostream>
  2.  
  3. int __io_putchar (int ch)
  4. {
  5.     HAL_UART_Transmit(&huart2, (uint8_t*)&ch, 1, 1000);
  6.     return ch;
  7. }
  8.  
  9. //W funkcji main oba sposoby przesłania danych zadziałają poprawnie
  10. std::cout << "wartosc " << "\r\n";
  11. printf("test2\r\n");

Przy takiej implementacji __io_putchar na terminalu można zaobserwować poprawne działanie obu funkcji.

Poniżej przykład użycia:

  1. uint8_t value = 12;
  2. int value2 = 56;
  3. std::cout << unsigned(value) << "\r\n";
  4. std::cout << value2 << "\r\n";
  5. printf("test2 %u\r\n", value);

Teraz przygotuję prostą klasę obsługującą cztery diody zamontowane na płytce discovery.

Klasę można dodać przez kliknięcie prawym przyciskiem na projekt Add->Class. Otworzy to okno z możliwością dodania nowych plików.


Poniżej przykładowa klasa obsługująca cztery wbudowane diody na urządzeniu:

  1. #ifndef INC_DIODECONTROLCLASS_H_
  2. #define INC_DIODECONTROLCLASS_H_
  3.  
  4. #include "main.h"
  5.  
  6. class DiodeControlClass {
  7. private:
  8.     uint8_t diodeNumber;
  9.     void InitPins(void);
  10. public:
  11.     DiodeControlClass();
  12.     virtual ~DiodeControlClass();
  13.     void TurnOnDiode(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
  14.     void TurnOffDiode(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
  15.     void ToggleDiode(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
  16.     void LoopThroughDiodes(void);
  17. };
  18.  
  19. #endif /* SRC_DIODECONTROLCLASS_H_ */

  1. #include "DiodeControlClass.h"
  2.  
  3. DiodeControlClass::DiodeControlClass() {
  4.     // TODO Auto-generated constructor stub
  5.     InitPins();
  6. }
  7.  
  8. DiodeControlClass::~DiodeControlClass() {
  9.     // TODO Auto-generated destructor stub
  10. }
  11.  
  12. void DiodeControlClass::InitPins(void)
  13. {
  14.       GPIO_InitTypeDef GPIO_InitStruct = {0};
  15.       __HAL_RCC_GPIOD_CLK_ENABLE();
  16.       HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
  17.       GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
  18.       GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  19.       GPIO_InitStruct.Pull = GPIO_NOPULL;
  20.       GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  21.       HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  22. }
  23.  
  24. void DiodeControlClass::TurnOnDiode(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
  25.      HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_SET);
  26. }
  27.  
  28. void DiodeControlClass::TurnOffDiode(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
  29.      HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_RESET);
  30. }
  31.  
  32. void DiodeControlClass::ToggleDiode(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin){
  33.     HAL_GPIO_TogglePin(GPIOx, GPIO_Pin);
  34. }
  35.  
  36. void DiodeControlClass::LoopThroughDiodes(void)
  37. {
  38.     if(diodeNumber >= 4)
  39.     {
  40.         diodeNumber = 0;
  41.     }
  42.  
  43.     if(diodeNumber == 0) {
  44.         ToggleDiode(GPIOD, GPIO_PIN_12);
  45.         diodeNumber++;
  46.     }
  47.     else if(diodeNumber == 1) {
  48.         ToggleDiode(GPIOD, GPIO_PIN_13);
  49.         diodeNumber++;
  50.     }
  51.     else if(diodeNumber == 2) {
  52.         ToggleDiode(GPIOD, GPIO_PIN_14);
  53.         diodeNumber++;
  54.     }
  55.     else if(diodeNumber == 3) {
  56.         ToggleDiode(GPIOD, GPIO_PIN_15);
  57.         diodeNumber++;
  58.     }
  59. }

Jej wywołanie wywołanie wygląda następująco:

  1.   /* USER CODE BEGIN 2 */
  2.   DiodeControlClass DiodeControl;
  3.   /* USER CODE END 2 */
  4.  
  5.   /* Infinite loop */
  6.   /* USER CODE BEGIN WHILE */
  7.   while (1)
  8.   {
  9.     /* USER CODE END WHILE */
  10.  
  11.     /* USER CODE BEGIN 3 */
  12.       DiodeControl.LoopThroughDiodes();
  13.       HAL_Delay(400);
  14.   }
  15.   /* USER CODE END 3 */