# STM32 - ADC ###### tags: `firmware_hardware` `electrical_system` `NTURT` #### Author: @andre-liang ![](https://i.imgur.com/pqzH1Eq.jpg) source: [link](https://open.spotify.com/playlist/37i9dQZF1DZ06evO49hLQA) ### Preface ADC (Analog-to-Digital Converter) is a peripheral to measure analog signal. ### How it works? ![](https://i.imgur.com/6LVXPn3.png) source: [link](https://www.mlmvlab.bime.ntu.edu.tw/_files/ugd/0752bb_b825987585d6457998471ca802a351c0.pdf) There many way to design a ADC, one of which is successive approximation ADC. It essencially use different sample voltage to sample the unknown outside voltage. Due to the sampling process, the our ADC has a smaple rate, which decide how fast the MCU can convert the analog signal to digital signal. Also as the resolution increase, the ADC's conversion speed becomes slower. ### Config #### Channel ![](https://i.imgur.com/aPh4uSA.png) One ADC unit can have multiple channel, enable the MCU to measure multiple analog signals at once. Each ADC can also operate in regular mode or injected mode. In regular mode, the ADC convert each channel one after another. While in injected mode, the ADC will prioritize the convertion of injected group channel, achieving lower latency. #### DualMode On our STM32, there are two ADCs, which we can synchronize together to get more accurate results. #### Get your values Just like other STM32 peripherals, the ADC can be driven in three modes: polling, interrupt and DMA (Direct Memory Access) mode. #### Setup ![](https://i.imgur.com/K4ZqOvb.png) Generate a new project using STM32CubeMX, Enable `ADC1->Temperature Sensor Channel`. *Note that if you want to read multiple channel, it is recommended to use the DMA mode & injected group channel and is generally more complicated.* ### Example In this example, we will measure the temperature of the chip by using internal temperature channel and ADC. For simplicity, we will use pooling to get the ADC conversion value. ### Variables ```cpp= float temperture; ``` Declare the `temperture` variable in global variable so that it could be displayed on the live expression window. ### Functions ![](https://i.imgur.com/3Kcf852.png) source: [link](https://www.st.com/en/microcontrollers-microprocessors/stm32g431kb.html#st_all-features_sec-nav-tab) So we can get the relation: $$ V=V_{30}+ \textrm{Avg_Slope} \times \left( T-30 \right) $$ $$ T= \frac{ \left(V-V_{30}\right)}{\textrm{Avg_Slope}} $$ By using the sensor characteristics, we can get the current temperature by reading the voltage output of the sensor. First start the ADC before the main loop, then read the value of ADC in pooling mode, finally convert the voltage into temperture. ```cpp= /* USER CODE BEGIN 2 */ HAL_ADC_Start(&hadc1); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); adc_value = HAL_ADC_GetValue(&hadc1); voltage = (double) adc_value / 4095.0 * 3.3; temperture = (voltage - 0.76) / (0.0025); HAL_Delay(200); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ ``` But since our sensor is not calibrated, we don't expect you to get accurate results. :disappointed_relieved: ### Conclusion The ADCs (Analog-to-Digital Converters) offer a robust mechanism for your microcontroller to capture analog signals from the external environment. It's important to recognize that analog signals are susceptible to interference. Therefore, in order to secure accurate readings, it's advisable to calibrate your sensor or employ statistical techniques to effectively reduce signal noise. This meticulous approach ensures the reliability of the obtained results despite the inherent challenges posed by analog signals.