STM32 ADC is pretty complex peripheral. It is designed to be flexible enough to accomplish complex tasks. We are going to dedicate few posts where we will try to cover main features and give working examples of code.
The block schematic may look scary at first time but if you look closer it can be split in to several pieces that are responsible for different functions. Will will go through them step by step to make it look more clear.
Lets see what ADC is capable to do. Generally speaking STM32 microcontroller ADC have up to 18 multiplexed 12-bit channels where two of them are internal – temperature sensor and reference (band gap) voltage. ADC module has a separate supply which normally can be connected to general MCU power supply. Also ADC can have external reference source through VREF+ and VREF- that can be brought through dedicated pins. In no special case analog supply voltage may be as reference internally. ADC can be performed in single or continuous mode for single channel, scan through all channels, externally triggered conversion. There is also an analog watchdog which can detect if voltage exceed preset threshold values. And of course DMA request based conversions.
ADC has dedicated prescaller that scales down APB2 clock to /2, /4, /6 and /8. Sampling time can be set individually for each channel from 1.5 to 239.5 cycles by selecting SMP[2:0] bits in ADC_SMPR1 and ADC_SMPR2 registers.
Regular and Injected conversions
STM32 microcontrollers support two ADC conversion modes: regular and injected. Regular mode is what we used to see in many types of microcontroller – all channels share same data register. Various regular modes can be possible, like single, continuous and group. More interesting here is group conversion where channels are specified to convert in round robin mode – cycle through channels. Its up to you how you collect data from register in time – through conversion complete interrupt or using DMA. Conversion group can be configured to cycle through max 16 channels and order of channels can be also programmed – they don’t have to be in order like 0,1,2,… number of channels and order can be selected in ADC_SQRx registers. Group can be programmed to convert continuously, and discontinuously triggered by external trigger. In discontinuous mode parts of group can be triggered to convert. For instance if we select group to be 16 channels then we can program to convert first 3 channels on trigger, then wait for another trigger and convert next three channels and so on.
Another is injected conversion mode. This might look something new. Actually there is nothing fancy about it. Injected group can perform conversion of selected four channels. Simply speaking injected group have a priority over normal conversion group scan.
If normal group conversion is going on and injected conversion is triggered, then normal conversion is halted, then injected conversion is performed. When done normal conversion is resumed. Injected conversion channels have their own result registers and offset registers. Offset can store value that will be automatically deducted from ADC result.
Analog watchdog is a handy feature of ADC module. It can save lots processing time if used where needed. In some cases we use ADC only to check if analog voltage reached some level (or dropped). Normally we would scan ADC channel continuously to capture the moment when level is reached. Analog watchdog can do this automatically in hardware level. All you need is to load low and high threshold values set interrupt and forget.
Watchdog can be set to monitor any channel or all channels either from regular group or injected. Why not to use this feature to monitor sensor data and raise alarm on some level. Might be a good choice for zero crossing detector. Processor could be put to sleep all time and awaken when analog watchdog interrupt occurs.
Next time we will get to ADC programming examples using GCC tools. There are several interesting modes we would like to try.