전자공학/개인 설계
STM32 첫 설계
안녕 나의 20대
2024. 6. 28. 16:54
반응형
최초 종이 설계도
Schematic
PCB 설계도 (실제 회로랑 다름 설계 후 잘못된걸 인지해서 바꿈)
STM32 연결도
PCB 실물 (쌩 보드)
완성 후 모습
코딩하기 전 시프트 연산 구상도
코딩
#include "main.h"
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1; // UART 핸들러 정의
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN 0 */
// #define SWITCH_ADDRESS 0x00 // 스위치의 초기 주소 값 설정
/* USER CODE END 0 */
/**
* @brief 애플리케이션 시작점.
* @retval int
*/
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* 모든 주변 장치 초기화, Flash 인터페이스 및 Systick 초기화 */
HAL_Init();
/* 시스템 클록 구성 */
SystemClock_Config();
/* 모든 설정된 주변 장치 초기화 */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* 무한 루프 */
while (1)
{
// 초기 데이터 배열 설정
uint8_t data[5];
data[0] = 0x55;
data[1] = 0xAA;
data[2] = 0xF0;
data[3] = 0x0F;
data[4] = 0; // 초기 주소 값
uint8_t switch_pressed = 0; // 스위치가 눌렸는지 확인하는 플래그
// 각 스위치의 상태를 확인하고 데이터를 설정
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) {
data[4] |= (1 << 0); // 스위치 1
switch_pressed = 1; // 스위치가 눌렸음을 표시
}
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET) {
data[4] |= (1 << 1); // 스위치 2
switch_pressed = 1; // 스위치가 눌렸음을 표시
}
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) == GPIO_PIN_RESET) {
data[4] |= (1 << 2); // 스위치 3
switch_pressed = 1; // 스위치가 눌렸음을 표시
}
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3) == GPIO_PIN_RESET) {
data[4] |= (1 << 3); // 스위치 4
switch_pressed = 1; // 스위치가 눌렸음을 표시
}
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_RESET) {
data[4] |= (1 << 4); // 스위치 5
switch_pressed = 1; // 스위치가 눌렸음을 표시
}
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_RESET) {
data[4] |= (1 << 5); // 스위치 6
switch_pressed = 1; // 스위치가 눌렸음을 표시
}
// UART로 항상 데이터 전송
HAL_UART_Transmit(&huart1, data, 5, 100); // UART로 데이터 전송
// 스위치가 하나라도 눌렸을 때 LED 켜기
if (switch_pressed) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET); // LED 켜기
} else {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET); // LED 끄기
}
// 디바운싱을 위한 짧은 지연
HAL_Delay(50); // 지연 시간 조정 (50ms)
}
}
/**
* @brief 시스템 클록 구성
* @retval 없음
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** 메인 내부 레귤레이터 출력 전압 구성 */
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** RCC 오실레이터 초기화, 지정된 매개변수에 따라 오실레이터 구성 */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** CPU, AHB 및 APB 버스 클록 초기화 */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief USART1 초기화 함수
* @param 없음
* @retval 없음
*/
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200; // UART 보레이트 설정
huart1.Init.WordLength = UART_WORDLENGTH_8B; // 데이터 비트 길이 설정
huart1.Init.StopBits = UART_STOPBITS_1; // 정지 비트 설정
huart1.Init.Parity = UART_PARITY_NONE; // 패리티 비트 없음
huart1.Init.Mode = UART_MODE_TX_RX; // 송신 및 수신 모드 설정
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 하드웨어 흐름 제어 없음
huart1.Init.OverSampling = UART_OVERSAMPLING_16; // 오버샘플링 설정
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; // 한 비트 샘플링 비활성화
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1; // 클록 프리스케일러 설정
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_SWAP_INIT; // 고급 기능 초기화 - 핀 스왑
huart1.AdvancedInit.Swap = UART_ADVFEATURE_SWAP_ENABLE; // 핀 스왑 활성화
if (HAL_RS485Ex_Init(&huart1, UART_DE_POLARITY_HIGH, 0, 0) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO 초기화 함수
* @param 없음
* @retval 없음
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO 포트 클록 활성화 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/* GPIO 핀 출력 레벨 설정 */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET); // LED를 처음부터 끔
/* PA0 ~ PA5 핀 구성 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP; // 풀업 저항 사용
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* PA6 핀 구성 */
GPIO_InitStruct.Pin = 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(GPIOA, &GPIO_InitStruct);
}
/**
* @brief 오류 발생 시 실행되는 함수.
* @retval 없음
*/
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief assert_param 오류가 발생한 소스 파일과 소스 라인 번호를 보고합니다.
* @param file: 소스 파일 이름에 대한 포인터
* @param line: assert_param 오류 소스 번호
* @retval 없음
*/
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 */
주요 구성 요소
- 시스템 초기화
- HAL_Init(): 하드웨어 추상화 계층(HAL) 라이브러리를 초기화하여 MCU의 기본 설정을 초기화합니다.
- SystemClock_Config(): 시스템 클럭을 설정하여 MCU가 안정적으로 작동할 수 있도록 합니다.
- MX_GPIO_Init(): GPIO 핀들을 초기화합니다.
- MX_USART1_UART_Init(): UART1를 초기화하여 시리얼 통신을 설정합니다.
- 메인 루프
- 프로그램이 무한 루프(while (1)) 내에서 지속적으로 실행됩니다.
- GPIO 핀의 상태를 읽어 각 스위치의 상태를 확인합니다.
- 스위치의 상태에 따라 UART를 통해 데이터를 전송하고, LED를 제어합니다.
동작 원리
- GPIO 초기화
- MX_GPIO_Init(): GPIO 핀을 입력 모드와 출력 모드로 설정합니다. 스위치 입력 핀은 풀업 저항을 사용하여 초기 상태를 설정합니다. LED 핀은 출력 모드로 설정합니다.
- UART 초기화
- MX_USART1_UART_Init(): UART1를 115200 보드레이트, 8비트 데이터 길이, 1비트 정지 비트, 패리티 비트 없음 등으로 설정합니다. UART 통신을 위해 FIFO 모드와 고급 기능도 설정합니다.
- 스위치 상태 확인 및 데이터 전송
- 각 스위치(GPIO 핀)의 상태를 확인합니다. 스위치가 눌리면 해당 비트를 데이터 배열의 마지막 바이트에 설정합니다.
- 모든 스위치 상태를 확인한 후, 데이터 배열을 UART를 통해 전송합니다.
- LED 제어
- 하나 이상의 스위치가 눌린 경우 LED를 켭니다. 모든 스위치가 눌리지 않은 경우 LED를 끕니다.
- 디바운싱
- 짧은 지연(HAL_Delay(50))을 추가하여 스위치 디바운싱을 처리합니다.
코드 실행 흐름
- 초기화 단계
- HAL 라이브러리를 초기화하고 시스템 클럭과 주변 장치를 설정합니다.
- 무한 루프
- GPIO 핀을 읽어 스위치 상태를 확인합니다.
- 스위치 상태에 따라 데이터를 설정하고, UART를 통해 전송합니다.
- 스위치 상태에 따라 LED를 제어합니다.
- 디바운싱을 위해 짧은 지연을 추가합니다.
UART 485 결과 및 검증
특이사항
UART 설계 실수로 반대 설계해서 TX RX Swapping (switching 해둠)
+ 설계 초기 실수해서 10핀 핀헤더 거꾸로 달아서 아래로 달아야함
반응형