Harman 세미콘 아카데미/STM32

2024.7.22 [STM32]3 - BUTTON, UART

U_Pong 2024. 7. 22. 21:37

2024.7.22 수업날


< BUTTON >

STM32cubeide 진행 과정

이번에는 00_BASIC의 .ioc 파일을 불러오는 방식으로 새로운 파일을 만든다.

강의실 컴퓨터에서 캡쳐한 사진이므로 위치가 다를 수 있다.

 

 

main.c 소스코드
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  	if(!(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)))
  	{
  		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
  	}
  	else
  	{
  		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 0);
  	}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

여러개의 파일이 열려있을 때, 원하는 하나의 파일만 build 시키고 싶다면

원하는 파일에서 오른쪽 클릭을 하여 Build Project를 선택하면 된다.

그리고 build 시킬 파일만 열어두고, 사용하지 않는 파일은 Close Project를 선택하여 잠시 닫아두는 것이 좋다.

 

이제 run을 실행하기 위하여 상단의 run 아이콘의 옆 화살표를 선택한 후  Run Configurations를 선택한다.

 

그리고 run 하려는 파일을 좌측에 나타나게 한 후에 run을 실행해야한다.

 

 

다음으로 debug를 실행해보자.

디버그를 실행했을 때 디버그 창으로 항상 스위칭 하는지 물어보는 창

 

디버그 실행 시, 나타나는 창

 

디버그가 되는지 확인하기 위해서는 왼쪽에서 두번째 아이콘을 클릭하면 된다.

 

좌측의 SFRs에서 결과가 나타나는 것을 확인할 수 있다.

 

 

이번에는 stm32 보드에 있는 USER 버튼을 눌렀을때만 LED 불이 들어오는 소스코드를 작성했다.

BUTTON 결과

 

 

다음으로 led bar를 사용하여 좌측으로 차례대로 켜지면서 다시 좌측부터 꺼지는 소스코드를 작성해본다.

아래의 그림처럼 파일을 순서대로 추가하고 작성한다.

 

STM32cubeide 진행 과정

사진에서 PA5도 led bar에 연결할때 필요하다.

 

 

새로 만든 App 파일에 아래와 같이 파일을 2개를 추가로 만든다.

 

최종적으로 아래와 같이 파일과 소스코드를 생성해주면 된다.

강의실 컴퓨터에서 캡쳐한 사진으로 파일 이름이 다름

 

def.h 소스코드
/*
 * def.h
 *
 *  Created on: Jul 24, 2024
 */

#ifndef COMMON_DEF_H_
#define COMMON_DEF_H_

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

//#include "main.h"
#include "stm32f4xx_hal.h"



#endif /* COMMON_DEF_H_ */

 

hw_def.h 소스코드
/*
 * hw_def.h
 *
 *  Created on: Jul 24, 2024
 */

#ifndef HW_HW_DEF_H_
#define HW_HW_DEF_H_

#include "def.h"


#define _LED_MAX_CH		8
#define _BUTTON_MAX_CH		3

#endif /* HW_HW_DEF_H_ */

 

hw.c 소스코드
/*
 * hw.c
 *
 *  Created on: Jul 24, 2024
 */


#include "hw.h"

void hwInit()
{
	ledInit();
}


// 할 딜레이 함수 대체
void delay(uint32_t time_ms)
{
	HAL_Delay(time_ms);
}

// 전원 입력후에 카운트 값을 반환 함수
// 시스템 틱을 이용함
uint32_t millis(void)
{
	return HAL_GetTick();
}

 

hw.h 소스코드
/*
 * hw.h
 *
 *  Created on: Jul 24, 2024
 */

#ifndef HW_HW_H_
#define HW_HW_H_

#include "hw_def.h"

#include "led.h"


void hwInit();


void delay(uint32_t time_ms);
uint32_t millis(void);

#endif /* HW_HW_H_ */

 

led.c 소스코드
/*
 * led.c
 *
 *  Created on: Jul 24, 2024
 *      Author: jsmok
 */


