Classic_STM32_ADC multi-channel sampling example

Publisher:TechVoyagerLatest update time:2015-08-14 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
STM32 ADC multi-channel conversion
Description: Use ADC to continuously collect 11 analog signals and transfer them to memory by DMA. ADC is configured to scan and continuously convert mode, and the ADC clock is configured to 12MHZ. After each conversion, DMA transfers the converted data to memory in a loop. ADC can collect N times continuously to calculate the average value. Finally, the final conversion result is transmitted through the serial port.
The program is as follows:
#i nclude "stm32f10x.h" //This header file includes the definition of all peripheral registers, bits, and memory mapping of STM32F10x
#i nclude "eval.h" //Header file (including function declarations of serial port, buttons, and LEDs)
#i nclude "SysTickDelay.h"
#i nclude "UART_INTERFACE.h"
#i nclude

#define N 50 //50 samples per channel
#define M 12 //12 channels

vu16 AD_Value[N][M]; //Used to store ADC conversion results, also the target address of DMA
vu16 After_filter[M]; //Used to store the result after averaging
int i;



void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //Because the USART1 pin is connected to the GPIO port in multiplexed form, multiplexed push-pull output is used
GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);



//PA0/1/2 as analog channel input pins
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0| GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //Analog input pin
GPIO_Init(GPIOA, &GPIO_InitStructure);

//PB0/1 is used as analog channel input pin
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //Analog input pin
GPIO_Init(GPIOB, &GPIO_InitStructure);

//PC0/1/2/3/4/5 is used as analog channel input pin
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //Analog input pin
GPIO_Init(GPIOC, &GPIO_InitStructure);
}

}


void RCC_Configuration(void)
{
ErrorStatus HSEStartUpStatus;

RCC_DeInit(); //RCC system reset
RCC_HSEConfig(RCC_HSE_ON); //Turn on HSE
HSEStartUpStatus = RCC_WaitForHSEStartUp(); //Wait for HSE preparation Good
if(HSESstartUpStatus == SUCCESS)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Enable Prefetch Buffer
FLASH_SetLatency(FLASH_Latency_2); //Set 2 Latency cycles
RCC_HCLKConfig(RCC_SYSCLK_Div1); //AHB clock = SYSCLK
RCC_PCLK2Config(RCC_HCLK _Div1); //APB2 clock = HCLK
RCC_PCLK1Config(RCC_HCLK_Div2); //APB1 clock = HCLK/2
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_6); //PLLCLK = 12MHz * 6 = 72 MHz
RCC_PLLCmd(ENABLE); //Enable PLL
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait till PLL is ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //Select PLL as system clock source
while(RCC_GetSYSCLKSource() != 0x08); //Wait till PLL is used as system clock source

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB
| RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO |RCC_APB2Periph_USART1, ENABLE ); //Enable ADC1 channel clock, each pin clock

RCC_ADCCLKConfig(RCC_PCLK2_Div6); //72M/6=12,ADC maximum time cannot exceed 14M
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //Enable DMA transmission

}
}


void ADC1_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;

ADC_DeInit(ADC1); //Reset all registers of peripheral ADC1 to default valuesADC_InitStructure.ADC_Mode


= ADC_Mode_Independent; //ADC working mode: ADC1 and ADC2 work in independent modeADC_InitStructure.ADC_ScanConvMode
= ENABLE; //Analog-to-digital conversion works in scan modeADC_InitStructure.ADC_ContinuousConvMode
= ENABLE; //Analog-to-digital conversion works in continuous conversion modeADC_InitStructure.ADC_ExternalTrigConv
= ADC_ExternalTrigConv_None; //External trigger conversion is turned offADC_InitStructure.ADC_DataAlign
= ADC_DataAlign_Right; //ADC data is right-
alignedADC_InitStructure.ADC_NbrOfChannel = M; //Number of ADC channels for regular conversion in
sequenceADC_Init(ADC1, &ADC_InitStructure); //Initialize the registers of the peripheral ADCx according to the parameters specified in ADC_InitStruct


//Set the regular group channels of the specified ADC, set their conversion order and sampling time
//ADC1, ADC channel x, regular sampling order value is y, sampling time is 239.5 cycles
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig
(ADC1, ADC_Channel_3, 4, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 5, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 6, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 7
, ADC_SampleTime_239Cycles5 ); ADC_RegularChannelConfig( ADC1, ADC_Channel_11,
8, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 9, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 10, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 11, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 12, ADC_SampleTime_239Cycles5 );

// Enable DMA support for ADC (to implement DMA function, you also need to configure DMA channel and other parameters independently)
ADC_DMACmd(ADC1, ENABLE);[page]


ADC_Cmd(ADC1, ENABLE); // Enable the specified ADC1

ADC_ResetCalibration(ADC1); // Reset the calibration register of the specified ADC1

while(ADC_GetResetCalibrationStatus (ADC1)); // Get the status of the ADC1 reset calibration register, set the status and wait


ADC_StartCalibration(ADC1); // Start the calibration status of the specified ADC1

while(ADC_GetCalibrationStatus(ADC1)); //Get the calibration procedure of the specified ADC1, set the status to wait


}


