We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi,
I want to program STM32F103 in which define an array that is completed with ADC value. I need to trigger the ADC with timer and also use DMA. It means that when the array complete, the DMA_IRQ Handler send this array by USART channel. I wrote this code but it doesn't work.
I would be appreciate if you help me to correct this program.
#include "stm32f10x.h" #define ADC1_DR_Address ((uint32_t)0x4001244C) uint16_t array [32]; DMA_InitTypeDef DMA_InitStructure; int main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 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_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); NVIC_InitTypeDef sara3; sara3.NVIC_IRQChannel = DMA1_Channel1_IRQn; sara3.NVIC_IRQChannelPreemptionPriority = 0; sara3.NVIC_IRQChannelSubPriority = 0; sara3.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&sara3); TIM_TimeBaseInitTypeDef Tim_TimeBaseStructure; TIM_TimeBaseStructInit(&Tim_TimeBaseStructure); Tim_TimeBaseStructure.TIM_Period = 9000; Tim_TimeBaseStructure.TIM_Prescaler = 0x0; Tim_TimeBaseStructure.TIM_ClockDivision = 0x0; Tim_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &Tim_TimeBaseStructure); TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); /* TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0x7F; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OC1Init(TIM2, &TIM_OCInitStructure); */ ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5); //ADC_SoftwareStartConvCmd(ADC1,ENABLE); DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)array; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 32; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART1, USART_IT_TXE, ENABLE); USART_ClearFlag(USART1,USART_FLAG_TC); DMA_ITConfig (DMA1_Channel1, DMA_IT_TC,ENABLE); DMA_Cmd(DMA1_Channel1, ENABLE); ADC_Cmd(ADC1, ENABLE); ADC_DMACmd(ADC1, ENABLE); USART_Cmd(USART1, ENABLE); TIM_Cmd(TIM2, ENABLE); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); while (1); } void DMA1_Channel1_IRQHandler(void) { uint8_t i = 0; if( DMA_GetITStatus(DMA1_FLAG_TC1) ) { for(i = 0;i < 32 ; i++){ USART_SendData(USART1, (uint8_t) array[i]); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} USART_SendData(USART1, (uint8_t) array[i]>> 8); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} } DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)array; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 32; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); ADC_DMACmd(ADC1, ENABLE); DMA_Cmd(DMA1_Channel1, ENABLE); DMA_ClearITPendingBit(DMA1_IT_TC1); DMA_ClearITPendingBit(DMA1_IT_GL1); } }
I add some init code that uses the STM32F407 and this show's the setup of 4 ADC1 channels handled by DMA transfer.
#define Num_used_ADC_Channels 5 // how many ADC channels should be handled? // Wieviel ADC-Kanäle sollen ausgelesen werden? !!! #define Num_Of_Used_Buffers Num_used_ADC_Channels // how many memory should be used by DMA ? volatile uint16_t ADCBuffer[Num_Of_Used_Buffers + 2] = { 0x00AA,0,0,0,0,0,0x00BB }; // DMA-Buffer - 5 words enum __ADC_CHAN_BUFF_ORDER__ { CH0 = 1, CH1 = 2, VBAT = 3, TEMP = 4, VREF = 5 }; // Weleche Reihenfolge sollen die ADC Kanöäle gelesen werden? void Init_ADC ( void ) { // ############## ADC ########################################################################################################## // ---------- Configure PB0 and PB1 (ADC Channel1 and ADC Channel2 ) as analog input ------------------ // // GPIOB function block clock enable RCC_APB2PeriphClockCmd ( RCC_APB2Periph_ADC1, ENABLE ); // clock to ADC1 RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOB, ENABLE ); // clock to PortB GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; // Init AIN0 / AIN1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; // alternative mode "Analog in" GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init ( GPIOB, &GPIO_InitStructure ); // Init GPIO-PORTA as Analog input // DMA2 Stream0 configuration ------------------------------------------------------------------------------------------------ // // Enable DMA2 clock RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_DMA2, ENABLE ); DMA_DeInit ( DMA2_Stream0 ); DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) ADC1_DR_Address; // source DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &ADCBuffer[1]; // destination - start to copy by dma at the second element of the array DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; // Transfertype DMA_InitStructure.DMA_BufferSize = Num_used_ADC_Channels; // Num of ADC register that should transfered DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // Register address is static - no increment. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // auto increment the memory at each transfer DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // transfer size of source register DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // transfer size of destinantion (array) DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // at the end of dma transfer cycle, starts again. DMA_InitStructure.DMA_Priority = DMA_Priority_Low; // system load depended - i decide me to low priority. DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; // DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; // DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; // DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // DMA_Init ( DMA2_Stream0, &DMA_InitStructure ); DMA_Cmd ( DMA2_Stream0, ENABLE ); // ------------------ ADC1 configuration ------------------------------------------------------- // ADC_DeInit(); ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles; ADC_CommonInit(&ADC_CommonInitStructure); // ########################### ADC1 Init ######################################### ADC_InitStructure.ADC_Resolution = RESOLUTION; // Auflösung definiert in ADC1.h ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // dauerhaft lesen und wandeln ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; // ADC_InitStructure.ADC_ExternalTrigConv = 0; // ohne Trigger ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // Conversions are 12 bit - put them in the lower 12 bits of the result ADC_InitStructure.ADC_NbrOfConversion = Num_used_ADC_Channels; // num of adc-channels ADC_Init (ADC1, &ADC_InitStructure); ADC_DMACmd ( ADC1, ENABLE ); // Enable ADC1 DMA // ######### ADC1 regular conversation mode configuration #################################### // ADC , CHANNEL, DMA MemoryOrder, SampleTime // ADC_RegularChannelConfig(ADC1, ADC_Channel_8, CH0, ADC_SampleTime_15Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_9, CH1, ADC_SampleTime_15Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat, VBAT, ADC_SampleTime_15Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, TEMP, ADC_SampleTime_15Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_Vrefint, VREF, ADC_SampleTime_15Cycles); ADC_VBATCmd ( ENABLE ); // Enable VBAT at channel 18 ADC_TempSensorVrefintCmd ( ENABLE ); // Enable TempSensor and Vrefint at channels 16 and 17 ADC_DMARequestAfterLastTransferCmd ( ADC1, ENABLE ); // Enable DMA request after last transfer (Single-ADC mode) ADC_Cmd ( ADC1, ENABLE ); // Enable ADC1 ADC_SoftwareStartConv ( ADC1 ); // Start ADC1 Software Conversion return; }
take care of the volatile declared array variable
Juppeck
HEY.
i wanna to read the timer value and put it onto the adc. it must use dma channels 3 or 5. how can i do it? code gotta be working by two days. plz post examples
The world haven't figured out yet how to put the timer value onto the ADC. But if you instead feed it to the DAC, you get a nice sawtooth output.
Quit wasting time trolling on the internets and get busy then.