반응형

https://youtube.com/live/2mMDL1DBVEM

[STM32#04] HAL_UART_Transmit(), HAL_UART_Receive() 함수를 이용해서 USART2 시리얼통신 계속 해보기!(녹칸다 내맘대로 STM32)

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

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

기본 송수신은 되었고, 가변길이에 대한 송수신과 LED와 버튼을 제어해보는 예제를 만들어보도록 하자!

 

1.STM32의 PB1에 연결된 버튼을 누르면 usart2통신으로 PC에게 “PB1 PRESSED!!”라는 문자열이 버튼 누를때마다 전송되도록 하시오!

ex1.zip
0.00MB

 

/* USER CODE BEGIN 2 */
 char *msg = "PB1 PRESSED!!\n";
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //PB1을 눌렀다!
	  if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == GPIO_PIN_RESET){
	  	  //usart2로 메시지를 전송한다!
		  HAL_UART_Transmit(&huart2, msg, strlen(msg), 100);
		  HAL_Delay(200); //채터링 방지를 위한 소량의 딜레이
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }

 

2.10초간격으로 STM32가 PC쪽으로 “NOCKANDA!!”라는 문자열을 전송한다! 그리고 이때 PB1버튼을 누르면 “PB1 PRESSED!!”라는 문자열이 이전 조건과는 별개로 전송된다!(HAL_Delay를 사용하지 마십시요!)

ex2.zip
0.00MB

 

/* USER CODE BEGIN 2 */
 char *msg1 = "PB1 PRESSED!!\n";
 char *msg2 = "NOCKANDA\n";
 uint32_t t = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //PB1을 눌렀다!
	  if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == GPIO_PIN_RESET){
	  	  //usart2로 메시지를 전송한다!
		  HAL_UART_Transmit(&huart2, msg1, strlen(msg1), 100);
		  HAL_Delay(200); //채터링 방지를 위한 소량의 딜레이
	  }
	  //10000이라는 값을 인터벌로해서 인터벌마다 한번씩 걸리는 조건문!
	  if(HAL_GetTick() - t >= 10000){
		  t = HAL_GetTick();
		  //지정된 메시지를 10초간격으로 전송한다!
		  HAL_UART_Transmit(&huart2, msg2, strlen(msg2), 100);
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }

 

3.조건문의 재미난 특성에 대해서 간략한 예시를 구현하시오!(깨알지식)

ex3.zip
0.00MB

 

/* USER CODE BEGIN 2 */
 char *msg1 = "condition1 print!!\n";
 char *msg2 = "condition2 print!!\n";
 char *msg3 = "condition3 print!!\n";
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //if는 괄호안에 들어가는 조건식이 참이면 중괄호 부분을 실행한다!
	  //조건식은 흔히 yes와 no같은 맞다 아니다로 해석하는데, 내부적으로는 참이 1이고 거짓이 0이다!
	  //참은 0이 아닌 숫자는 참으로 처리한다!
	  if(0){
		  HAL_UART_Transmit(&huart2, msg1, strlen(msg1), 100);
	  }
	  if(1){
		  HAL_UART_Transmit(&huart2, msg2, strlen(msg2), 100);
	  }
	  if(2){
		  HAL_UART_Transmit(&huart2, msg3, strlen(msg3), 100);
	  }
	  HAL_Delay(1000);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }

 

4.가변길이를 가지는 문자열 데이터를 PC에서 STM32로 전송했을때 수신을 하는 예시를 보이시오!(타임아웃을 기반으로 처리하기 버전1)

ex4.zip
0.00MB

 

 

/* USER CODE BEGIN 2 */
 char recv;
 char buff[100]; //수신메모리
 int pos = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //PC에서 보낸 데이터가 있는가? 있다면 읽기 시작한다!
	  if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
		  //보낸 데이터가 있다면 1바이트씩 읽는다!
		  buff[0] = recv;
		  pos = 1;
		  while(1){
			  //만약 PC에서 데이터를 연속으로 보내다가 흐름이 0.5초정도 끊어지면 읽기를 종료한다!
			  if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
				  //계속 데이터가 우체통에 있고~
				  buff[pos] = recv;
				  pos++;
			  }else{
				  //0.5초 기다려도 없네? 타임아웃이네?
				  //이 지점이 문자열의 끝지점인것을 의미한다!
				  buff[pos] = '\0';
				  //ECHO
				  HAL_UART_Transmit(&huart2, buff, pos, 100);
				  break;
			  }
		  }
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }

 