#include "led.h"
#include "hw.h"

LED_TBL led_tbl[_LED_MAX_CH] =
	{
		{GPIOA, GPIO_PIN_5, GPIO_PIN_SET, GPIO_PIN_RESET},
		{GPIOA, GPIO_PIN_6, GPIO_PIN_SET, GPIO_PIN_RESET},
		{GPIOA, GPIO_PIN_7, GPIO_PIN_SET, GPIO_PIN_RESET},

		{GPIOB, GPIO_PIN_6, GPIO_PIN_SET, GPIO_PIN_RESET},

		{GPIOC, GPIO_PIN_7, GPIO_PIN_SET, GPIO_PIN_RESET},

		{GPIOA, GPIO_PIN_9, GPIO_PIN_SET, GPIO_PIN_RESET},
		{GPIOA, GPIO_PIN_8, GPIO_PIN_SET, GPIO_PIN_RESET},

		{GPIOB, GPIO_PIN_10, GPIO_PIN_SET, GPIO_PIN_RESET}
	};

bool ledInit()
{
	bool ret = true;
	return ret;
}

void ledOn(uint8_t ch)
{
	if(ch > _LED_MAX_CH) return;

	for (uint8_t i = 0; i < ch; i++)
	{
		HAL_GPIO_WritePin(led_tbl[i].port, led_tbl[i].pinNumber, led_tbl[i].onState);
	}
}

void ledOff(uint8_t ch)
{
	if(ch > _LED_MAX_CH) return;

		for (uint8_t i = 0; i < ch; i++)
		{
			HAL_GPIO_WritePin(led_tbl[i].port, led_tbl[i].pinNumber, led_tbl[i].offState);
		}
}

void ledToggle(uint8_t ch)
{
	HAL_GPIO_TogglePin(led_tbl[ch].port, led_tbl[ch].pinNumber);
}


void ledLeftShift(uint8_t ch)
{
	for(uint8_t i = 0; i < ch; i++)
	{
		//HAL_GPIO_WritePin(led_tbl[i].port, led_tbl[i].pinNumber, 1);
		ledOn(i);
		delay(100);
	}
	delay(500);
	for(uint8_t i = 0; i < ch; i++)
	{
		//HAL_GPIO_WritePin(led_tbl[i].port, led_tbl[i].pinNumber, 0);
		ledOff(i);
	}
	delay(500);
}

 

led.h 소스코드
/*
 * led.h
 *
 *  Created on: Jul 24, 2024
 */

#ifndef HW_DEVICE_LED_H_
#define HW_DEVICE_LED_H_

#include "hw_def.h"

typedef struct
{
	GPIO_TypeDef 	*port;
	uint16_t		pinNumber;
	GPIO_PinState	onState;
	GPIO_PinState	offState;
}LED_TBL;


bool ledInit(void);
void ledOn(uint8_t ch);
void ledOff(uint8_t ch);
void ledToggle(uint8_t ch);

void ledLeftShift(uint8_t ch);


#endif /* HW_DEVICE_LED_H_ */

 

ap.c 소스코드
/*
 * ap.c
 *
 *  Created on: Jul 24, 2024
 */


#include "ap.h"

void apInit(void)
{
	hwInit();
}

void apMain(void)
{
	while(1)
	{
		ledLeftShift(8);
	}
}

 

ap.h 소스코드
/*
 * ap.h
 *
 *  Created on: Jul 24, 2024
 */

#ifndef AP_H_
#define AP_H_

#include "hw.h"

void apInit(void);		// 어플리케이션에 대한 초기화 함수
void apMain(void);		// 우리가 사용할 실질적인 메인함수



#endif /* AP_H_ */

 

main.c 소스코드
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "ap.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */

  apInit();
  apMain();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 100;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8
                          |GPIO_PIN_9, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10|GPIO_PIN_6, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);

  /*Configure GPIO pins : PA5 PA6 PA7 PA8
                           PA9 */
  GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8
                          |GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PB10 PB6 */
  GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_6;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : PC7 */
  GPIO_InitStruct.Pin = GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PA10 */
  GPIO_InitStruct.Pin = GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PB3 PB5 */
  GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

