Notice
Recent Posts
Recent Comments
Link
승코딩당당당
[TC275] 4자리 FND 카운터 구현하기 (스위치 제어) 본문
이번 실습에서는 TC725 보드에서 GPIO를 이용해 4자리 FND(7-Segment) 디스플레이를 제어하는 카운터 시스템을 구현한다. 하드웨어 SPI 모듈을 사용하는 대신, SCLK·RCLK·DIO 핀을 직접 제어하는 비트뱅잉(Bit-Banging) 방식의 소프트웨어 SPI로 데이터를 전송하도록 구성하였다.
카운터 값은 0부터 9999까지 증가하며, 각 자리 숫자는 _LED_0F[] 배열을 통해 7-Segment 패턴으로 변환된다. 4자리 FND는 멀티플렉싱 방식으로 동작하며, send_port() 함수를 통해 자리 선택 신호와 세그먼트 데이터를 순차적으로 출력하여 사람이 보기에 동시에 켜진 것처럼 보이도록 구현하였다.
또한 두 개의 스위치를 이용해 동작을 제어한다.
- SW1 : 카운터 시작 / 정지 토글 (하강 에지 검출 방식)
- SW2 : 카운터 값 리셋
스위치 입력은 이전 상태(prevSw1, prevSw2)와 현재 상태를 비교하는 방식으로 에지를 검출하여, 단순 폴링 구조에서도 정확한 토글 동작이 이루어지도록 설계하였다.
이번 실습을 통해 다음 내용을 함께 정리할 수 있다.
- GPIO 기반 소프트웨어 SPI 구현 방식
- 7-Segment(FND) 멀티플렉싱 동작 원리
- 스위치 에지 검출(Edge Detection) 기법
- Start/Stop/Reset 제어 로직 설계
코드 (Cpu0_Main.c)

/**********************************************************************************************************************
* \file Cpu0_Main.c
* \copyright Copyright (C) Infineon Technologies AG 2019
*
* Use of this file is subject to the terms of use agreed between (i) you or the company in which ordinary course of
* business you are acting and (ii) Infineon Technologies AG or its licensees. If and as long as no such terms of use
* are agreed, use of this file is subject to following:
*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and
* accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute,
* and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the
* Software is furnished to do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including the above license grant, this restriction
* and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all
* derivative works of the Software, unless such copies or derivative works are solely in the form of
* machine-executable object code generated by a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*********************************************************************************************************************/
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "IfxStm.h"
#include "IfxCpu_Irq.h"
#include "IfxPort.h"
#include "IfxPort_PinMap.h"
// SPI port define
#define SCLK IfxPort_P00_0
#define RCLK IfxPort_P00_1
#define DIO IfxPort_P00_2
// Switch 핀 정의
#define SW1 IfxPort_P02_0 // 시작 / 정지 토글
#define SW2 IfxPort_P02_1 // 리셋
uint8 _LED_0F[10] = {0xC0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
void initGPIO(void);
void send(uint8 X);
void send_port(uint8 X, uint8 port);
IfxCpu_syncEvent cpuSyncEvent = 0;
void core0_main(void)
{
IfxCpu_enableInterrupts();
/* !!WATCHDOG0 AND SAFETY WATCHDOG ARE DISABLED HERE!!
* Enable the watchdogs and service them periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
IfxScuWdt_disableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
/* Wait for CPU sync event */
IfxCpu_emitEvent(&cpuSyncEvent);
IfxCpu_waitEvent(&cpuSyncEvent, 1);
initGPIO();
int n = 0;
uint8 run = 0;
uint8 prevSw1 = 1;
uint8 prevSw2 = 1;
while(1)
{
// 스위치 입력 처리
uint8 curSw1 = IfxPort_getPinState(SW1.port, SW1.pinIndex); // 1: not pressed, 0: pressed
uint8 curSw2 = IfxPort_getPinState(SW2.port, SW2.pinIndex);
// SW1: HIGH -> LOW
if ((prevSw1 == 1u) && (curSw1 == 0u))
{
run ^= 1u; // 0->1, 1->0
}
// SW2: 하강 에지에서 카운터 리셋
if ((prevSw2 == 1u) && (curSw2 == 0u))
{
n = 0;
}
prevSw1 = curSw1;
prevSw2 = curSw2;
// 현재 값 FND에 표시
int n1 = n % 10;
int n2 = (n % 100) / 10;
int n3 = (n % 1000) / 100;
int n4 = (n % 10000) / 1000;
for (int i = 0; i < 50; i++)
{
send_port(_LED_0F[n1], 0x1);
send_port(_LED_0F[n2], 0x2);
send_port(_LED_0F[n3], 0x4);
send_port(_LED_0F[n4], 0x8);
}
// 카운터 증가 (run==1일 때만)
if (run != 0u)
{
n++;
if (n > 9999)
n = 0;
}
}
}
void initGPIO(void)
{
// SPI 핀 출력 설정
IfxPort_setPinModeOutput(
SCLK.port,
SCLK.pinIndex,
IfxPort_OutputMode_pushPull,
IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(
RCLK.port,
RCLK.pinIndex,
IfxPort_OutputMode_pushPull,
IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(
DIO.port,
DIO.pinIndex,
IfxPort_OutputMode_pushPull,
IfxPort_OutputIdx_general);
// 초기 Low 설정
IfxPort_setPinLow(SCLK.port, SCLK.pinIndex);
IfxPort_setPinLow(RCLK.port, RCLK.pinIndex);
IfxPort_setPinLow(DIO.port, DIO.pinIndex);
// 스위치 입력 설정
IfxPort_setPinModeInput(
SW1.port,
SW1.pinIndex,
IfxPort_InputMode_pullUp);
IfxPort_setPinModeInput(
SW2.port,
SW2.pinIndex,
IfxPort_InputMode_pullUp);
}
void send(uint8 X)
{
for (int i = 8; i >= 1; i--)
{
if (X & 0x80)
IfxPort_setPinHigh(DIO.port, DIO.pinIndex);
else
IfxPort_setPinLow(DIO.port, DIO.pinIndex);
X <<= 1;
IfxPort_setPinLow(SCLK.port, SCLK.pinIndex);
IfxPort_setPinHigh(SCLK.port, SCLK.pinIndex);
}
}
void send_port(uint8 X, uint8 port)
{
send(X);
send(port);
IfxPort_setPinLow(RCLK.port, RCLK.pinIndex);
IfxPort_setPinHigh(RCLK.port, RCLK.pinIndex);
}
결과
아래 SW1을 눌렀을 때 On/Off가 가능하고, 위 SW2를 눌렀을 때 0으로 리셋되는 것을 확인할 수 있다.
'개발 > 임베디드' 카테고리의 다른 글
| [최적화] 임베디드 C 코드 최적화 전략 정리 (1) | 2026.03.03 |
|---|---|
| [메모리 구조] 변수 선언 방식에 따른 메모리 영역 확인 (0) | 2026.02.26 |
| [TC275] STM 인터럽트 기반 신호등 구현하기 (1) | 2026.02.23 |
| [TC275] 인터럽트로 LED Blinking과 멈추기 (0) | 2026.02.20 |
| [TC275] Multi-interrupt로 LED 제어 (Blue/Red) (0) | 2026.02.20 |
