반응형

https://youtube.com/live/Iz-1TaHBU88

[STM32#13] FND모듈인 TM1637을 STM32f103rb nucleo에 연결해서 디스플레이에 다양한 센서값 출력하는 방법 알아보기!(녹칸다 내맘대로 STM32)

심심한녹칸다의 내맘대로 STM32시리즈이다!

STM32시리즈의 모든 자료는 구글 슬라이드에 작성하고 모두에게 공유되어있음!
https://docs.google.com/presentation/d/1myA5iYbjuKsLWLqtRLKAiRfwUwvqB1d1RGjiMIIgp3I/edit?slide=id.g3a8e99eac0a_1_8#slide=id.g3a8e99eac0a_1_8

이번편은 FND모듈인 TM1637입니다~!

(필수추가코드)

#define delay_ms HAL_Delay
#define SYS_CLOCK    64
#define SYSTICK_LOAD 63999
uint32_t millis_cnt = 0;
uint32_t millis() {
 return millis_cnt;
}
uint32_t micros() {
 return (millis_cnt & 0x3FFFFF) * 1000 + (SYSTICK_LOAD - SysTick->VAL) / SYS_CLOCK;
}
void delay_us(uint32_t us) {  // 64MHz 보정
 if (us > 1) {
   uint32_t count = us * 7 - 6;
   while (count--);
 } else {
   uint32_t count = 2;
   while (count--);
 }
}
// TM1637 7세그먼트 숫자 코드 매핑
const char segmentMap[] = {
   0x3f, 0x06, 0x5b, 0x4f,
   0x66, 0x6d, 0x7d, 0x07,
   0x7f, 0x6f, 0x77, 0x7c,
   0x39, 0x5e, 0x79, 0x71,
   0x00
};
// GPIOB 클럭 활성화 매크로
#define PORTB_CLK_ENABLE() (RCC->APB2ENR |= RCC_APB2ENR_IOPBEN)
// PB8, PB9 핀 사용 (GPIOB)
// PB8 = CLK, PB9 = DIO
// CLK와 DIO 핀 제어 함수
static inline void _tm1637ClkHigh(void) { GPIOB->BSRR = (1 << 8); } // CLK HIGH
static inline void _tm1637ClkLow(void)  { GPIOB->BRR = (1 << 8); }  // CLK LOW
static inline void _tm1637DioHigh(void) { GPIOB->BSRR = (1 << 9); } // DIO HIGH
static inline void _tm1637DioLow(void)  { GPIOB->BRR = (1 << 9); }  // DIO LOW
// 마이크로초 단위 딜레이
void _tm1637DelayUsec(unsigned int i)
{
	delay_us(i); // 사용자 정의 delay_us 함수 사용
}
// TM1637 초기화 함수 (GPIO 출력 설정)
void tm1637Init(void)
{
   PORTB_CLK_ENABLE(); // GPIOB 클럭 활성화
   // GPIOB CRH 초기화 (PB8, PB9 출력 2MHz Push-Pull)
   GPIOB->CRH &= ~((0xF << 0) | (0xF << 4)); // 해당 비트 클리어
   GPIOB->CRH |= (0x2 << 0); // PB8: MODE=10(출력 2MHz), CNF=00(Push-Pull)
   GPIOB->CRH |= (0x2 << 4); // PB9: MODE=10(출력 2MHz), CNF=00(Push-Pull)
   tm1637SetBrightness(8); // 밝기 최대
}

// TM1637 시작 신호
void _tm1637Start(void)
{
   _tm1637ClkHigh();
   _tm1637DioHigh();
   _tm1637DelayUsec(20);
   _tm1637DioLow(); // START 조건: DIO LOW
}
// TM1637 종료 신호
void _tm1637Stop(void)
{
   _tm1637ClkLow();
   _tm1637DelayUsec(20);
   _tm1637DioLow();
   _tm1637DelayUsec(20);
   _tm1637ClkHigh();
   _tm1637DelayUsec(20);
   _tm1637DioHigh(); // STOP 조건: DIO HIGH
}
// TM1637 ACK 무시 (결과 확인용)
void _tm1637ReadResult(void)
{
   _tm1637ClkLow();
   _tm1637DelayUsec(50);
   // DIO 상태 확인, ACK 처리 (여기서는 실제 확인 없이 무시)
   _tm1637ClkHigh();
   _tm1637DelayUsec(20);
   _tm1637ClkLow();
}

// TM1637 1바이트 전송
void _tm1637WriteByte(unsigned char b)
{
   for (int i = 0; i < 8; ++i) {
       _tm1637ClkLow();
       if (b & 0x01) {
           _tm1637DioHigh();
       } else {
           _tm1637DioLow();
       }
       _tm1637DelayUsec(30);
       b >>= 1; // 다음 비트로 이동
       _tm1637ClkHigh();
       _tm1637DelayUsec(30);
   }
}
// 밝기 설정 (0~8, 0 = 꺼짐)
void tm1637SetBrightness(char brightness)
{
   _tm1637Start();
   _tm1637WriteByte(0x87 + brightness); // 밝기 명령어
   _tm1637ReadResult();
   _tm1637Stop();
}

// 4자리 10진수 표시 (displaySeparator=1이면 3번째 자리 점 켬)
void tm1637DisplayDecimal(int v, int displaySeparator)
{
   unsigned char digitArr[4];
   int isNegative = 0;
   if (v < 0) {
       isNegative = 1;
       v = -v;
   }
   // 숫자를 segmentMap으로 변환
   for (int i = 0; i < 4; ++i) {
       digitArr[i] = segmentMap[v % 10];
       if (i == 2 && displaySeparator) {
           digitArr[i] |= 1 << 7; // 점(DP) 켬
       }
       v /= 10;
   }
   // 음수 표시
   if (isNegative) {
       digitArr[3] = 0x40; // '-' 표시
   }
   // TM1637에 데이터 전송
   _tm1637Start();
   _tm1637WriteByte(0x40); // 자동 주소 증가 모드
   _tm1637ReadResult();
   _tm1637Stop();
   _tm1637Start();
   _tm1637WriteByte(0xc0); // 시작 주소 0
   _tm1637ReadResult();
   for (int i = 0; i < 4; ++i) {
       _tm1637WriteByte(digitArr[3 - i]); // 3->0 순서로 전송
       _tm1637ReadResult();
   }
   _tm1637Stop();
}

// 4자리 10진수 표시 (앞자리 0 제거, displaySeparator=1이면 점 켬)
void tm1637DisplayDecimalTrim(int v, int displaySeparator)
{
   unsigned char digitArr[4];
   int isNegative = 0;
   if (v < 0) {
       isNegative = 1;
       v = -v;
   }
   // 숫자를 segmentMap으로 변환
   for (int i = 0; i < 4; ++i) {
       digitArr[i] = segmentMap[v % 10];
       if (i == 2 && displaySeparator) {
           digitArr[i] |= 1 << 7; // 점(DP) 켬
       }
       v /= 10;
   }
   // 앞자리 0 제거 (공백 처리)
   int leadingZero = 1;
   for (int i = 3; i >= 0; --i) {
       if (digitArr[i] != segmentMap[0] || i == 0) {
           leadingZero = 0;
       }
       if (leadingZero && digitArr[i] == segmentMap[0]) {
           digitArr[i] = 0x00; // 공백
       }
   }

   // 음수 표시
   if (isNegative) {
       digitArr[3] = 0x40; // '-'
   }
   // TM1637에 데이터 전송
   _tm1637Start();
   _tm1637WriteByte(0x40); // 자동 주소 증가 모드
   _tm1637ReadResult();
   _tm1637Stop();
   _tm1637Start();
   _tm1637WriteByte(0xC0); // 시작 주소 0
   _tm1637ReadResult();
   for (int i = 0; i < 4; ++i) {
       _tm1637WriteByte(digitArr[3 - i]); // 3->0 순서로 전송
       _tm1637ReadResult();
   }
   _tm1637Stop();
}
void tm1637SetRawSegment(uint8_t position, uint8_t segData)
{
   // 주소 범위 보호
   if (position > 3) return;
   _tm1637Start();
   _tm1637WriteByte(0x40);      // 데이터 입력 모드
   _tm1637ReadResult();
   _tm1637Stop();
   _tm1637Start();
   _tm1637WriteByte(0xC0 + position);   // 자리 선택
   _tm1637ReadResult();
   _tm1637WriteByte(segData);           // 세그먼트 데이터 전송
   _tm1637ReadResult();
   _tm1637Stop();
}

 

 

1.참고코드를 프로젝트에 반영하고 TM1637화면에 123이라고 출력하는데 2종류의 함수를 각각 사용해서 결과를 확인하시오!

/* USER CODE BEGIN 2 */
 //TM1637 시작~
 tm1637Init();
 //원하는 숫자 출력
 tm1637DisplayDecimal(123, 0);  //0123
 //tm1637DisplayDecimalTrim(123, 0);  //_123
 /* USER CODE END 2 */

/* USER CODE BEGIN 2 */
 //TM1637 시작~
 tm1637Init();
 //원하는 숫자 출력
 //tm1637DisplayDecimal(123, 0);  //0123
 tm1637DisplayDecimalTrim(123, 0);  //_123
 /* USER CODE END 2 */


2.TM1637에 0.1초 간격으로 1씩 업카운트를 하는데, tm1637DisplayDecimalTrim함수를 이용해서 출력하시오!(0~9999까지만 출력하시오)

/* USER CODE BEGIN 2 */
 //TM1637 시작~
 tm1637Init();
 int cnt = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  tm1637DisplayDecimalTrim(cnt, 0);
	  cnt++;
	  //cnt가 9999를 초과하면 다시 0으로 초기화한다!
	  if(cnt > 9999) cnt = 0;
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


3.예제2와 동일한데, 0부터 출발해서 음의 방향으로 1씩 다운카운트를하고 (-999 ~ 0)

/* USER CODE BEGIN 2 */
 //TM1637 시작~
 tm1637Init();
 int cnt = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  tm1637DisplayDecimalTrim(cnt, 0);
	  cnt--;
	  //cnt가 -999를 미만이 되면 0으로 초기화한다!
	  if(cnt < -999) cnt = 0;
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


4.tm1637SetRawSegment함수를 이용해서 왼쪽부터 1번 FND는 0b0001자리만 ON하고, 2번은 0b0010만 ON하고, 3번은 0b0100만 ON하고 4번은 0b1000만 ON하도록 하시오!

/* USER CODE BEGIN 2 */
 //TM1637 시작~
 tm1637Init();
 tm1637SetRawSegment(0,0b0001);
 tm1637SetRawSegment(1,0b0010);
 tm1637SetRawSegment(2,0b0100);
 tm1637SetRawSegment(3,0b1000);
 /* USER CODE END 2 */


5.이번에는 숫자패턴은 출력하지말고 4개의 FND의 소수점을 표시하는 dp만 모조리 다 출력하시오!

/* USER CODE BEGIN 2 */
 //TM1637 시작~
 tm1637Init();
 tm1637SetRawSegment(0,0b10000000);
 tm1637SetRawSegment(1,0b10000000);
 tm1637SetRawSegment(2,0b10000000);
 tm1637SetRawSegment(3,0b10000000);
 /* USER CODE END 2 */


6.TM1637에 붙은 FND4개의 테두리를 이용해서 시계방향으로 빙글빙글 돌아가는 듯한 효과를 연출하시오!

 

/* USER CODE BEGIN 2 */
 int nockanda_i = 0;
 uint8_t nockanda_array[][4] = {
	  {0b00000001, 0b00000000, 0b00000000, 0b00000000},
	  {0b00000000, 0b00000001, 0b00000000, 0b00000000},
	  {0b00000000, 0b00000000, 0b00000001, 0b00000000},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000001},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000010},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000100},
	  {0b00000000, 0b00000000, 0b00000000, 0b00001000},
	  {0b00000000, 0b00000000, 0b00001000, 0b00000000},
	  {0b00000000, 0b00001000, 0b00000000, 0b00000000},
	  {0b00001000, 0b00000000, 0b00000000, 0b00000000},
	  {0b00010000, 0b00000000, 0b00000000, 0b00000000},
	  {0b00100000, 0b00000000, 0b00000000, 0b00000000}
 };
 //TM1637 시작~
 tm1637Init();
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  for(int j = 0;j<4;j++){
		  tm1637SetRawSegment(j,nockanda_array[nockanda_i][j]);
	  }
	  nockanda_i++;
	  if(nockanda_i == 12) nockanda_i = 0;
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


