반응형

https://youtube.com/live/Pl1SAaUqfII

[STM32#32] 블루필보드로 전자산업기사, 임베디드기능사 국가자격증 실기시험 공개문제에 있는 일부 문제를 해결해보기!(녹칸다 내맘대로 STM32)

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

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

그냥 막 하면 재미 없으니 국가 자격증 시험에 있는 문제를 STM32로 접근해봅시당!

 

1.STM32의 PB9에 주파수발생기를 연결하고 PB8에 LED를 연결해서 주파수 발생기에서 엣지를 검출할때 마다 PB8의 LED가 토글되도록 하시오!

/* USER CODE BEGIN 0 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == GPIO_PIN_9)
  {
      HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);
  }
}
/* USER CODE END 0 */


2.주파수 발생기에서 나오는 신호를 검출해서 1씩 증가하는 카운터를 구성한다음 단위시간으로 나눠서 USB CDC로 출력하시오!

/* USER CODE BEGIN 0 */
volatile uint16_t cnt = 0;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == GPIO_PIN_9)
  {
	   //10ms초마다 1씩 증가
	   cnt++;
  }
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
 uint8_t buff[100];
 /* USER CODE END 2 */
while (1)
 {
	  //1초 간격으로 cnt값을 USB CDC로 출력하고 cnt를 0으로 초기화한다!
	  sprintf(buff,"now_cnt = %d\n",cnt);
	  CDC_Transmit_FS(buff, strlen(buff));
	  cnt = 0;
	  HAL_Delay(1000);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


3.예제2에서 측정한 주파수값을 1602LCD(PB6,PB7)에 형식에 맞게 출력하시오!

#define delay_ms HAL_Delay
#define SYS_CLOCK    72
#define SYSTICK_LOAD 72000-1
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--);
 }
}
#define ADDRESS   0x27<<1
#define RS1_EN1   0x05
#define RS1_EN0   0x01
#define RS0_EN1   0x04
#define RS0_EN0   0x00
#define BackLight 0x08
// RS-Q0 / RW-Q1 / EN-Q2 / BackLight-Q3 / D4-Q4 / D5-Q5 / D6-Q6 / D7-Q7
void LCD_DATA(uint8_t data) {
 uint8_t temp=(data & 0xF0)|RS1_EN1|BackLight;
 while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
 temp=(data & 0xF0)|RS1_EN0|BackLight;
 while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
 delay_us(4);
 temp=((data << 4) & 0xF0)|RS1_EN1|BackLight;
 while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
 temp = ((data << 4) & 0xF0)|RS1_EN0|BackLight;
 while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
 delay_us(50);
}
void LCD_CMD(uint8_t cmd) {
 uint8_t temp=(cmd & 0xF0)|RS0_EN1|BackLight;
 while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
 temp=(cmd & 0xF0)|RS0_EN0|BackLight;
 while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
 delay_us(4);
 temp=((cmd << 4) & 0xF0)|RS0_EN1|BackLight;
 while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
 temp=((cmd << 4) & 0xF0)|RS0_EN0|BackLight;
 while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
 delay_us(50);
}
void LCD_CMD_4bit(uint8_t cmd) {
 uint8_t temp=((cmd << 4) & 0xF0)|RS0_EN1|BackLight;
 while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
 temp=((cmd << 4) & 0xF0)|RS0_EN0|BackLight;
 while(HAL_I2C_Master_Transmit(&hi2c1, ADDRESS, &temp, 1, 1000)!=HAL_OK);
 delay_us(50);
}
void LCD_INIT(void) {
 delay_ms(100);
 LCD_CMD_4bit(0x03); delay_ms(5);
 LCD_CMD_4bit(0x03); delay_us(100);
 LCD_CMD_4bit(0x03); delay_us(100);
 LCD_CMD_4bit(0x02); delay_us(100);
 LCD_CMD(0x28);  // 4 bits, 2 line, 5x8 font
 LCD_CMD(0x08);  // display off, cursor off, blink off
 LCD_CMD(0x01);  // clear display
 delay_ms(3);
 LCD_CMD(0x06);  // cursor movint direction
 LCD_CMD(0x0C);  // display on, cursor off, blink off
}
void LCD_XY(char x, char y) {
 if      (y == 0) LCD_CMD(0x80 + x);
 else if (y == 1) LCD_CMD(0xC0 + x);
 else if (y == 2) LCD_CMD(0x94 + x);
 else if (y == 3) LCD_CMD(0xD4 + x);
}
void LCD_CLEAR(void) {
 LCD_CMD(0x01);
 delay_ms(2);
}
void LCD_PUTS(char *str) {
 while (*str) LCD_DATA(*str++);
}
/* USER CODE BEGIN 0 */
volatile uint16_t cnt = 0;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == GPIO_PIN_9)
  {
	   //10ms초마다 1씩 증가
	   cnt++;
  }
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
 uint8_t line1[20];
 uint8_t line2[20];
 LCD_INIT(); //1회호출(메인루프 시작전)
 LCD_XY(0, 0) ; LCD_PUTS("[Pulse Mode]    "); //첫번째줄
 /* USER CODE END 2 */