LED LeftShift 결과

 

 

다음으로 버튼을 눌렀을때만 led bar의 led가 켜지는 소스코드를 작성해본다.

LED LeftShift와 STM32cubeide 진행 과정은 똑같고, 수정할 부분만 첨부한다.

 

아래와 같이 button.c, button.h를 device 파일에 추가한다.

 

button.c 소스코드
/*
 * button.c
 *
 *  Created on: Jul 24, 2024
 */


#include "button.h"



typedef struct
{
	GPIO_TypeDef	*port;
	uint16_t			pinNumber;
	GPIO_PinState	onState;
}BUTTON_TBL;

BUTTON_TBL button_tbl[_BUTTON_MAX_CH] =
	{
		{GPIOB, GPIO_PIN_5, 0},
		{GPIOB, GPIO_PIN_3, 0},
		{GPIOA, GPIO_PIN_10, 0},
	};


bool buttonInit()
{
	bool ret = true;

	return ret;
}

bool buttonGetPressed(uint8_t ch)
{
	bool ret = false;

	if(ch >= _BUTTON_MAX_CH)
	{
		return ret;
	}

	if(HAL_GPIO_ReadPin(button_tbl[ch].port, button_tbl[ch].pinNumber) == button_tbl[ch].onState)
	{
		delay(10);
		if(HAL_GPIO_ReadPin(button_tbl[ch].port, button_tbl[ch].pinNumber) == button_tbl[ch].onState)
		{
			ret = true;
		}
	}
	return ret;
}

 

button.h 소스코드
/*
 * button.h
 *
 *  Created on: Jul 24, 2024
 */

#ifndef HW_DEVICE_BUTTON_H_
#define HW_DEVICE_BUTTON_H_

#include "hw.h"

bool buttonInit();
bool buttonGetPressed(uint8_t ch);


#endif /* HW_DEVICE_BUTTON_H_ */

 

ap.c 소스코드
/*
 * ap.c
 *
 *  Created on: Jul 24, 2024
 *      Author: jsmok
 */


#include "ap.h"

void apInit(void)
{
	hwInit();
}

void apMain(void)
{
	while(1)
	{
		if(buttonGetPressed(0))
		{
			ledOn(8);
		}
		else
		{
			ledOff(8);
		}
	}
}

 

BUTTON LED 결과

 

 

< UART_Rx >

STM32cubeide 진행 과정

 

여기서 usart2를 설정하고 자동으로 PA2, PA3이 usart2_tx, usart2_rx으로 설정되는 이유는

아래와 같이 핀이 TX, RX로 정해져있기 때문이다.

 

체크표시를 하지 않으면 폴링방식이다, 디버깅으로 결과를 확인하기 위해 체크표시를 하는 것

 

main.c 소스코드
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

uint8_t rxData[10];		// global val

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	//HAL_UART_Receive_IT(&huart2, rxData, 4);
	HAL_UART_Receive_DMA(&huart2, rxData, 4);
}

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  //HAL_UART_Receive_IT(&huart2, rxData, 4);	//interrupt
  HAL_UART_Receive_DMA(&huart2, rxData, 4);		//DMA

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  	//HAL_UART_Receive(&huart2, rxData, 4, 1000);

  	//check code
  	HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
  	HAL_Delay(200);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 100;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

UART_Rx는 uart 통신을 받는 결과만 확인할 수 있으므로 디버그를 통해 통신이 잘 되는지 확인할 수 있다.

UART_Rx 디버깅 결과

 

 

< UART_Tx >

STM32cubeide 진행 과정은 UART_Tx와 똑같다. 수정해야하는 코드만 첨부한다.

먼저 comportmaster에 uart 통신이 되는지 확인하기 위해 테스트 코드를 작성한다.

main.c 테스트 소스코드
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