7.PB1버튼을 누르면 예제6이 시계방향으로 회전하고, PA8을 누르면 반시계방향으로 회전하도록 하시오!

/* USER CODE BEGIN 2 */
 int nockanda_i = 0;
 uint8_t nockanda_array[][4] = {
	  {0b00000001, 0b00000000, 0b00000000, 0b00000000},
	  {0b00000000, 0b00000001, 0b00000000, 0b00000000},
	  {0b00000000, 0b00000000, 0b00000001, 0b00000000},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000001},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000010},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000100},
	  {0b00000000, 0b00000000, 0b00000000, 0b00001000},
	  {0b00000000, 0b00000000, 0b00001000, 0b00000000},
	  {0b00000000, 0b00001000, 0b00000000, 0b00000000},
	  {0b00001000, 0b00000000, 0b00000000, 0b00000000},
	  {0b00010000, 0b00000000, 0b00000000, 0b00000000},
	  {0b00100000, 0b00000000, 0b00000000, 0b00000000}
 };
 int direct = 0; //0이면 시계 1이면 반시계
 //TM1637 시작~
 tm1637Init();
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0){
		  direct = 0;
	  }
	  if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == 0){
		  direct = 1;
	  }
	  for(int j = 0;j<4;j++){
		  tm1637SetRawSegment(j,nockanda_array[nockanda_i][j]);
	  }
	  if(direct == 0){
		  nockanda_i++;
		  if(nockanda_i == 12) nockanda_i = 0;
	  }else if(direct == 1){
		  nockanda_i--;
		  if(nockanda_i == -1) nockanda_i = 11;
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


8.PB1버튼을 누르면 1씩 업카운트되고, PA8버튼을 누르면 1씩 다운카운트 되고, PB2를 누르면 0으로 초기화하시오!

/* USER CODE BEGIN 2 */
 //TM1637 시작~
 tm1637Init();
 int cnt = 0;
 //초기값 출력하기~
 tm1637DisplayDecimalTrim(cnt,0);
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0){
		  cnt++;
		  tm1637DisplayDecimalTrim(cnt,0);
		  HAL_Delay(300);//채터링방지
	  }
	  if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == 0){
		  cnt--;
		  tm1637DisplayDecimalTrim(cnt,0);
		  HAL_Delay(300);//채터링방지
	  }
	  if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == 0){
		  cnt = 0;
		  tm1637DisplayDecimalTrim(cnt,0);
		  HAL_Delay(300);//채터링방지
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


9.PA11과 PA12에 연결된 로터리 엔코더를 시계방향으로 돌리면 1씩 업카운트, 반시계방향으로 돌리면 1씩 다운카운트, PC7이 로터리엔코더 스위치인데 누르면 0으로 초기화하시오!

/* USER CODE BEGIN 2 */
 //TM1637 시작~
 tm1637Init();
 int cnt = 0;
 //초기값 출력하기~
 tm1637DisplayDecimalTrim(cnt,0);
 uint8_t old_rot_A = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_7) == 0){
		  cnt = 0;
		  tm1637DisplayDecimalTrim(cnt,0);
	  }
	  uint8_t now_rot_A = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
	  if(now_rot_A == 1 && old_rot_A == 0){
		  uint8_t now_rot_B = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_12);
		  if(now_rot_B){
			  //CCW
			  cnt--;
		  }else{
			  //CW
			  cnt++;
		  }
		  tm1637DisplayDecimalTrim(cnt,0);
	  }
	  old_rot_A = now_rot_A;
	  HAL_Delay(1);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