while (1)
 {
	  //1초간격으로 1602LCD에 출력한다!
	  sprintf(line2,"Freq: %3dHz     ",cnt);
	  LCD_XY(0, 1) ; LCD_PUTS(line2); //두번째줄
	  cnt = 0;
	  HAL_Delay(1000);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


4.전자산업기사 공개문제 2번에서 주파수발생기로 시계만드는 부분을 블루필보드로 해결하시오!

//(LCD코드는 생략)
/* USER CODE BEGIN 0 */
volatile uint16_t h = 11; //시
volatile uint16_t m = 59; //분
volatile uint16_t s = 50; //초
volatile uint16_t ms = 0; //밀리초
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == GPIO_PIN_9)
  {
	   //10ms초마다 1씩 증가
	   ms++;
	   if(ms >= 100){
		   ms = 0;
		   s++;
	   }
	   if(s >= 60){
		   s = 0;
		   m++;
	   }
	   if(m >= 60){
		   m = 0;
		   h++;
	   }
	   if(h >= 24){
		   h = 0;
	   }
  }
}

/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
 uint8_t line1[20];
 uint8_t line2[20];
 LCD_INIT(); //1회호출(메인루프 시작전)
 LCD_XY(0, 0) ; LCD_PUTS("[ DigitalClock ]"); //첫번째줄
 /* USER CODE END 2 */

while (1)
 {
	  //1초간격으로 1602LCD에 출력한다!
	  sprintf(line2,"Freq: %3dHz     ",cnt);
	  LCD_XY(0, 1) ; LCD_PUTS(line2); //두번째줄
	  cnt = 0;
	  HAL_Delay(1000);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }
while (1)
 {
	  //1초간격으로 1602LCD에 출력한다!
	  sprintf(line2,"[%s]%02d:%02d:%02d:%02d ",(h>=12)?"PM":"AM",h,m,s,ms);
	  LCD_XY(0, 1) ; LCD_PUTS(line2); //두번째줄
	  HAL_Delay(10);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


5.임베디드기능사에서 나오는 문제를 P6~P9까지를 PB6~PB9까지 연결 P10을 PB4, P11을 PB5에 연결해서 FND에 숫자 두자리(15)를 출력하시오!

/* USER CODE BEGIN 0 */
void set_fnd(uint8_t num){
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, num&0b0001); //하위
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, (num>>1)&0b0001);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, (num>>2)&0b0001);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, (num>>3)&0b0001); //상위
}
uint8_t fnd_num = 15;
uint8_t fnd_sw = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(fnd_sw == 0){
		//십의자리
		set_fnd(fnd_num/10);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 1);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);
		fnd_sw = 1;
	}else if(fnd_sw == 1){
		//일의자리
		set_fnd(fnd_num%10);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 0);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);
		fnd_sw = 0;
	}
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
 HAL_TIM_Base_Start_IT(&htim3);
