본문 바로가기
임베디드 개발/STM32 (ARM Cortex-M)

STM32 , 디지털 금고 프로그래밍으로 구현 ( 시프트 레지스터 응용 )

by eteo 2022. 5. 24.

 

시프트 레지스터를 응용한 디지털 금고를 프로그래밍으로 구현하였습니다.

 

올바른 비밀번호인 3190을 순서대로 입력하면 LED가 오른쪽 왼쪽으로 번갈아 이동하면서 켜지고, 틀린 번호를 입력하면 LED가 깜빡이면서 초기화 되서 다시 입력해야 합니다.

 

 

 

 

 

버튼 3, 1, 9, 0 은 PG0-3 과 연결해두었고

버튼 2, 4, 5, 6, 7, 8 은 PC7-12 와 연결해두었다.

LED는 PD0-5 이다.

 

 

D 플립플롭은 입력과 출력이 버퍼와 마찬가지이다. 시프트 레지스터라서 처음 입력이 1으로 고정이고 각 플립플롭의 출력 Qa, Qb, Qc, Qd의 값은 0으로 초기화된 상태에서 시작하기 때문에 올바른 순서대로 클락펄스를 주어야 비트 1이 이동한다.

 

 

 

 

소스코드

/* USER CODE BEGIN PFP */
void JKflipflopR(uint8_t J, uint8_t K, uint8_t Pulse, uint8_t *Q);
/* USER CODE END PFP */

 

이전 글에서 사용한 JKflipflopR 함수를 다시사용했다. 함수의 원형

 

 

 

  /* USER CODE BEGIN 2 */
  uint8_t Q[4] = {0,};

 

변수선언 부분

클락펄스를 버튼으로 받으니까 굳이 예전 클락펄스의 상태를 기억할 필요가 없어서 이전글에서 만든 JKFF 구조체 안쓰고, 그냥 1바이트 배열로 만들었다.

 

 

 

 

 

  /* USER CODE BEGIN WHILE */
  while (1)
  {

	  JKflipflopR(1, 0, HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_1), &Q[0]);
	  JKflipflopR(Q[0], !Q[0], HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_0), &Q[1]);
	  JKflipflopR(Q[1], !Q[1], HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_2), &Q[2]);
	  JKflipflopR(Q[2], !Q[2], HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_3), &Q[3]);


	  if((GPIOC->IDR & 0x1f80) != 0){
		  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, 1);	// buzzer on
		  for(int i=0; i<2; i++){
			  GPIOC->ODR |= 0x40;
			  GPIOD->ODR |= 0x3f;
			  HAL_Delay(100);
			  GPIOD->ODR &= ~(0x3f);
			  GPIOC->ODR &= ~(0x40);
			  HAL_Delay(100);
		  }
		  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, 0);	// buzzer off
		  for(int i=0; i<4; i++){
			  Q[i] = 0;
		  }
	  }


	  if(Q[3]){
		  int i;
		  for(i=0; i<6; i++){
			  GPIOD->ODR |= (1<<i);
			  HAL_Delay(100);
			  GPIOD->ODR &= ~(0x3f);
		  }
		  for(; i>0;i--){
			  GPIOD->ODR |= (1<<i);
			  HAL_Delay(100);
			  GPIOD->ODR &= ~(0x3f);
		  }
		  for(int i=0; i<4; i++){
			  Q[i] = 0;
		  }
	  }

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

while문 내

 

3, 1, 9, 0 과 연결된 핀의 상태를 읽어서 플립플롭을 호출하며 그 클락펄스로 주는 부분.

 

3, 1, 9, 0 을 제외한 다른 번호가 눌러졌을 때 부저를 울리고 LED를 두번 껐다 키고 Q값을 다 0으로 초기화하는 부분.

 

올바른 순서 대로 비밀번호를 입력해, 마지막 플립플롭의 출력으로 1이 나왔을때 LED를 왼쪽 오른쪽 번갈아 이동하며 Q값을 0으로 초기화하는 부분.

 

이렇게 3가지로 구성된다. 

 

스위치는 풀다운 저항으로 연결했으며 상승엣지 플립플롭을 써서 스위치가 눌렸을 때만 각 플립플롭의 출력으로 이동한다.

 

 

 

 

 

void JKflipflopR(uint8_t J, uint8_t K, uint8_t Pulse, uint8_t *Q){
	static uint8_t clockbefore = 0;

	if(Pulse == 1 && clockbefore == 0){
		if(J==1 && K==1){
			*Q ^= 1;
		}else if(J==0 && K==1){
			*Q = 0;
		}else if(J==1 && K==0){
			*Q = 1;
		}
	}
	clockbefore = Pulse;
}

JKflipflopR 함수의 정의