10.PA0에 연결된 12BIT 가변저항값을 TM1637에 그대로 출력하시오!

/* USER CODE BEGIN 2 */
 //TM1637 시작~
 tm1637Init();
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 uint16_t adc_value0 = 0;
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //측정할때마다 호출
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
		  tm1637DisplayDecimalTrim(adc_value0,0);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


11.예제10에서 측정한 가변저항값을 전압으로 환산해서 TM1637에 소수점을 포함해서 출력하시오!

/* USER CODE BEGIN 2 */
 //TM1637 시작~
 tm1637Init();
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 uint16_t adc_value0 = 0;
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //측정할때마다 호출
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
		  float voltage = 3.3*adc_value0/4095;
		  voltage = voltage * 100; //FND에 출력하기 위한 용도
		  tm1637DisplayDecimalTrim((int)voltage, 1);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


12.예제6번과 예제9번을 합쳐서 로터리엔코더를 돌리면 시계나 반시계방향으로 빙글빙글 돌아가는 효과를 연출하시오!

/* USER CODE BEGIN 2 */
 int nockanda_i = 0;
 uint8_t nockanda_array[][4] = {
	  {0b00000001, 0b00000000, 0b00000000, 0b00000000},
	  {0b00000000, 0b00000001, 0b00000000, 0b00000000},
	  {0b00000000, 0b00000000, 0b00000001, 0b00000000},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000001},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000010},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000100},
	  {0b00000000, 0b00000000, 0b00000000, 0b00001000},
	  {0b00000000, 0b00000000, 0b00001000, 0b00000000},
	  {0b00000000, 0b00001000, 0b00000000, 0b00000000},
	  {0b00001000, 0b00000000, 0b00000000, 0b00000000},
	  {0b00010000, 0b00000000, 0b00000000, 0b00000000},
	  {0b00100000, 0b00000000, 0b00000000, 0b00000000}
 };
 //초기패턴출력
 for(int j = 0;j<4;j++){
	  tm1637SetRawSegment(j,nockanda_array[0][j]);
 }
 //TM1637 시작~
 tm1637Init();
 uint8_t old_rot_A = 0;
/* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */

 while (1)
 {
	  uint8_t now_rot_A = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
	  if(now_rot_A == 1 && old_rot_A == 0){
		  uint8_t now_rot_B = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_12);
		  if(now_rot_B){
			  //CCW
			  //패턴이 반시계방향으로 1씩 움직인다
			  nockanda_i--;
			  if(nockanda_i == -1) nockanda_i = 11;
		  }else{
			  //CW
			  //패턴이 시계방향으로 1씩 움직인다
			  nockanda_i++;
			  if(nockanda_i == 12) nockanda_i = 0;
		  }
		  for(int j = 0;j<4;j++){
			  tm1637SetRawSegment(j,nockanda_array[nockanda_i][j]);
		  }
	  }
	  old_rot_A = now_rot_A;
	  HAL_Delay(1);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


13.로터리엔코더를 돌려서 0~10의 범위로 값을 결정하고, 스위치를 누르면 녹칸다쿠쿠가 밥을 짓기 시작하는데, 지정된 시간에서 1초마다 1씩 다운카운트된다! 시간이 0이되면 TM1637에 빙글빙글 돌아가는 패턴이 나오도록하시오! 밥이 다되면 부저에서 도레미파솔라시도가 LED가 빙글빙글 돌아가는 타이밍에 맞춰서 출력되도록 하시오! 

