Embedded systems occupy an important position in the field of micro-control (temperature, humidity, pressure detection, four-axis aircraft), which are implemented by microprocessor CPUs (such as STM32) and sensors and controllers, and connect them so that they can communicate with each other properly. is the module to be sued in this section, ADC Analog-to-digital conversion peripherals. Let's start with the simplest experiment and learn more about this magical peripheral.
The ADC analog-to-digital conversion design is not complex, and the steps can be simplified to the following three steps:
1. Input voltage of the potentiometer on the receiving board
2. A/D conversion to obtain the digital amount, and transmit to the CPU
3. Output on PC via serial port.
Analyzing the above three steps to analyze the requirements, you will find that the ADC, GPIO, Usart, and RCC modules are the necessary peripherals for this experiment, because in addition to the ADC module, other peripherals have been learned and practiced, then understand and learn the ADC module, you can start the design of the program implementation.
ADC Chapters according to the stm32f series microcontroller manual
ADC conversion after the digital volume is 12 bits (resolution), in the Reference Board user manual and schematic diagram, it is known that the potentiometer port is PC0, the input voltage range 0~3.3v, the accuracy is 3.3/(2^12) V.
Query stm32f107 pin definition allocation, PC0 corresponds to Adc12_in10, that is, the acquisition of potentiometer voltage ADC1 and ADC2 can be, but must use Channel 10.
For now, using library functions to avoid leaks, so I recommend using library functions to configure registers, but understanding the meaning of library functions is quite necessary:
typedefstruct{u32 adc_mode; //clear the way ADC1 and ADC2 work, independent or other combinationsfunctionalstate Adc_scanconvmode; //channel mode of operation, single channel or multi-channel (scan)functionalstate Adc_continuousconvmode; //working in continuous or single-time mode (ADC conversion works in continuous modeu32 Adc_externaltrigconv; //A /D conversion start ruleu32 adc_dataalign; //determining the alignment of converted dataU8 Adc_nbrofchannel; //Specify the exact number of rule conversion channels 1~16}adc_inittypedef
To understand the meaning of the above structure, it is possible to initialize the relevant registers to implement the configuration of the ADC peripherals:
gpio_inittypedef gpio_initstructure; Adc_inittypedef adc_initstructure; Adc_deinit (ADC1); the //ADC module Peripheral clock needs to be set on the APB2 clock basis, determining the clock length for a single cycle (since the ADC clock cannot be greater than 14MHZ, note)
Rcc_adcclkconfig (RCC_PCLK2_DIV4);
//Enable ADC corresponds to Gpio port, peripheral area and multiplexing function clockrcc_apb2periphclockcmd (RCC_ADC1, ENABLE); //initializing the ADC module for GpioGpio_initstructure.gpio_pin =Gpio_adc1_pin; Gpio_initstructure.gpio_mode=Gpio_mode_ain; Gpio_init (GPIO_ADC1,&gpio_initstructure); Adc_initstructure.adc_mode= Adc_mode_independent;//ADC1 and ADC2 work in standalone modeAdc_initstructure.adc_scanconvmode = ENABLE;//working in scan mode
Adc_initstructure.adc_continuousconvmode = ENABLE;//conversion work in continuous mode
Adc_initstructure.adc_externaltrigconv = Adc_externaltrigconv_none;//The conversion is triggered by the software and the Adc_cmd program needs to be invokedAdc_initstructure.adc_dataalign = Adc_dataalign_right;//Right alignment of ADC dataAdc_initstructure.adc_nbrofchannel =1;//ADC channel number is 1Adc_init (ADC1, &adc_initstructure);//specifying the channel and conversion period for ADC conversionsAdc_regularchannelconfig (ADC1, Adc_channel_10,1, ADC_SAMPLETIME_55CYCLES5);
#ifdef use_adc1_dma_per adc_dmacmd (ADC1, ENABLE); //ADC1 DMA Request enable#endifadc_cmd (ADC1, ENABLE); //ADC1 Enable
adc_resetcalibration (ADC1); // reset ADC1 Calibration Register while (Adc_getcalibrationstatus (ADC1)) // Wait for the ADC1 calibration register reset to complete {}adc_startcalibration (ADC1); //ADC1 into the calibration state while (Adc_getcalibrationstatus (ADC1)) // Wait for ADC1 calibration to complete {}
Adc_softwarestartconvcmd (ADC1, ENABLE); //ADC1 software trigger mode start
Here's an important point of knowledge: the rule Group and injection group for the ADC channel
In AD conversion, the rule group defines the order of the ADC scan channels, sequentially scanning the ADC channel from small to large in accordance with the order of the rule group configuration, while the injection group takes precedence over the rule group, and when the injection group conversion is triggered it interrupts the scan of the rule group and performs a channel scan of the injection group, similar to preemption in interrupts. The conversion of this ADC uses only one port, which is not considered, but when the multi-channel Ad/da is collected, the rule group and injection group are configured according to the actual situation.
Note: Configuring the channel's rule group and injection group is a must in the Enable ADC before the conversion.
After the initialization is complete, the rest is simple, as long as the ADC processing of the digital amount, in the conversion into shaping variables, can be sent through the serial port received, as follows:
//direct access to the current ADC converted values, conversion and output, CPU participation in the transferAdvalue =Adc_getconversionvalue (ADC1); Precent= (advalue* -/0x1000); Voltage= precent* -;p rintf ("\r\n\n Adcconvertedvalue is 0x%x, Percent are%d%%, voltage is%D.%D%DV", Advalue,precent,voltage/ +, (voltage% +)/ -, (voltage% -)/Ten);p rintf ("\ r \ n ADC output"); Arm_delay (2000000);
Note: Using the printf function as input and output, including header file #include "stdio.h" ; Target next to select Use MicroLib , otherwise there will be no output. (the serial port section has been explained, important) .
This enables the acquisition and output of the voltage of the potentiometer, but this is not the end, as today we are going to learn another peripheral-DMA module that is also widely used.
First we need to know what DMA is for? The main function of the DMA module is to move data in memory or peripherals freely, without CPU involvement, and to store the sequential storage of large amounts of data by storing the self-offsets of pointers (this is important in the field of communication). As with the above, learning DMA, you must first check the manual:
、
From this we can conclude that the ADC1 corresponds to Channel 1, because the ADC is operating mode, after understanding the following structure body:
typedefstruct{u32 dma_peripheralbaseaddr; //defined peripheral Base address u32 dma_memorybaseaddr; //defined memory Base address u32 Dma_dir; //peripheral as the source of data transfer or destination u32 dma_buffersize; //The size of the DMA cache for DMA channels, in units of data u32 Dma_peripheralinc; //The peripheral address register is incremented or unchanged u32 Dma_memoryinc; //memory address register incremented or unchanged u32 dma_peripheraldatasize; //Peripheral Data Width u32 dma_memorydatasize; //Memory Data width u32 Dma_mode; //How DMA caching works u32 dma_priority; //DMA Work Priority u32 dma_m2m; //DMA work is memory-to-memory or peripheral-to-memory} dma_inittypedef;
We can draw the following conclusions:
Define uint16_t Adcconvertedvalue; //Receive memory address
1. Peripheral base Address is adc1_dr_address or (uint32_t) & (ADC1->DR)
2. Data from the ADC peripherals, transfer the address to memory
3. Working in cycle mode and not self-increasing
According to the structure of the above configuration dma_initstructrue parameters, initialize the following:
Dma_inittypedef dma_initstructure; Rcc_ahbperiphclockcmd (RCC_AHBPERIPH_DMA1, ENABLE); Dma_deinit (DMA1_CHANNEL1); //reset ADC1 corresponding DMA channel Dma1_channel1dma_initstructure.dma_peripheralbaseaddr= (uint32_t) & (ADC1->DR);//ADC1 Rule Group Conversion Value Register address as base addressDma_initstructure.dma_memorybaseaddr = (uint32_t) &ADCConvertedValue;//base address for data transfer to memoryDma_initstructure.dma_dir = DMA_DIR_PERIPHERALSRC;//Peripherals as data sourceDma_initstructure.dma_buffersize =1;//can increase the length of the addressDma_initstructure.dma_peripheralinc = dma_peripheralinc_disable;//peripheral address does not allow self-incrementDma_initstructure.dma_memoryinc = dma_memoryinc_disable;//memory address does not allow self-incrementDma_initstructure.dma_peripheraldatasize = Dma_peripheraldatasize_halfword;//peripheral data is half word 16bitDma_initstructure.dma_memorydatasize = Dma_memorydatasize_halfword;//memory data is half word 16bitDma_initstructure.dma_mode = Dma_mode_circular;//DMA working in loop modedma_initstructure.dma_priority = Dma_priority_high;//High DMA Request prioritydma_initstructure.dma_m2m = dma_m2m_disable;//DMA is peripheral to memory transferDma_init (Dma1_channel1, &dma_initstructure); Dma_cmd (Dma1_channel1, ENABLE); /*DMA Enable*/
Also add in the main function:
//The amount of digital DMA transferred from the ADC is processed, converted and output, and the DMA controller is used to transmitAdcconvertedvaluelocal =Adcconvertedvalue; Precent= (adcconvertedvaluelocal* -/0x1000); Voltage= precent* -;p rintf ("\r\n\n Adcconvertedvalue is 0x%x, Percent are%d%%, voltage is%D.%D%DV", Adcconvertedvaluelocal,precent,voltage/ +, (voltage% +)/ -, (voltage% -)/Ten);p rintf ("\ r \ n ADC DMA output");
This enables the transmission of DMA through the ADC.
Code Download: http://files.cnblogs.com/files/zc110747/7.ADC-DMA.7z
The following comes from external sources and personal summaries, which hopefully are useful for understanding the DMA module:
1.DMA transfer data from one address space to another address space, which is implemented by the DMA controller, does not rely on the CPU of a large number of data collection and transmission, saving CPU resources.
2.DMA work consists of four processes
DMA Request-〉DMA Response-〉DMA transfer-〉DMA end
There are three ways to transfer the 3.DMA
(1) Stop the CPU to visit the memory;
When the peripheral device has a batch of data to be transmitted, the DMA sends a stop signal to the CPU, the CPU stops accessing the memory, releases the relevant bus control, and the DMA obtains the bus control and begins to pass the data, and then gives the bus control to the CPU after completion. Once the DMA transfer is complete.
Advantages: Simple control for high-speed group transfer
Disadvantage: Memory performance is not played, part of the time memory is in idle state. This is because the DMA transfer phase has a lot of time to read the peripheral data, the bus is certainly idle for some time, and this part of the time is enough for the CPU to access the memory.
(2) periodic misappropriation; (This is the way ADC conversions are used)
When the I/O device does not have a DMA request, the CPU accesses the memory as required by the program, and once the I/O device has a DMA request, one or several memory cycles are appropriated by the I/O device.
(3) DMA and CPU alternate memory visits.
1.7 ADC Analog-to-digital conversion measurement level (normal and DMA modes)