2010-03-20 07:24 AM
ADC1 and temperature reading
2011-05-17 04:44 AM
Yes. I do it in my code which uses ST's STandard Peripheral Library.
--- // Configure DMA #1 Channel 1 (dedicated to ADC1--see Figure 18/Table 40 of // the STM32F103xx Reference Manual) to fill the adc_dma_buffer[] array with // ADC results automatically. DMA_DeInit(DMA1_Channel1); dma_setup.DMA_PeripheralBaseAddr = (uint32_t) &(ADC1->DR); dma_setup.DMA_MemoryBaseAddr = (uint32_t) &adc_dma_buffer; dma_setup.DMA_DIR = DMA_DIR_PeripheralSRC; dma_setup.DMA_BufferSize = sizeof(adc_dma_buffer) / sizeof(uword); dma_setup.DMA_PeripheralInc = DMA_PeripheralInc_Disable; dma_setup.DMA_MemoryInc = DMA_MemoryInc_Enable; dma_setup.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; dma_setup.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; dma_setup.DMA_Mode = DMA_Mode_Circular; dma_setup.DMA_Priority = DMA_Priority_High; dma_setup.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &dma_setup); DMA_Cmd(DMA1_Channel1, ENABLE); // Enable DMA transfer complete interrupts (i.e. A/D results are // available for processing). DMA_ITConfig(DMA1_Channel1, DMA1_FLAG_TC1, ENABLE); ... // Setup ADC1. It's configured to scan the ADC channels defined by // 'adc1_index_t' and DMA the results into 'adc_dma_buffer[]'. A/D // conversions are started manually (software) every 1mS in // 'adc_sampling_isr()'. adc_setup.ADC_Mode = ADC_Mode_Independent; adc_setup.ADC_ScanConvMode = ENABLE; adc_setup.ADC_ContinuousConvMode = DISABLE; adc_setup.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; adc_setup.ADC_DataAlign = ADC_DataAlign_Right; adc_setup.ADC_NbrOfChannel = 4; ADC_Init(ADC1, &adc_setup); // Enable temperature sensor & ADC reference voltage channels for debugging // purposes (they're not needed or used for anything). // // From the STM32F103xB datasheet: Vrefint = 1.16-1.24V from -40C to +85C // with a typical value of 1.20V. // On the hardware Vref+ = 3.3V and Vref- = 0V. // Thus the reference channel should be between 1.16/3.30*4096 = 1439 and // 1.24/3.30*4096 = 1539 counts with a typical value of 1489/1490. ADC_TempSensorVrefintCmd(ENABLE); // Setup ADC1 regular channel scanning conversion order. // The sample time for the temperature/reference channels must be >= 17.1uS // (specified in the STM32F103xB datasheet). // Therefore set the sample time, for each channel, to the maximum of // 239.5 clocks. The total conversion time is the sample time + 12.5 clocks // or 252 clocks. That is 28uS (@72 MHz) / 31.5uS (@64MHz) per channel. ADC_RegularChannelConfig(ADC1, CHANNEL_1, CHANNEL_1_INDEX+1, ADC_SampleTime_239Cycles5); #ifdef PHOTOCELL_2_CHANNEL ADC_RegularChannelConfig(ADC1, CHANNEL_2, CHANNEL_2_INDEX+1, ADC_SampleTime_239Cycles5); #endif ADC_RegularChannelConfig(ADC1, TEMPERATURE_CHANNEL, TEMPERATURE_INDEX+1, ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1, REFERENCE_CHANNEL, REFERENCE_INDEX+1, ADC_SampleTime_239Cycles5); // Enable ADC1 DMA. ADC_DMACmd(ADC1, ENABLE); // Enable ADC1. ADC_Cmd(ADC1, ENABLE);2011-05-17 04:44 AM
Thanks Stuart,
I managed to read out the temperature. I added it like you wrote with just putting the sensor channel 16 as a second conversion and second in order for the DMA buffer. I also checked the Vref which in my case was 1503 so just a bit higher as the typical value (1.21). I just have one problem I have to solve because my channel 1 conversion has to be done in 1.5 µs started with a 25µs interrupt timer. I have some FIR code that handles the EOC interrupt for channel 1 ( takes 16µs ). This code must not be executed when the EOC of the sensor is firing of course. I will look into the spec if there's a flag on which I can test what kind of ADC channel conversion is actually done. So I can skip if the sensor is coming along every 17µs. PS Be careful in your code you have a define put over the second ADC (photocell) but not over the amount channels in the init section which is always 4 and not 3 in case the define isn't defined ;) Anyway thanks for putting me on track. Guy( my username before this forum changed was guyvo67 )
2011-05-17 04:44 AM
Thanks for the warning but the code posted here is a modified version of the original. I deliberately changed the number of channels to a constant of 4 (actual code uses a definition) for clarity but forgot to remove the #ifdef.
BTW if you're using a device with 2 or more A/D's you could use the first to convert the temperature/reference (only connected to ADC1) and the second to convert your input. Each A/D has its own DMA but they're connected to the same port pins. In short you can perform parallel conversions to meet your timing needs.2011-05-17 04:44 AM
BTW if you're using a device with 2 or more A/D's you could use the first to convert the temperature/reference (only connected to ADC1) and the second to convert your input. Each A/D has its own DMA but they're connected to the same port pins. In short you can perform parallel conversions to meet your timing needs.
Do you mean that I could link ADC1 to the sensor with DMA channel and link my PINA.1 input as AIN to ADC2 with another DMA channel so I can get separated triggers to act upon ?
I already saw in pin layout that PINA.1 can be mapped to ADC123_IN1. The bad thing is that ADC2 cannot be connected to any DMA channel. So my fast conversion on PINA.1 can only be done by reading the converted value without DMA or by using ADC3. ADC3 has DMA support on ch 5 of DMA2 bank. I could also try the dual mode using ADC1 as master and ADC2 as slave. The spec says:
Only ADC1 and ADC3 have this DMA capability. ADC2-converted data can be transferred in
dual ADC mode using DMA thanks to master ADC1.
I will give ADC3 with DMA a try and come back here with my results.
1h later after coding the above:
Results are fine for ADC1/3 on both on DMA. Nothing special to be done just write the init code and enable the ADC & DMA clocks. If on interrupt not forget to clear the flag.
My questions are answered !
Many thanks Stuart to give the hints ;)
Guy
2011-05-17 04:44 AM
Yes, exactly.
I didn't know ADC2 didn't have DMA capability but since you were able to use ADC3 with DMA it all worked out well :)