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
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);
Previous article:STM32 learning notes-preparation
Next article:STM32 study notes - RCC system clock configuration
Recommended ReadingLatest update time:2024-11-16 14:30
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- FAQ_About the pulse problem when the output port of BlueNRG-2 remains at a low level in low power mode
- There are still some problems with the PCB diagram drawn by a novice
- 【TGF4042 signal generator】+ Dual channel comparison test
- 3. Microcontrollers used in previous "Control" competitions
- Can you share your experience of learning FPGA?
- Why are the added including paths empty after installing TI products? Is it an installation or configuration problem?
- How to detect motor speed?
- TCP network communication problem
- Using Ginkgo USB-ADC and heart rate sensor to implement a heart rate tester with Android APP source code
- Jump-start your new design with the TI motor control software development kit!