/* USER CODE END 2 */


6.예제5에서 PB12,PB13에 버튼을 1개씩 추가하고 PB12버튼을 누르면 FND에 1씩 업카운트되고 PB13을 누르면 다운카운트되는데 표시되는 숫자의 범위가 00~99까지 되도록 하시오!

/* USER CODE BEGIN 0 */
void set_fnd(uint8_t num){
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, num&0b0001); //하위
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, (num>>1)&0b0001);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, (num>>2)&0b0001);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, (num>>3)&0b0001); //상위
}
uint8_t fnd_num = 15;
uint8_t fnd_sw = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(fnd_sw == 0){
		//십의자리
		set_fnd(fnd_num/10);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 1);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);
		fnd_sw = 1;
	}else if(fnd_sw == 1){
		//일의자리
		set_fnd(fnd_num%10);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 0);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);
		fnd_sw = 0;
	}
}
/* USER CODE END 0 */



/* USER CODE BEGIN 2 */
 HAL_TIM_Base_Start_IT(&htim3);
 for(int i = 0;i<2;i++){
	  fnd_control = 1;
	  fnd_num = 88;
	  HAL_Delay(1000);
	  fnd_control = 0;
	  HAL_Delay(1000);
 }
 fnd_control = 1;
 fnd_num = 0;
 /* USER CODE END 2 */

while (1)
 {
	  if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == 0){
		  if(fnd_num != 99){
			  fnd_num++;
		  }
		  HAL_Delay(200);
	  }
	  if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13) == 0){
		  if(fnd_num != 0){
			  fnd_num--;
		  }
		  HAL_Delay(200);
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


7.예제6에서 PB12를 누르면 0에서 99까지 0.5초간격으로 업카운트되고 PB13을 누르면 99에서 0까지 1씩 다운카운트되는 원래 임베디드기능사에 있는 문제를 구현하시오!

/* USER CODE BEGIN 0 */
void set_fnd(uint8_t num){
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, num&0b0001); //하위
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, (num>>1)&0b0001);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, (num>>2)&0b0001);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, (num>>3)&0b0001); //상위
}
uint8_t fnd_num = 15;
uint8_t fnd_sw = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(fnd_sw == 0){
		//십의자리
		set_fnd(fnd_num/10);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 1);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);
		fnd_sw = 1;
	}else if(fnd_sw == 1){
		//일의자리
		set_fnd(fnd_num%10);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 0);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);
		fnd_sw = 0;
	}
}
/* USER CODE END 0 */



/* USER CODE BEGIN 2 */
 HAL_TIM_Base_Start_IT(&htim3);
 for(int i = 0;i<2;i++){
	  fnd_control = 1;
	  fnd_num = 88;
	  HAL_Delay(1000);
	  fnd_control = 0;
	  HAL_Delay(1000);
 }
 fnd_control = 1;
 fnd_num = 0;
 uint32_t t = 0;
 //task_num이 0이면 아무것도 안함, 1이면 task1, 2면 task2
 uint8_t task_num = 0;
 /* USER CODE END 2 */
while (1)
 {
	  if(task_num == 1){
		  if(HAL_GetTick() - t >= 500){
			  t = HAL_GetTick();
			  //0부터 상승
			  if(fnd_num == 99){
				  fnd_num = 0;
			  }else{
				  fnd_num++;
			  }
		  }

	  }else if(task_num == 2){
		  if(HAL_GetTick() - t >= 500){
			  t = HAL_GetTick();
			  //99부터 하강
			  if(fnd_num == 0){
				  fnd_num = 99;
			  }else{
				  fnd_num--;
			  }
		  }
	  }
	  if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == 0){
		  //task1 작동
		  task_num = 1;
		  fnd_num = 0;
		  HAL_Delay(200);
	  }
	  if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13) == 0){
		  //task2 작동
		  task_num = 2;
		  fnd_num = 99;
		  HAL_Delay(200);
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }
반응형
Posted by 덕력킹
,