[Embedded] FND 제어 기초(GPIO 사용)

강지원·2025년 3월 2일

STM32 강의

목록 보기
25/33

1. FND(7-segment)란?

Flexible Numeric Display의 약자로, LED를 사용하여 숫자 모양을 하나로 만들어 놓은 것이다.
7개의 LED를 아래와 같이 배치하고 그 몇개를 선택하여 조광함으로써 0 ~ 9까지를 표시할 수 있도록 한다.

7-segment

TIP. 처음 본 모듈 제어하기

  1. 메인칩 이름 확인(TM74HC595)
  2. 7-SEGMENT가 무엇인지 확인
  3. 웹에서 메인칩(TM74HC595)의 데이터시트 확인
  4. 모듈자체(4-BitLED Digital Tube Module)의 데이터시트 확인
  5. 샘플코드를 구해서, 일단 동작시키고, 그 후 코드분석

1) FND 모듈

모듈(쪽보드) = 메인 칩(드라이버)+ 필요한 최소한의 회로

FND 모듈
: TM74HC595 칩 2개(lcd 드라이버) + 7-segment

7-segment에 gpio를 하나씩 연결해서 제어할 수 있지만 gpio가 8개나 필요하다.
그래서 메인칩을 이용해서 7-segment를 제어하는 것이다.
업로드중..

메인칩(TM74HC595) 데이터시트 확인

  • SPI 통신
  • Shift 클럭 > 25MHz
  • 3.0V ~ 5.5V

2. 샘플코드 이용해서 구현하기

1) PIN 연결

원래는 SPI로 연결할 것이지만 일단 GPIO로 구현먼저 해볼 예정이다

2) SPI 통신

SCLK : 기본클럭
DIO : 기본클럭을 기준으로 원하는 곳에 클럭을 보내면 1 0 0 0 1 이런식으로 데이터를 보냄

STM32에서 SPI 통신을 지원해주지만 일단 이번에는 GPIO를 이용해서 구현할 예정이다.

3) 소스파일, 헤더파일 생성

4) 소스파일(fnd_controller.c) 구현

(1) send 코드

// 샘플코드
void TM74HC595Display::send(unsigned char X)
{

  for (int i = 8; i >= 1; i--)
  {
    if (X & 0x80)
    {
      digitalWrite(_DIO, HIGH);
    }
    else
    {
      digitalWrite(_DIO, LOW);
    }
    X <<= 1;
    digitalWrite(_SCLK, LOW);
    digitalWrite(_SCLK, HIGH);  
  }
}

적용코드

void send(uint8_t X){
	
	for (int i = 8; i >= 1; i--)
	  {
	    if (X & 0x80)
	    {
	      HAL_GPIO_WritePin(FND_DIO_GPIO_Port, FND_DIO_Pin, HIGH);
	    }
	    else
	    {
	    	HAL_GPIO_WritePin(FND_DIO_GPIO_Port, FND_DIO_Pin, LOW);
	    }
	    X <<= 1;
	    HAL_GPIO_WritePin(FND_SCLK_GPIO_Port, FND_SCLK_Pin, LOW);
	    HAL_GPIO_WritePin(FND_SCLK_GPIO_Port, FND_SCLK_Pin, HIGH); 
	  }
}

send 코드 해석

보내고 싶은 데이터 X (= 0x52 = 0101 0010)
X & 0x80(1000 0000)
: X의 첫번째 비트부터 and 연산해서 0이면 DIO = LOW, 1이면 DIO = HIGH

X를 쉬프트연산해서 2,3,4,...번째 비트 전부 비교한다.

SCLK는 HIGH 상태였다가, DIO로 데이터를 한비트씩 보낼때마다 SCLK가 LOW로 갔다가 HIGH로 돌아온다.(클럭을 만드는 것)

(2) 전체 적용소스코드

/*
 * fnd_controller.c
 *
 *  Created on: Mar 2, 2025
 *      Author: lnaur
 */
#include "fnd_controller.h"

uint8_t _LED_0F[29];

void fnd_init(){
	_LED_0F[0] = 0xC0; //0
	_LED_0F[1] = 0xF9; //1
	_LED_0F[2] = 0xA4; //2
	_LED_0F[3] = 0xB0; //3
	_LED_0F[4] = 0x99; //4
	_LED_0F[5] = 0x92; //5
	_LED_0F[6] = 0x82; //6
	_LED_0F[7] = 0xF8; //7
	_LED_0F[8] = 0x80; //8
	_LED_0F[9] = 0x90; //9
	_LED_0F[10] = 0x88; //A
    _LED_0F[11] = 0x83; //b
	_LED_0F[12] = 0xC6; //C
	_LED_0F[13] = 0xA1; //d
	_LED_0F[14] = 0x86; //E
	_LED_0F[15] = 0x8E; //F
	_LED_0F[16] = 0xC2; //G
	_LED_0F[17] = 0x89; //H
	_LED_0F[18] = 0xF9; //I
	_LED_0F[19] = 0xF1; //J
	_LED_0F[20] = 0xC3; //L
	_LED_0F[21] = 0xA9; //n
	_LED_0F[22] = 0xC0; //O
	_LED_0F[23] = 0x8C; //P
	_LED_0F[24] = 0x98; //q
	_LED_0F[25] = 0x92; //S
	_LED_0F[26] = 0xC1; //U
	_LED_0F[27] = 0x91; //Y
	_LED_0F[28] = 0xFE; //hight -
}