5.가변길이를 가지는 문자열 데이터를 PC에서 STM32로 전송했을때 수신을 하는 예시를 보이시오!(타임아웃을 기반으로 처리하기 버전2)

ex5.zip
0.00MB

 

/* USER CODE BEGIN 2 */
 char recv;
 char buff[100]; //수신메모리
 int pos = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //PC에서 뭔가 데이터를 보내면 while루프는 동작한다!
	  pos = 0;
	  while(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
		  buff[pos] = recv;
		  pos++;
	  }
	  buff[pos] = '\0';
	  //pos가 0이면 PC에서 온 데이터가 없고 0보다 크다면 있는것이다!
	  if(pos > 0){
		  //받은 데이터를 ECHO한다!
		  HAL_UART_Transmit(&huart2, buff, pos, 100);
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }

 

6.이번에는 PC하고 STM32하고 종료문자를 라인피더(‘\n’)로 설정했을때 STM32에서 1개씩 데이터를 빼오다가 라인피더가 확인되면 거기까지를 한덩어리로 해서 PC쪽으로 반환하시오!(보내는 쪽에서 무조건 종료문자를 붙힌다) putty의 설정이 \n이 아니라 캐리지리턴인 \r로 되어있어서 수정함!

 

/* USER CODE BEGIN 2 */
  char recv;
  char buff[100]; //수신메모리
  int pos = 0;
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
 	  //PC에서 보낸 데이터가 있는가? 있다면 읽기 시작한다!
 	  if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
 		  //보낸 데이터가 있다면 1바이트씩 읽는다!
 		  buff[0] = recv;
 		  pos = 1;
 		  while(1){
 			  //만약 PC에서 데이터를 연속으로 보내다가 흐름이 0.5초정도 끊어지면 읽기를 종료한다!
 			  if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
 				  //지금 읽은 데이터가 종료문자이냐? 이면 끝이고 아니면 계속 읽는다!
 				  if(recv == '\r'){
 					buff[pos] = '\0';
 					HAL_UART_Transmit(&huart2, buff, pos, 100);
 					break;
 				  }else{
 					buff[pos] = recv;
 					pos++;
 				  }
 			  }
 		  }
 	  }
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  }


7.녹칸다가 “LED ON”이라고 전송하면 PB3에 연결된 LED가 켜지고, “LED OFF”라고 전송하면 LED가 꺼지도록 하시오!

ex7.zip
0.00MB

/* USER CODE BEGIN 2 */
  char recv;
  char buff[100]; //수신메모리
  int pos = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
  while (1)
  {
 	  //PC에서 보낸 데이터가 있는가? 있다면 읽기 시작한다!
 	  if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
 		  //보낸 데이터가 있다면 1바이트씩 읽는다!
 		  buff[0] = recv;
 		  pos = 1;
 		  while(1){
 			  //만약 PC에서 데이터를 연속으로 보내다가 흐름이 0.5초정도 끊어지면 읽기를 종료한다!
 			  if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
 				  //지금 읽은 데이터가 종료문자이냐? 이면 끝이고 아니면 계속 읽는다!
 				  if(recv == '\r'){
 					buff[pos] = '\0';
 					//LED ON이면 LED를 켜고 LED OFF면 끈다
 					if(strcmp(buff,"LED ON") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET);
 					}else if(strcmp(buff,"LED OFF") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);
 					}
 					break;
 				  }else{
 					buff[pos] = recv;
 					pos++;
 				  }
 			  }
 		  }
 	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
  }

 