void DMA_Configuration(void)
{

DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel1); //Reset DMA channel 1 register to default valueDMA_InitStructure.DMA_PeripheralBaseAddr
= (u32)&ADC1->DR; //DMA peripheral ADC base
addressDMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value; //DMA memory base
addressDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //Memory as the destination of data transmissionDMA_InitStructure.DMA_BufferSize
= N*M; //DMA channel DMA buffer sizeDMA_InitStructure.DMA_PeripheralInc
= DMA_PeripheralInc_Disable; //Peripheral address register unchangedDMA_InitStructure.DMA_MemoryInc
= DMA_MemoryInc_Enable; //Memory address register incrementDMA_InitStructure.DMA_PeripheralDataSize
= DMA_PeripheralDataSize_HalfWord; //Data width is 16
bitsDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //Data width is 16
bitsDMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //Work in circular buffer modeDMA_InitStructure.DMA_Priority
= DMA_Priority_High; //DMA channel x has high priorityDMA_InitStructure.DMA_M2M
= DMA_M2M_Disable; //DMA channel x is not set up for memory to memory transferDMA_Init
(DMA1_Channel1, &DMA_InitStructure); //Initialize DMA channel according to the parameters specified in DMA_InitStruct

}


//Configure all peripheralsvoid
Init_All_Periph(void)
{

RCC_Configuration();

GPIO_Configuration();

ADC1_Configuration();

DMA_Configuration();

//USART1_Configuration();
USART_Configuration(9600);


}



u16 GetVolt(u16 advalue)

{

return (u16)(advalue * 330 / 4096); //The result is enlarged 100 times to facilitate the decimal below

}




void filter(void)
{
int sum = 0;
u8 count;
for(i=0;i<12;i++)

{

for ( count=0;count
{

sum += AD_Value[count][i];

}

After_filter[i]=sum/N;

sum=0;
}

}




int main(void)
{

u16 value[M];

init_All_Periph();
SysTick_Initaize();


ADC_SoftwareStartConvCmd(ADC1, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE); //Start DMA channelwhile
(1)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//Wait for the transmission to complete, otherwise the first bit of data is easily lost

filter();
for(i=0;i<12;i++)
{
value[i]= GetVolt(After_filter[i]);

printf("value[%d]:t%d.%dvn",i,value[i]/100,value[i]0) ;
delay_ms(100);
}
}

}
Summary
The two macro definitions in this program, M and N, represent the number of channels and the number of conversions for each channel, respectively, and their values ​​can be modified.
Problems that have occurred: When configuring the clock, you need to know the external crystal oscillator to accurately configure the clock. When converting the conversion value from binary to decimal, you must first expand it by 100 times to facilitate the display of decimals. Finally, add this code before the printf statement when outputting to the serial port to prevent the first bit of data from being lost: while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
Keywords:STM32 Reference address:Classic_STM32_ADC multi-channel sampling example

Previous article:STM32 learning notes-preparation
Next article:STM32 study notes - RCC system clock configuration

Recommended ReadingLatest update time:2024-11-16 14:30

STM32 USART DMA transmission (transfer)
Problem Description:      I have a requirement that after AD samples a certain amount of data, it is sent out by serial port DMA. Since AD ​​uses double buffering, the starting memory address and the number of transfers need to be reset each time DMA is started (these are all natural). However, when I started debugg
[Microcontroller]
STM32 hardware IIC and 51 analog IIC communication
IIC Introduction   The IIC protocol stipulates that the data transmitted on SDA must remain stable during the high level of SCL, and the data on SDA can only change during the low level of SCL. During IIC, data is placed on SDA at the rising edge of the pulse, and data is read from SAD at the falling edge of the pul
[Microcontroller]
STM32 simple data transmission method and communication protocol (suitable for serial port and general bus)
introduction In the general project development process, two or more microcontrollers are often required to communicate to complete data transmission. For example, a quadcopter wirelessly transmits data back to the ground station during flight, therapeutic equipment needs to transmit the patient and machine operation
[Microcontroller]
STM32 SPI slave routine
#include "stm32f10x.h" /* RCC clock configuration*/ void RCC_config(void) {  ErrorStatus HSEStartUpStatus; /* RCC registers are set to default configuration*/ RCC_DeInit(); /* Turn on external high-speed clock*/ RCC_HSEConfig(RCC_HSE_ON); /* Wait for external high-speed clock to stabilize*/ HSEStartUpStatus = RCC_Wa
[Microcontroller]
CTSD Precision ADCs – Part 2: Introducing the CTSD Architecture for Signal Chain Designers
This article will introduce continuous-time Σ-Δ (CTSD) ADC technology in a different way than the traditional approach, so that signal chain designers can understand this new and easy-to-use precision ADC technology by imagining it as a simple system connecting certain known components. In Part 1, we focused on the ke
[Analog Electronics]
CTSD Precision ADCs – Part 2: Introducing the CTSD Architecture for Signal Chain Designers
STM8S003/903 using ADC interrupt function
Regarding the ADC interrupt function of the STM8S003/903 chip (including two cases), record your understanding: 1. When using ADC interrupt for a single channel: If you only need to collect one analog quantity in the project, and want to use interrupt mode to obtain the AD value, then set it as follows: void ADC1_
[Microcontroller]
STM32-Library Development-Address Mapping
1. stm32 has AHB, APB2, and APB1 buses.    The APB2 peripheral address space is from 0x40010000 to 0x40013FFF. The first address is called the base address. 2. The port configuration register in the reference manual has an address offset of 0x04, so the address of GPIOC_CRH is GPIOC_BASE+0x04   GPIO_TypeDef structur
[Microcontroller]
Reasonable selection of high-speed ADC to achieve undersampling
Undersampling or violating the Nyquist criterion is a technique often used in ADC applications. Radio frequency (RF) communications and high performance test equipment such as oscilloscopes are some examples. Confusion often arises in this "gray" area as to whether it is necessary to obey the Nyquist criterion to ob
[Analog Electronics]
Reasonable selection of high-speed ADC to achieve undersampling
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号