void send(uint8_t X){

	for (int i = 8; i >= 1; i--)
	  {
	    if (X & 0x80)
	    {
	      HAL_GPIO_WritePin(FND_DIO_GPIO_Port, FND_DIO_Pin, HIGH);
	    }
	    else
	    {
	    	HAL_GPIO_WritePin(FND_DIO_GPIO_Port, FND_DIO_Pin, LOW);
	    }
	    X <<= 1;
	    HAL_GPIO_WritePin(FND_SCLK_GPIO_Port, FND_SCLK_Pin, LOW);
	    HAL_GPIO_WritePin(FND_SCLK_GPIO_Port, FND_SCLK_Pin, HIGH);
	  }
}

void send2(uint8_t X, uint8_t port)
{
  send(X);
  send(port);
  HAL_GPIO_WritePin(FND_RCLK_GPIO_Port, FND_RCLK_Pin, LOW);
  HAL_GPIO_WritePin(FND_RCLK_GPIO_Port, FND_RCLK_Pin, HIGH);
}

void digit4(int n, int replay, uint8_t showZero)
{
  int n1, n2, n3, n4;
  n1 = (int)  n % 10;
  n2 = (int) ((n % 100)-n1)/10;
  n3 = (int) ((n % 1000) - n2 - n1) / 100;
  n4 = (int) ((n % 10000) - n3 - n2 - n1) / 1000;

 for(int i = 0; i<=replay; i++){
	send2(_LED_0F[n1], 0b0001);
    if(showZero | n>9)send2(_LED_0F[n2], 0b0010);
    if(showZero | n>99)send2(_LED_0F[n3], 0b0100);
    if(showZero | n>999)send2(_LED_0F[n4], 0b1000);
 }
}

void digit4_replay(int n, int replay)
{
  digit4(n,replay,false);
}

void digit4_0(int n)
{
  digit4(n,0,false);
}

void digit4showZero_replay(int n, int replay)
{
	digit4(n, replay, true);
}

void digit4showZero_0(int n)
{
	digit4(n, 0, true);
}

void digit2_replay(int n, int port, int replay)
{
  int n1, n2;
  n1 = (int)  n % 10;
  n2 = (int) ((n % 100)-n1)/10;

   for(int i = 0; i<=replay; i++){
   send2(_LED_0F[n1], port);
   send2(_LED_0F[n2], port<<1);
   }
}

void digit2_0(int n, int port)
{
	digit2_replay(n, port, 0);
}

5) 헤더파일(fnd_controller.h) 구현

/*
 * fnd_controller.h
 *
 *  Created on: Mar 2, 2025
 *      Author: lnaur
 */

#ifndef SRC_FND_CONTROLLER_H_
#define SRC_FND_CONTROLLER_H_

#include "main.h"

#define HIGH 1
#define LOW 0

#define true 1
#define false 0

void fnd_init();
void send(uint8_t X);
void send2(uint8_t X, uint8_t port);
void digit4(int n, int replay, uint8_t showZero);
void digit4_replay(int n, int replay);
void digit4_0(int n);
void digit4showZero_replay(int n, int replay);
void digit4showZero_0(int n);
void digit2_replay(int n, int port, int replay);
void digit2_0(int n, int port);

#endif /* SRC_FND_CONTROLLER_H_ */

3. main 코드에서 동작시키기

1) fnd_controller.h 헤더파일 정의

/* USER CODE BEGIN Includes */
#include "fnd_controller.h"
/* USER CODE END Includes */

2) while()안에서 코드 작동

(1) 1,2번 포트에서 0 ~ 99까지 50번 replay로 보여줌

-> while(1) 문이여서 계속 돌아감

while (1)
    {
    	fnd_init();

    	for (int i = 0; i <= 99; i++) {
    		digit2_replay(i, 0b0001, 50);
    	}
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
    }

(2) 1~4번 포트 0표시, 0~9999까지 표시

for (int i = 0; i <= 9999; i++) {
    digit4showZero_replay(i, 50); 
}

(3) 내 생일 표시

fnd_init();

send2(0xC0,0b1000);
send2(0x80,0b0100);
send2(0xC0,0b0010);
send2(0xF8,0b0001);

업로드중..

0개의 댓글