After we had a quick overview of STM32 ADC peripheral we can start digging deeper in to specifics. In order to understand simple things lets go with simplest case – single conversion mode. In this mode ADC does one conversion and then stops. After ADC conversion result is stored in to 16-bit ADC_DR data register (remember that conversion result is 12-bit), then End of Conversion (EOC) flag is set and interrupt is generated if EOCIE flag is set. Same situation is if injected channel is converted. The difference is that result is stored in to corresponding ADC_DRJx register, JEOC flag is set and interrupt generated if JEOCIE flag is set.
In our example we are going to measure the internal temperature sensor value and send it using USART. Temperature sensor is internally connected to ADC1_IN16 channel. Algorithm will start single conversion and wait for conversion complete flag EOC. Then we are going to read ADC value from ADC_DR register, which later will be used to calculate in temperature value in Celsius and sent via USART. So we should see value in terminal screen. Continue reading
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.
In many microcontroller projects you need to read and write data. It can be reading data from peripheral unit like ADC and writing values to RAM. In other case maybe you need send chunks of data using SPI. Again you need to read it from RAM and constantly write to SPI data register and so on. When you do this using processor – you loose a significant amount of processing time. In order to avoid occupying CPU most advanced microcontrollers have Direct memory Access (DMA) unit. As its name says – DMA does data transfers between memory locations without need of CPU.
Low and medium density ST32 microcontrollers have single 7 channel DMA unit while high density devices have two DMA controllers with 12 independent channels. In STM32VLDiscovery there ST32F100RB microcontroller with single DMA unit having 7 channels. Continue reading
In previous part of tutorial we have covered simple USART routines that sends data directly to USART peripheral. This is OK to use such approach when project isn’t time critical and processing resources are far from limits. But most often we stuck with these limiting factors especially when RTOS is used or when we perform critical real time data processing. And having USART routines with while loop based wait isn’t a good idea – it simply steals processing power only to send a data.
As you may guessed – next step is to employ interrupts.
As you can see there are many sources to trigger interrupts and each of them are used for different purpose. In order to use one or another interrupt first it has to be enabled in USART control register (USART_CR1, USART_CR2 or USART_CR3). Then NVIC USART_IRQn channel has to be enabled in order to map interrupt to its service routine. Because NVIC has only one vector for all USART interrupt triggers, service routine has to figure out which of interrupts has triggered an event. This is done by checking flags in USART status register (USART_SR). Continue reading