8.STM32실습보드에 LED가 총 8개 연결되어있는데, LED다음에 번호를 1~8까지 붙히고 ON이면 켜지고 OFF면 꺼지도록 하시오! 예를들면 LED5 ON이라고 하면 다섯번째 LED가 켜지는 것이다!(LED가 만약 10개 이상이라면 숫자가 2자리가 되어서 복잡한데 지금은 한자리만 해석하면 되니까 간단!)

ex8.zip
0.00MB

/* USER CODE BEGIN 2 */
  char recv;
  char buff[100]; //수신메모리
  int pos = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
  while (1)
  {
 	  //PC에서 보낸 데이터가 있는가? 있다면 읽기 시작한다!
 	  if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
 		  //보낸 데이터가 있다면 1바이트씩 읽는다!
 		  buff[0] = recv;
 		  pos = 1;
 		  while(1){
 			  //만약 PC에서 데이터를 연속으로 보내다가 흐름이 0.5초정도 끊어지면 읽기를 종료한다!
 			  if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
 				  //지금 읽은 데이터가 종료문자이냐? 이면 끝이고 아니면 계속 읽는다!
 				  if(recv == '\r'){
 					buff[pos] = '\0';
 					//LED ON이면 LED를 켜고 LED OFF면 끈다
 					if(strcmp(buff,"LED1 ON") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET);
 					}else if(strcmp(buff,"LED1 OFF") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);
 					}else if(strcmp(buff,"LED2 ON") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);
 					}else if(strcmp(buff,"LED2 OFF") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);
 					}else if(strcmp(buff,"LED3 ON") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
 					}else if(strcmp(buff,"LED3 OFF") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
 					}else if(strcmp(buff,"LED4 ON") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);


 					}else if(strcmp(buff,"LED4 OFF") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET);
 					}else if(strcmp(buff,"LED5 ON") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);
 					}else if(strcmp(buff,"LED5 OFF") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
 					}else if(strcmp(buff,"LED6 ON") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_SET);
 					}else if(strcmp(buff,"LED6 OFF") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_RESET);
 					}else if(strcmp(buff,"LED7 ON") == 0){
 						HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET);
 					}else if(strcmp(buff,"LED7 OFF") == 0){
 						HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET);
 					}else if(strcmp(buff,"LED8 ON") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
 					}else if(strcmp(buff,"LED8 OFF") == 0){
 						HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
 					}
 					break;
 				  }else{
 					buff[pos] = recv;
 					pos++;
 				  }
 			  }
 		  }
 	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
  }

 

9.녹칸다가 LED1번부터 8번까지의 상태를 2진수로 전송한다! 0이면 OFF고 1이면 ON이다! 예를들어 11110000이라고 보내면 LED1~4까지는 ON이고 5~8까지는 OFF하라는 의미이다!(데이터가 고정길이다)

ex9.zip
0.00MB