uint8_t rxData[] = "Hello STM32F411\r\n";		// global val
//char hello_arr[] = "LED_ON";

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//	HAL_UART_Receive_IT(&huart2, rxData, 4);
//	HAL_UART_Receive_DMA(&huart2, rxData, 4);
	HAL_UART_Receive_IT(&huart2, &rxData, sizeof(rxData));
	HAL_UART_Transmit_IT(&huart2, &rxData, sizeof(rxData));
}

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  HAL_UART_Receive_IT(&huart2, &rxData, sizeof(rxData));	//interrupt
  //HAL_UART_Receive_DMA(&huart2, rxData, 4);		//DMA

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  	HAL_UART_Transmit(&huart2, rxData, sizeof(rxData), 100);
  	HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 100;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

1000 Delay 마다 지정한 문장이 반복해서 나타나도록 하는 테스트 코드이다.

UART_Tx 테스트 코드

 

 

이번에는 디버그를 통해 결과를 확인해본다.

UART_Rx와는 다르게 rxData의 크기를 지정해주지 않았기 때문에 기본적으로 1글자만 받으며,

comportmater에도 통신받은 글자가 2글자 이하로 받을 수 있는 소스코드이다.

main.c 소스코드
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

uint8_t rxData;		// global val

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//	HAL_UART_Receive_IT(&huart2, rxData, 4);
//	HAL_UART_Receive_DMA(&huart2, rxData, 4);
	HAL_UART_Receive_IT(&huart2, &rxData, sizeof(rxData));
	HAL_UART_Transmit_IT(&huart2, &rxData, sizeof(rxData));
}

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  HAL_UART_Receive_IT(&huart2, &rxData, sizeof(rxData));	//interrupt
  //HAL_UART_Receive_DMA(&huart2, rxData, 4);		//DMA

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 100;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

UART_Tx 디버그 결과

 

 

이번에는 uart 통신을 통해

a를 전송하면 LED_ON이라는 문구가 출력되면서 stm32보드의 LED가 켜지고,

b를 전송하면 LED_OFF라는 문구가 출력되면서 stm32보드의 LED가 꺼지는 소스코드를 작성해본다.

STM32cubeide 진행 과정

 

아래와 같이 파일과 소스코드를 추가해준다.

 

 led bar를 사용하여 좌측으로 차례대로 켜지면서 다시 좌측부터 꺼지는 소스코드와 진행방식은 똑같으며 수정해야하는 코드만 첨부한다.

uart.c 소스코드
/*
 * uart.c
 *
 *  Created on: Jul 24, 2024
 */

#include "uart.h"
#include "led.h"


uint8_t rxData;

uint8_t ledOn_arr[]="LED_ON\n";
uint8_t ledOff_arr[]="LED_OFF\n";



void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart == &huart2)
  {
    HAL_UART_Receive_IT(&huart2, &rxData, sizeof(rxData));

    if(rxData == 'a')
    {
      HAL_UART_Transmit_IT(&huart2, ledOn_arr, sizeof(ledOn_arr));
      ledOn(8);
    }
    if(rxData == 'b')
    {
      HAL_UART_Transmit_IT(&huart2, ledOff_arr, sizeof(ledOff_arr));
      ledOff(8);
    }
  }
}

 

uart.h 소스코드
/*
 * uart.h
 *
 *  Created on: Jul 24, 2024
 */

#ifndef HW_DEVICE_UART_H_
#define HW_DEVICE_UART_H_

#include "hw_def.h"


extern UART_HandleTypeDef huart2;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart2_tx;


bool uartInit(void);

#endif /* HW_DEVICE_UART_H_ */

 

ap.c 소스코드
/*
 * ap.c
 *
 *  Created on: Jul 24, 2024
 */


#include "ap.h"

void apInit(void)
{
	hwInit();
}

extern uint8_t rxData;

void apMain(void)
{
	HAL_UART_Receive_IT(&huart2, &rxData, sizeof(rxData));

	while(1)
	{

	}
}

 

UART_LED 결과

BUTTON, UART 끝!