[임베디드 18강] FND 제어

강지원·2024년 7월 18일

STM32 강의

목록 보기
18/33

1. FND 모듈

: 메인 칩 + 필요한 최소한의 회로

쪽보드라고도 한다
뒷면을 확인해 보면 메인 칩이 2개 있음

메인칩(TM74HC595) + 7세그먼트

1.1 TM74HC595

메인칩 없이 7세그먼트를 다루려면 LED를 제어한 것처럼 하나당 한 개의 GPIO를 연결하여 제어해야한다
-> 7세그먼트 하나 당 GPIO 8개가 필요

LCD 드라이버(메인칩)과 7세그먼트와 연결하고 LCD 드라이버와 칩이 통신해서 사용하는 GPIO를 줄일 수 있다.

1.2 모듈 작동 방법 찾기

데이터시트 2개를 찾아야 한다
1. 메인칩 데이터시트
2. 모듈 자체에 대한 데이터시트(없는 경우가 많다)

데이터 시트 내용 확인

동작 온도, 동작 전원, ...
SPI 통신 (다음시간에 공부하고 다룰예정이다)

SCLK : Input pin latch clock
RCLK
QA,QB,QC, .. : FND에 연결되어 있는 핀

샘플코드를 통해 작동시켜서 이해하기

데이터시트만 보고 동작시키기에는 너무 어려울 수 있다
샘플코드를 찾아서 동작시키면서 제어방법을 이해해 볼 예정이다

2. FND 모듈 회로 연결

3. 샘플코드 적용하기

3.1 GPIO 설정

SPI 통신을 이용하는 방법도 있지만 오늘은 GPIO로 설정해서 해볼 예정이다

3.2 파일 생성

fnd_controller.c : c파일
fnd_controller.h : 헤더파일

3.3 fnd_controller.c 코드 가져오기

1. fnd_controller.c에 fnd_controller.h 헤더파일 추가

#include "fnd_controller.h"

2. send 함수

원본 파일이 c++ 이여서 수정이 필요함

원본 파일(c++)
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);  
  }
}

수정내용

unsigned char -> uint8_t
digitalWrite(_DIO, HIGH) -> HAL_GPIO_WritePin(FND_DIO_GPIO_Port, FND_DIO_Pin, HIGH);

수정 후 적용

fnd_controller.c(c파일)

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);
	  }
}

위 코드 해석

보내고 싶은 8bit 데이터 X가 만약 0101 0010 이면

0x80 과 and 연산을 해서 1이 나오면 HIGH, 0이 나오면 LOW 보낸다
= 0x80 (1000 0000)

0101 0010 & 1000 0000 = 0000 0000 = 0

그 후 쉬프트 연산으로 왼쪽으로 1 미루고 다시 and 연산

1010 0100 & 1000 0000 = 1000 0000 = 128

원하는 데이터가 0101 0010 이면 LHLH LLHL 로 보내는 코드이다

SCLK 는 클럭을 만드는 것이다
LOW -> HIGH 로 올려주는 클럭을 만든다
기본적으로 HIGH를 유지하는 상태이다

원하는 데이터 세팅 후 클럭을 올림

FND에 적용

FND에 적용해서 생각하면 만약에
0을 만들고 싶으면 A,B,C,D,E,F 만 켜지면 된다
LED ON : LOW
LED OFF : HIGH

DPGFE DCBA
 1100 0000 : 0xC0

3. init_fnd() 함수

uint8_t _LED_0F[29];

void init_fnd(){
	  _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 -
}

4. send_port 함수

c에서는 함수 이름 중복이 되지 않아서 따로 이름을 변경해 줘야 함
-> 함수 이름을 변경하면 함수 적용한 부분도 인자 개수 확인해서 변경해줘야 한다

void send_port(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);
}

5. digit4 함수

void digit4_show(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++){
	 send_port(_LED_0F[n1], 0b0001);
    if(showZero | n>9)send_port(_LED_0F[n2], 0b0010);
    if(showZero | n>99)send_port(_LED_0F[n3], 0b0100);
    if(showZero | n>999)send_port(_LED_0F[n4], 0b1000);
 }
}

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

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

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

void digit4showZero(int n)
{
	digit4_show(n, 0, true);
}

6. digit2 함수

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++){
	   send_port(_LED_0F[n1], port);
	   send_port(_LED_0F[n2], port<<1);
   }
}

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

3.4 fnd_controller.h 코드 추가

1. fnd_controller.h 에 main.h 헤더파일 추가

main.h 에 fnd port, pin 이 정의되어 있으므로

#include "main.h"
main.h 파일
#define FND_RCLK_Pin GPIO_PIN_13
#define FND_RCLK_GPIO_Port GPIOB
#define FND_DIO_Pin GPIO_PIN_14
#define FND_DIO_GPIO_Port GPIOB
#define FND_SCLK_Pin GPIO_PIN_15
#define FND_SCLK_GPIO_Port GPIOB

2. 정의

#define HIGH 1
#define LOW 0

#define false 0
#define true 1

3. 함수 정의

void init_fnd();
void send(uint8_t X);
void send_port(uint8_t X, uint8_t port);
void digit4_show(int n, int replay, uint8_t showZero);
void digit4_replay (int n, int replay);
void digit4(int n);
void digit4showZero_replay(int n, int replay);
void digit4showZero(int n);
void digit2_replay(int n, int port, int replay);
void digit2(int n, int port);

4. main 함수에서 코드를 실행시켜보자

4.1 헤더파일 추가

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

4.2 init_fnd

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

4.3 실행 코드

(1) 1, 2번 칸에 0 ~ 99까지 표시

 while (1)
  {
	  for (int i = 0; i <= 99; i++) {

	  		digit2_replay(i, 0b0001, 50); //send counter 0-99 with delay 50 cicles int 1st and 2nd view ports

	  	}
   }

(2) 1, 2번 칸에 0 ~ 100까지 표시, 3, 4번 칸은 0으로 표시

for (int i = 0; i <= 100; i++) {
	 digit4showZero_replay(i, 50); //send counter 0-100 with delay 50 cicles with zero
}

(3) 1,2,3,4 번 칸에 0 ~ 9999까지 표시

for (int i = 0; i <= 9999; i++) {
	 digit4_replay(i, 50); //send counter 0-9999 with delay 50 cicles and hide zero
}

업로드중..

(4) A 표시

send_port(0x88, 0b0001);

업로드중..

0개의 댓글