반응형

https://youtube.com/live/tYoSbV1Dg9I

[STM32#06] HAL_ADC_PollForConversion(),HAL_ADC_GetValue()을 이용해서 아날로그(analog)값을 입력받는 방법 알아보기!(녹칸다 내맘대로 STM32)

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

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

이번편에는 녹칸다의 STM32쉴드에 붙어있는 로터리엔코더를 작동시켜보도록 합니다~!

 

(STM32에서 아날로그입력시 알고있으면 좋은점!)
1.STM32에는 아날로그입력을 위한 ADC가 12bit가 적용된다!
2.아두이노 우노는 ADC가 10bit이고 측정값의 범위가 0~1023이다!
3.아하! 그러면 STM32는 0~4095의 범위를 가지는군요!(정답)
4.아두이노의 경우 analogRead(핀번호) 라고 하면 아주 간단하게 값 측정이 가능하나, STM32는 그렇게 간단하지 않다!
5.아날로그값을 1개로 측정할때와 2개이상을 동시에 측정할때는 접근법이 달라지게 되니 상황에 따른 방법론을 이해할 필요가 있음!
6.지금 사용하는 뉴클레오보드는 ADC1과 ADC2로 2개로 구성되어있고 이하에 IN이라는 여러개의 채널로 구성되어있다!
7.내가 사용할 핀을 ADC1이나 ADC2의 채널에 지정을 해서 사용할 수 있음!

 

(아날로그 3종세트 회로도)


(예제목차)
1.PB1과 PA8에 연결된 버튼을 EXTI로 설정한다음 PB1버튼을 누르면 PB3에 연결된 LED가 ON되고 PA8버튼을 누르면 OFF되도록 하는데, main loop에 10초간격으로 “NOCKANDA”라고 출력되는 시리얼출력 코드를 작성해서 인터럽트가 어떤 효과를 가지는지에 대해서 설명하시오! 

/* USER CODE BEGIN 0 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
 if(GPIO_Pin == GPIO_PIN_1)
 {
	   //LED ON
	  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3, 1);
 }else if(GPIO_Pin == GPIO_PIN_8)
 {
	   //LED OFF
	  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3, 0);
 }
}
/* USER CODE END 0 */
//중략
/* USER CODE BEGIN WHILE */
 while (1)
 {
	  HAL_UART_Transmit(&huart2, "NOCKANDA!!\n", 11, 100);
	  HAL_Delay(10000);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


2.PA0에 연결된 가변저항값을 측정해서 100밀리초 간격으로 시리얼출력하시오!(ADC1 IN0에 지정)

/* USER CODE BEGIN 2 */
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 uint16_t adc_value0 = 0;
 char buff[50];
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //측정할때마다 호출
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
		  sprintf(buff,"A0 = %d\n",adc_value0);
		  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


3.측정한 가변저항이 대략 0~4095의 값이 나오는데, 이값을 이용해서 부착되어있는 LED 8개를 게이지 형태로 출력하시오!

/* USER CODE BEGIN 2 */
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 uint16_t adc_value0 = 0;
 char buff[50];
 GPIO_TypeDef *mygroup[] = {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)
 {
	  //측정할때마다 호출
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
		  //0~4095의 범위를 0~7사이로 변환해라!
		  adc_value0 = 7 * adc_value0/4000.0;
		  sprintf(buff,"A0 = %d\n",adc_value0);
		  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
		  //8개의 LED를 0~7사이에 나온 LED의 갯수만큼 켠다
		  for(int i = 0;i < 8;i++){
			  if(i <= adc_value0){
				  HAL_GPIO_WritePin(mygroup[i],mypin[i], 1);
			  }else{
				  HAL_GPIO_WritePin(mygroup[i],mypin[i], 0);
			  }
		  }
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


4.PA1에 연결되어있는 CDS의 값을 100밀리초 간격으로 측정해서 시리얼출력하시오!(ADC1 IN1에 지정)

/* USER CODE BEGIN 2 */
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 uint16_t adc_value0 = 0;
 char buff[50];
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //측정할때마다 호출
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
		  sprintf(buff,"A1 = %d\n",adc_value0);
		  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


5.측정한 CDS값이 1000을 넘으면 LED 8개를 모두 ON하고 1000보다 작으면 OFF하시오! 

/* USER CODE BEGIN 2 */
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 uint16_t adc_value0 = 0;
 char buff[50];
 GPIO_TypeDef *mygroup[] = {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)
 {
	  //측정할때마다 호출
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
		  //CDS의 값이 1000미만이면 LED OFF고 1000이상이면 ON이다!
		  if(adc_value0 >= 1000){
			  for(int i = 0;i<8;i++){
				  HAL_GPIO_WritePin(mygroup[i], mypin[i], 0);
			  }
		  }else{
			  for(int i = 0;i<8;i++){
				  HAL_GPIO_WritePin(mygroup[i], mypin[i], 1);
			  }
		  }
		  sprintf(buff,"A1 = %d\n",adc_value0);
		  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


6.측정한 CDS값을 전압으로 계산해서 100밀리초 간격으로 출력하시오!

/* USER CODE BEGIN 2 */
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 uint16_t adc_value0 = 0;
 char buff[50];
 /* USER CODE END 2 */
 /* 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.0);
		  sprintf(buff,"Voltage = %f\n",voltage);
		  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


7.PA4에 연결된 NTC서미스터의 온도값을 측정해서 100밀리초간격으로 출력하시오!(온도값을 소수점이하 2자리만 살리고 ‘C단위를 붙히시오)

/* USER CODE BEGIN 0 */
#define R1 10000
#define c1 1.009249522e-03
#define c2 2.378405444e-04
#define c3 2.019202697e-07
/* USER CODE END 0 */
//중략
/* USER CODE BEGIN 2 */
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 uint16_t adc_value0 = 0;
 char buff[50];
 float logR2, R2, T, Tc, Tf;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //측정할때마다 호출
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
		  R2 = R1 * (4095.0 / adc_value0 - 1.0);
		  logR2 = log(R2);
		  T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
		  Tc = T - 273.15;
		  //온도값을 출력하는데 .2라는것은 소수점 이하 2자리만 출력하라는 것이다!
		  sprintf(buff,"Voltage = %.2f'C\n",Tc);
		  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


8.PA0과 PA1에 연결된 아날로그값을 ADC1과 ADC2로 분할해서 동시에 100밀리초 간격으로 출력하시오!

/* USER CODE BEGIN 2 */
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 HAL_ADC_Start(&hadc2); //딱 한번만 호출
 uint16_t adc_value0 = 0;
 uint16_t adc_value1 = 0;
 char buff[50];
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //PA0
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
	  }
	  //PA1
	  if(HAL_ADC_PollForConversion(&hadc2, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value1 = HAL_ADC_GetValue(&hadc2); //0~4095
	  }
	  sprintf(buff,"PA0 = %d, PA1 = %d\n",adc_value0,adc_value1);
	  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


9.PA0과 PA1에 연결된 아날로그값을 ADC1의 IN0과 IN1로 지정해서 동시에 출력하시오!

/* USER CODE BEGIN 2 */
 uint16_t adc_value0 = 0;
 uint16_t adc_value1 = 0;
 char buff[50];
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //PA0 ADC1 RANK1
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1, 100);
	  adc_value0 = HAL_ADC_GetValue(&hadc1);
	  //PA1 ADC1 RANK2
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1, 100);
	  adc_value1 = HAL_ADC_GetValue(&hadc1);
	  sprintf(buff,"PA0 = %d, PA1 = %d\n",adc_value0,adc_value1);
	  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


10.예제9의 방법으로 PA0, PA1, PA4의 값을 동시에 출력하시오!(PA4는 온도값으로 환산할 것)

/* USER CODE BEGIN 0 */
#define R1 10000
#define c1 1.009249522e-03
#define c2 2.378405444e-04
#define c3 2.019202697e-07
/* USER CODE END 0 */
//중략
/* USER CODE BEGIN 2 */
 uint16_t adc_value0 = 0;
 uint16_t adc_value1 = 0;
 uint16_t adc_value2 = 0;
 char buff[50];
 float logR2, R2, T, Tc, Tf;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //PA0 ADC1 RANK1
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1, 100);
	  adc_value0 = HAL_ADC_GetValue(&hadc1);
	  //PA1 ADC1 RANK2
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1, 100);
	  adc_value1 = HAL_ADC_GetValue(&hadc1);
	  //PA4 ADC1 RANK3
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1, 100);
	  adc_value2 = HAL_ADC_GetValue(&hadc1);
	  //온도계산
	  R2 = R1 * (4095.0 / adc_value2 - 1.0);
	  logR2 = log(R2);
	  T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
	  Tc = T - 273.15;
	  sprintf(buff,"PA0 = %d, PA1 = %d, PA4 = %.2f'C\n",adc_value0,adc_value1,Tc);
	  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