static void Tone(uint32_t Frequency)
{
   TIM3->ARR = (1000000UL / Frequency) - 1;
   TIM3->CCR3 = (TIM3->ARR >> 1);
}
static void noTone()
{
   TIM3->CCR3 = 0;
}
#define NOTE_C6  1047
#define NOTE_D6  1175
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_G6  1568
#define NOTE_A6  1760
#define NOTE_B6  1976
#define NOTE_C7  2093
uint8_t melody_i = 0;
uint16_t melody[] = {NOTE_C6,NOTE_D6,NOTE_E6,NOTE_F6,NOTE_G6,NOTE_A6,NOTE_B6,NOTE_C7};

/* USER CODE BEGIN 2 */
 int nockanda_i = 0;
 uint8_t nockanda_array[][4] = {
	  {0b00000001, 0b00000000, 0b00000000, 0b00000000},
	  {0b00000000, 0b00000001, 0b00000000, 0b00000000},
	  {0b00000000, 0b00000000, 0b00000001, 0b00000000},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000001},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000010},
	  {0b00000000, 0b00000000, 0b00000000, 0b00000100},
	  {0b00000000, 0b00000000, 0b00000000, 0b00001000},
	  {0b00000000, 0b00000000, 0b00001000, 0b00000000},
	  {0b00000000, 0b00001000, 0b00000000, 0b00000000},
	  {0b00001000, 0b00000000, 0b00000000, 0b00000000},
	  {0b00010000, 0b00000000, 0b00000000, 0b00000000},
	  {0b00100000, 0b00000000, 0b00000000, 0b00000000}
 };
 //초기패턴출력
 for(int j = 0;j<4;j++){
	  tm1637SetRawSegment(j,nockanda_array[0][j]);
 }
 //TM1637 시작~
 tm1637Init();
 uint8_t old_rot_A = 0;
 HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);
 uint8_t task_run = 0;
 uint8_t task_run2 = 0;
 uint32_t t = 0;

 int nockanda_cnt = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  if(task_run2){
		  if(HAL_GetTick() - t >= 100){
			  t = HAL_GetTick();
			  for(int j = 0;j<4;j++){
				  tm1637SetRawSegment(j,nockanda_array[nockanda_i][j]);
			  }
			  nockanda_i++;
			  if(nockanda_i == 12) nockanda_i = 0;
			  //부저 재생하기
			  Tone(melody[melody_i]);
			  melody_i++;
			  if(melody_i > 8) melody_i = 0;
		  }
	  }
	  if(task_run){
		  //task가 시작되면 1000밀리초 간격마다 걸리는 조건문
		  if(HAL_GetTick() - t >= 1000){
			  t = HAL_GetTick();
			  nockanda_cnt--;
			  tm1637DisplayDecimalTrim(nockanda_cnt,0);
			  if(nockanda_cnt == 0){
				  //탈출조건
				  task_run2 = 1;//LED빙글빙글 돌리는 작업
				  melody_i = 0;
				  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, 1); //부저ON
				  task_run = 0;
			  }
		  }
	  }

	  if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_7) == 0){
		  //카운트가 0보다 크면서 task가 실행중이 아니라면~
		  if(nockanda_cnt > 0 && task_run == 0 && task_run2 == 0){
			  task_run = 1;
		  }
		  task_run2 = 0; //스위치 누르면 종료
		  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, 0); //부저종료
		  HAL_Delay(300);
	  }
	  if(task_run2 == 0){
		  uint8_t now_rot_A = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
		  if(now_rot_A == 1 && old_rot_A == 0){
			  uint8_t now_rot_B = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_12);
			  if(now_rot_B){
				  //CCW
				  nockanda_cnt--;
				  if(nockanda_cnt < 0) nockanda_cnt = 0;
			  }else{
				  //CW
				  nockanda_cnt++;
				  if(nockanda_cnt > 10) nockanda_cnt = 10;
			  }
			  tm1637DisplayDecimalTrim(nockanda_cnt,0);
		  }
		  old_rot_A = now_rot_A;
		  HAL_Delay(1);
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }

 

반응형
Posted by 덕력킹
,