[Embedded] SPI 통신으로 FND 제어하기

강지원·2025년 3월 14일

STM32 강의

목록 보기
27/33

1. FND로 온도 표현하기

FND_controller.c

/*
 * 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_temper(int n, int replay)
{
  int n1, n2, n3, n4;
  n1 = (int)  n % 10;
  n2 = (int) (n % 100)/10;
  n3 = (int) (n % 1000)/100;
  n4 = (int) (n % 10000)/1000;

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

digit_temper를 사용해서 FND에 온도형식을 표현할 것이다.

main.c

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

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */


    while (1)
    {
    	for(int i=0;i<9999;i++){
    		digit4_temper(i,50);
    	}

    /* USER CODE END WHILE */

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

소수점 자리를 표시해서 온도표현을 할 수 있게 되었다.

2. SPI 통신 설정

1) 핀 설정

SPI2 를 Transmit only master로 설정하면 MOSI(PB15)와 SCK(PB13)이 자동으로 설정된다. PB14는 GPIO OUTPUT으로 설정해주고 RCLK로 설정해주면 된다.

PB14 설정

2) SPI 설정

데이터시트를 확인해 보면 상승 엣지(2엣지)로 설정하라고 나와 있기 때문에 2Edge로 설정해준다.

3) 코드 수정

fnd_controller.c 의 send 함수(원본)

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

수정본

HAL_SPI_Transmit(hspi, pData, Size, Timeout);

위 코드를 사용하기 위해서는 핸들러 설정을 해주어야 한다.

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

uint8_t _LED_0F[29];

static SPI_HandleTypeDef* mhspi;

void fnd_init(SPI_HandleTypeDef * hspi){

	mhspi = hspi;
	_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){
	HAL_SPI_Transmit(mhspi, &X, 1, 100);
}

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_temper(int n, int replay)
{
  int n1, n2, n3, n4;
  n1 = (int)  n % 10;
  n2 = (int) (n % 100)/10;
  n3 = (int) (n % 1000)/100;
  n4 = (int) (n % 10000)/1000;

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

4) main.c 코드 작동

/* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI2_Init();
  /* USER CODE BEGIN 2 */
  fnd_init(&hspi2);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

    while (1)
    {
    	for(int i=0;i<9999;i++){
    		digit4_temper(i,50);
    	}

    /* USER CODE END WHILE */

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

0개의 댓글