11.예제10에서 PA0의 값이 1000을 넘으면 PB3이 켜지고 그렇지않으면 꺼진다!, PA1의 값이 1000보다 크면 PB13의 LED가 켜지고 그렇지않으면 꺼지다! PA4에서 측정한 온도값이 20도를 넘으면 PB5의 LED가 켜지고 그렇지 않으면 꺼진다!

/* USER CODE BEGIN 0 */
#define R1 10000
#define c1 1.009249522e-03
#define c2 2.378405444e-04
#define c3 2.019202697e-07
/* USER CODE END 0 */
//중략
/* USER CODE BEGIN 2 */
 uint16_t adc_value0 = 0;
 uint16_t adc_value1 = 0;
 uint16_t adc_value2 = 0;
 char buff[50];
 float logR2, R2, T, Tc, Tf;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //PA0 ADC1 RANK1
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1, 100);
	  adc_value0 = HAL_ADC_GetValue(&hadc1);
	  //PA1 ADC1 RANK2
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1, 100);
	  adc_value1 = HAL_ADC_GetValue(&hadc1);
	  //PA4 ADC1 RANK3
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_PollForConversion(&hadc1, 100);
	  adc_value2 = HAL_ADC_GetValue(&hadc1);
	  //온도계산
	  R2 = R1 * (4095.0 / adc_value2 - 1.0);
	  logR2 = log(R2);
	  T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
	  Tc = T - 273.15;
	  if(adc_value0 > 1000){
		  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);
	  }else{
		  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);
	  }
	  if(adc_value1 > 1000){
		  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 1);
	  }else{
		  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 0);
	  }
	  if(Tc > 20){
		  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);
	  }else{
		  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);
	  }
	  sprintf(buff,"PA0 = %d, PA1 = %d, PA4 = %.2f'C\n",adc_value0,adc_value1,Tc);
	  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }





반응형
Posted by 덕력킹
,