stm32 uses DMA to transfer 9 ADCs using interrupts to process data

The advantage of using the interrupt method is that the DMA transfer BUF will not be called elsewhere. If called or modified accidentally, it may crash. The specific reasons have not been investigated.

Pay attention to whether the interrupt function is consistent with the .s file, otherwise it will crash.

Modify the content of the interrupt function as required.

dma_adc.h

#ifndef _DMA_ADC_
#define _DMA_ADC_

#include "sys.h"

#define ADC1_DR_Address ((u32)0x40012400+0X4C)

extern u16 ADC_buf[10]; //DMA transfer BUF
extern u32 ADC_BUF[10]; //Save BUF after filtering

extern u8 ADC_BUF_flag; //Complete flag after filtering

 void ADC1_DMA_init(void);

#endif

dma_adc.c

#include "dma_adc.h"
#include "serial.h"
#include "nrf_info.h"
u16  ADC_buf[10];
u32  ADC_BUF[10];
u8  ADC_BUF_flag=0;
 void ADC1_DMA_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);

	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; //通道引脚
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0; //Channel pin
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	DMA_InitTypeDef DMA_InitStructure;
	ADC_InitTypeDef	ADC_InitStructure;

	DMA_DeInit(DMA1_Channel1);
	
	
	NVIC_InitTypeDef NVIC_InitStructure;
  
  /* Configure one bit for preemption priority */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  /* Configure DMA interrupt source */
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	

	DMA_InitStructure.DMA_PeripheralBaseAddr=ADC1_DR_Address; //ADC data register address
	DMA_InitStructure.DMA_MemoryBaseAddr=(u32)ADC_buf; //Transfer ADC1_DR_Address data to ADC_buf
	DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC; //Data transfer direction, peripheral as data source
	DMA_InitStructure.DMA_BufferSize=9; //Transfer data
	DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//Peripheral address fixed
	DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord; //Indicates the data size of each transfer
	DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure.DMA_Mode=DMA_Mode_Circular; //Circular transmission
	DMA_InitStructure.DMA_Priority=DMA_Priority_High; //DMA channel priority
	DMA_InitStructure.DMA_M2M=DMA_M2M_Disable; //Disable memory to memory transfer
	DMA_Init(DMA1_Channel1,&DMA_InitStructure);
	
	DMA_Cmd(DMA1_Channel1,ENABLE); //Enable
	
	DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE); //Generate interrupt after configuring DMA transmission
	
	
	
	ADC_InitStructure.ADC_Mode=ADC_Mode_Independent; //Independent mode
	ADC_InitStructure.ADC_ScanConvMode=ENABLE; //Scan mode for multi-channel acquisition
	ADC_InitStructure.ADC_ContinuousConvMode=ENABLE; //Enable continuous conversion
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//b Do not use external trigger conversion
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//The acquisition data is right aligned
	ADC_InitStructure.ADC_NbrOfChannel=9; //Number of conversions
	ADC_Init(ADC1,&ADC_InitStructure);
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);	//6分频,12HZ
	
	//scan order, 55.5 per cycle
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_4,5,ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_5,6,ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_6,7,ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_7,8,ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_8,9,ADC_SampleTime_55Cycles5);
	
	ADC_DMACmd(ADC1,ENABLE); //Send a request to DMA
	
	ADC_Cmd(ADC1,ENABLE);
	
	ADC_ResetCalibration(ADC1); //Reset calibration register
	
	while(ADC_GetResetCalibrationStatus(ADC1)); //Wait for calibration to complete
	
	ADC_StartCalibration(ADC1); //ADC correction

	while(ADC_GetCalibrationStatus(ADC1)); //Wait for calibration to complete
	
	ADC_SoftwareStartConvCmd(ADC1,ENABLE); //Software trigger ADC conversion

	
}

static u8 count=0;


extern "C" void DMA1_Channel1_IRQHandler(void) //DMA interrupts transmission and processes data.
{         
					if(ADC_BUF_flag==0)
					{
              if(count==0)
							{
								
									//AD clear
									for(int i=0;i<9;i++)
									{
										ADC_BUF[i]=0;
									}
							}
	
							for(int j=0;j<9;j++)
							{
								ADC_BUF[j]+=ADC_buf[j];
							}
							
							count++;

							if(count==30)
							{
								// take the average filter
								for(int i=0;i<9;i++)
								{
										ADC_BUF[i]/=count;
										
								}
										//--------------------------------------After getting the filter value---- --------
										nrf_info.ch1=((ADC_BUF[0]*256)/4096);
										nrf_info.ch2=((ADC_BUF[1]*256)/4096);
										nrf_info.ch3=((ADC_BUF[2]*256)/4096);
										nrf_info.ch4=((ADC_BUF[3]*256)/4096);
										nrf_info.ch5=((ADC_BUF[4]*256)/4096);
										nrf_info.ch6=((ADC_BUF[5]*256)/4096);
										nrf_info.ch7=((ADC_BUF[6]*256)/4096);
										nrf_info.ch8=((ADC_BUF[7]*256)/4096);
										//---------------------------------------send data------- ------------
														if(nrf_info.send_mes())
													{
														//printf("send OK\r\n");
														PCout(13)=~	PCout(13);
													}
													else
													{
														PCout(13)=1;
														//printf("send ERROR\r\n");
													}
								
								count=0;
							  ADC_BUF_flag=1;
							}	
						}	
						// printf("I was interrupted\r\n");
						
              DMA_ClearITPendingBit(DMA1_IT_TC1);              
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325585757&siteId=291194637