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); }