본문 바로가기
임베디드 쌩초보 공부/STM32

STM32 Adc 개요 & Adc 채널 여러개 측정

by 존버매니아.임베디드 개발자 2021. 12. 27.
반응형

2021.12.26 - [임베디드 쌩초보 공부/STM32] - STM32 ADC Conversion

위 글에서 Adc Channel 한개에 대해서 Polling 방식으로 conversion 하는 방법에 대해 알아보았다

근데 밑바탕이 되는 배경지식 이런거 하나도 없이 그냥 최대한 간단하게만 설명했었다.

이번에는 좀 더 배경지식에 대해 상세히 알아보고, 또 adc channel이 한개가 아니라 여러개의 channel을 컨버전 하는 것에 대해서도 알아보자.


MCU마다 ADC Converter 갯수가 다르다.

일단 우리보드에는 ADC1 한개 밖에 없다.

이 ADC1에는 총 19개의 채널을 연결하여 사용할 수 있다.

ADC1_In1,  ADC1_In2 , ....   ADC1_In15 이런식으로 명칭한다.

16개의 External 채널 + 3개의 internal channles가 있다.

여기서 external 채널이란 실제 mcu 아날로그  핀에 연결되는 부분을 말하는 것이고

interal channel은 mcu 내부의 어떤 전압을 측정하는걸로 추정되는데 internal은 내용 잘 모르겠으니 pass

 

Regular Group, Injected Group 이라는 것이 있다

컨버전 하려는 채널을 Regular Group 혹은 Injected Group에 넣은 후

Group 단위로 컨버전을 요청하는 방식으로 동작한다

Regular Group은 최대 16개의 채널 할당이 가능하며

Injected Group은 최대 4개의 채널 할당이 가능하다.

이 때 할당순서와 갯수는 임의로 지정 가능하다

예를들어 ch5, ch3, ch2 , ch3 이렇게 group에 넣고 conversion 요청 할 수 있다.

 

가장 큰 차이점은

Regular Group결과 레지스터가 1개인 반면

Injected Group4개의 결과레지스터를 갖는 것이다.


Conversion Mode

Single Conversion Mode(CONT =0) 

ADC_CFGR 레지스터의 CONT 비트필드 값이 0 인 mode이다.

앞에 말한거처럼 regular group에 채널들을 채워넣은 후, conversion 요청하면

순서대로 채널 하나하나가 컨버전이 되고, 컨버전 결과가 ADC_DR 레지스터에 저장된다.

EOC(end of regular conversion) flag가 set된다.

 ->여기서 주목할 점은 regular group에 채널은 여러개 넣을 수 있는데 결과 레지스터가 하나란 거다.

  그러므로, 여러개의 채널에 대한 adc 결과물을 확인하려면 다음 채널의 결과가 덮어씌어지기 전에,

한개 채널에 대한 컨버전이 끝나면 곧 바로 adc 결과물을 읽어가야 한다.

필연적으로 인터럽트 혹은 DMA 방식이 필요하다는 얘기가 된다.

 

폴링 방식으로 가져가는 것이 불가능하진 않지만

채널 1개에 대한 컨버전이 끝날때마다 결과를 가져가는 구조로 sw 만들기가 굉장히 곤란하다.

여기서 무슨 얘기를 하고싶은거냐면

polling 방식의 ADC HAL API를 사용해서는 하나의 ADC에 여러개 채널을 할당하는 방식을 못쓴다는 얘기를 하고 싶은 거다. ( 사실은 discontiuous 모드를 사용하면 되기는한데 일단은 느낌만 그렇겠구나 하고 넘어가자)

 

암튼 이런식으로 동작을 하다가 group에 할당된 모든 채널에 대한 conversion이 끝나면 EOS(End of Sequence) Flag가 set되고 컨버전은 종료가 된다.

 

 

Continous Mode(CONT =1)

앞에 single conversion mode에서는 conversion start 신호를 받으면 시퀀스 하나를 컨버전하고 끝.

Continuous Mode는 한번 start 시키면 계속 컨버전을 자동으로 반복한다.

 

한편, Injected Group은 Continumous Mode가 안된다고 한다.

---------------------------------------

discontinous Mode

이게 뭐냐면

regular group에 채널 여러개를 할당해놓은다음 컨버전 요청하면 이것들에 대해서 전부 컨버전을 한다고 앞에서 설명했다.

근데 discontinous mode를 사용하면, group에 할당된 채널 전부를 다 요청하는게 아니라 일부만 요청하는 방식으로 동작한다

무슨 말이냐면

 

regular group에 채널 1,2,3,4,5,6 을 넣고 start conversion하면 원래 채널 6개에 대한 conversion이 일어나야하는데

discontinuous mode를 사용하면 컨버전 될 채널의 갯수를 셋팅하게 되어있는데 이것을 만약에 2로 셋팅하면?

 

그러면 conversion 요청하면 채널 1,2,3,4,5,6 중에 채널 1,2에 대해서만 컨버전하고 시퀀스를 종료한다.

이 상태에서 또 컨버전 요청하면 다음 2개인 채널 3,4 만 요청. 이런식으로 


한편 conversion start를 요청하는 방식은 크게

sw 방식, hw 방식이 있다.

sw 방식은 start bit를 set 하는 것이고

hw 방식은 특정 신호랑 연결을 해서 ,그 신호에서 falling edge나 rising edge가 생겼을 때 conversion 요청하는 방식이다.


Over Run

Over Run은 Conversion 결과를 아직 cpu나 dma가 읽어가지 않았는데 conversion이 새로 일어난 경우에 이를 알리는 기능이다.

이런 상황이 발생될 경우 flag가 set되며, 해당 flag에 대한 인터럽트를 enbale 했을 경우 인터럽트가 발생된다.

한편, 이렇게 오버런이 발생했을 때, 남아있는 데이터를 그대로 보존할 수도 있고 혹은 새로운 결과물로 덮어씌을 수도 있는데

이것은 OVRMOD 비트 필드를 통해서 컨트롤이 가능하다


개요는 일단 대강 이정도만 알아보고,

ADC1에 연결된 채널 여러개에 대해서 컨버전 하는 방법을 알아보자.

 

예를들어 ADC1의 채널 1,2,3 을 사용한다고 가정해보자.

Regular Group에 채널 1,2,3을 집어넣은 후

Adc Start를 하면된다.

이 때, polling 방식으로 사용하려면

discontinous 방식에 값을 1로 셋팅해서 

Adc start 한번할때마다 결과 하나씩 읽어가는 식으로 구성하면된다.

 

혹은, 인터럽트 방식으로 셋팅 한 후,

EOC( 채널에 컨버전 하나 끝날때 마다) 인터럽트가 발생해서 결과레지스터를 읽어가는 방식으로 구현하면 된다.

 

혹은 DMA 방식으로 셋팅 해서

EOC 인터럽트 발생될때마다 DMA에서 결과레지스터 읽어가는 방식으로 구현하면 된다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형