/* USER CODE BEGIN 2 */
  char buff[100]; //수신메모리
  GPIO_TypeDef *mygpio[] = {GPIOB,GPIOB,GPIOB,GPIOB,GPIOB,GPIOB,GPIOC,GPIOB};
  uint16_t mypin[] = {GPIO_PIN_3,GPIO_PIN_13,GPIO_PIN_5,GPIO_PIN_14,GPIO_PIN_4,GPIO_PIN_15,GPIO_PIN_4,GPIO_PIN_7};
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
  while (1)
  {
 	  //PC에서 보낸 데이터가 있는가? 있다면 읽기 시작한다!
 	  if(HAL_UART_Receive(&huart2, buff, 8, 500) == HAL_OK){
 		 //buff에 0~7까지 LED의 상태가 문자 '0'또는 '1'로 지정되어서 데이터가 왔다!
 		 //buff를 반복문으로 0~7까지 하나씩 순회하면서 문자로 해석한다!
 		 for(int i = 0;i < 8;i++){
 			 if(buff[i] == '0'){
 				 //i번째 LED가 OFF이다!
 				HAL_GPIO_WritePin(mygpio[i], mypin[i], GPIO_PIN_RESET);
 			 }else if(buff[i] == '1'){
 				 //i번째 LED가 ON이다!
 				HAL_GPIO_WritePin(mygpio[i], mypin[i], GPIO_PIN_SET);
 			 }
 		 }
 	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
  }

 

10.예제1번에서 연결해놓은 PB1버튼을 2초동안 누르면 길게눌렀다고 PC로 전송하고, 2초이내로 짧게 누르면 짧게 눌렀다고 전송하시오!

ex10.zip
0.00MB

/* USER CODE BEGIN 2 */
 char *msg1 = "LONG CLICK!!\n";
 char *msg2 = "SHORT CLICK!!\n";
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
  while (1)
  {
	   //PB1을 눌렀다!
	  if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == GPIO_PIN_RESET){
		  //눌렀던 버튼을 뗄때까지 무한루프를 돌려버린다
		  //루프가 작동한 시간을 측정한다!
		  uint32_t t = HAL_GetTick(); //while루프에 진입하기 직전의 시간!
		  uint8_t is_longclick = 0;
		  while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == GPIO_PIN_RESET){
			  if(HAL_GetTick() - t > 2000){
				  //버튼을 2초이상 눌렀다!
				  is_longclick = 1;
				  break;
			  }
		  }
		  if(is_longclick){
			  //길게 눌러서 while루프가 강제종료된 경우
			  HAL_UART_Transmit(&huart2, msg1, strlen(msg1), 100);
			  //버튼 뗄때까지 무한대기
			  while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == GPIO_PIN_RESET);
			  //버튼 뗀다음에 오류를 방지하기 위한 소량의 지연시간
			  HAL_Delay(200);
		  }else{
			  //2초 이내에 눌렀다가 떼서 자연스럽게 종료된경우
			  HAL_UART_Transmit(&huart2, msg2, strlen(msg2), 100);
			  HAL_Delay(200);
		  }
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
  }

 

11.PB1버튼을 짧게누르면 모든 LED를 ON한다! PB1을 길게 누르면 모든 LED를 OFF한다!(예제10번내용 포함)

ex11.zip
0.00MB

 

/* USER CODE BEGIN 2 */
 char *msg1 = "LONG CLICK!!\n";
 char *msg2 = "SHORT CLICK!!\n";
 GPIO_TypeDef *mygpio[] = {GPIOB,GPIOB,GPIOB,GPIOB,GPIOB,GPIOB,GPIOC,GPIOB};
 uint16_t mypin[] = {GPIO_PIN_3,GPIO_PIN_13,GPIO_PIN_5,GPIO_PIN_14,GPIO_PIN_4,GPIO_PIN_15,GPIO_PIN_4,GPIO_PIN_7};
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
  while (1)
  {
	   //PB1을 눌렀다!
	  if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == GPIO_PIN_RESET){
		  //눌렀던 버튼을 뗄때까지 무한루프를 돌려버린다
		  //루프가 작동한 시간을 측정한다!
		  uint32_t t = HAL_GetTick(); //while루프에 진입하기 직전의 시간!
		  uint8_t is_longclick = 0;
		  while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == GPIO_PIN_RESET){
			  if(HAL_GetTick() - t > 2000){
				  //버튼을 2초이상 눌렀다!
				  is_longclick = 1;
				  break;
			  }
		  }
		  if(is_longclick){
			  //길게 눌러서 while루프가 강제종료된 경우
			  HAL_UART_Transmit(&huart2, msg1, strlen(msg1), 100);
			  //LED컨트롤
			  for(int i = 0;i<8;i++){
				  HAL_GPIO_WritePin(mygpio[i], mypin[i], GPIO_PIN_RESET);
			  }
			  //버튼 뗄때까지 무한대기
			  while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == GPIO_PIN_RESET);
			  //버튼 뗀다음에 오류를 방지하기 위한 소량의 지연시간
			  HAL_Delay(200);
		  }else{
			  //2초 이내에 눌렀다가 떼서 자연스럽게 종료된경우
			  HAL_UART_Transmit(&huart2, msg2, strlen(msg2), 100);
			  for(int i = 0;i<8;i++){
				  HAL_GPIO_WritePin(mygpio[i], mypin[i], GPIO_PIN_SET);
			  }
			  HAL_Delay(200);
		  }
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
  }
반응형
Posted by 덕력킹
,