2017-06-09 03:06 AM
I wish to use ADC1 to measure 6 channels and to have the results DMAd into memory.
I am using CubeMX V4.21 and I think that I have set the parameters up correctly
(See attached screen snip ADC_DMA_1 to 3.PNG)
This sequence is to be triggered by S/W to run once, terminate and then run again sometime later.
(This is in a loop for testing at the moment).
The DMA happens as I am seeing the ADC readings appear in the adc1_data array and I get the DMA half complete interrupt handler being called but not the end of sequence interrupt.
What am I doing wrong please.....
My code is :-
uint16_t adc1_data[6];#define ADC1_BUFFER_SIZE_IN_BYTES 12
#define ADC1_TEMP1_OFFSET 0
#define
ADC1_TEMP2_OFFSET 1#define
ADC1_VBOOST_OFFSET 2#define
ADC1_VHLC_OFFSET 3#define
ADC1_INTERNAL_TEMP_OFFSET 4#define
ADC1_VREF_OFFSET 5volatile bool adc1_active_flag;
void start_adc1(void){ HAL_StatusTypeDef status;set_VDDA_PWR_EN(ANALOG_POWER_ON);
set_nVMON_ENABLE(VMON_ENABLE_ON); set_nTEMP_SENSOR_PWR_EN(TEMP_SENSOR_POWER_ON);adc1_active_flag = TRUE;
osDelay(2);
status = HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
if(HAL_OK != status) { // Blah }status = HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_data, ADC1_BUFFER_SIZE_IN_BYTES);
if(HAL_OK != status) { // Blah }}void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{ static bool apapap; if(ADC1 == hadc->Instance) { // Voltage subsystem... apapap = TRUE; // <<< Gets here.... } if(ADC2 == hadc->Instance) { // Blah }if(ADC3 == hadc->Instance)
{ // Blah }}void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){ if(ADC1 == hadc->Instance) { if(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS)) // << Never gets here...:(
{ // Voltage subsystem... adc1_active_flag = FALSE; set_nTEMP_SENSOR_PWR_EN(TEMP_SENSOR_POWER_OFF); set_nVMON_ENABLE(VMON_ENABLE_OFF); } if(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC)) { // Voltage subsystem... adc1_active_flag = FALSE; set_nTEMP_SENSOR_PWR_EN(TEMP_SENSOR_POWER_OFF); set_nVMON_ENABLE(VMON_ENABLE_OFF); } } if(ADC2 == hadc->Instance) { // Blah } if(ADC3 == hadc->Instance) { // Blah }} // freeRTOS task... // /* Infinite loop */ for(;;) { if(MODE_BLAH == my_mode) { osDelay(1000);// We have been woken so do something...
start_adc1();// Block until the scan has completed...
// Better way would be to use a mutex block here... [AP] while(TRUE == read_adc1_active_flag()) { ; }len = sprintf(adc1_test, 'T1:%d\tT2%dVB:%d\tVHLC:%d\tMCU_Temp:%d\tVref:%d\n',
adc1_data[ADC1_TEMP1_OFFSET], adc1_data[ADC1_TEMP2_OFFSET], adc1_data[ADC1_VBOOST_OFFSET], adc1_data[ADC1_VHLC_OFFSET], adc1_data[ADC1_INTERNAL_TEMP_OFFSET], adc1_data[ADC1_VREF_OFFSET]);// Trace the output...
str_trace('ADC Vals:%s', adc1_test);}
}Solved! Go to Solution.
2017-06-09 03:20 AM
Hi,
as in your second png, dma packet size is half wold, 16bit,
You can't use
ADC1_BUFFER_SIZE_IN_BYTES;
Probably, it's
#define ADC_CHANNEL_CNT 6
status = HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_data, ADC_CHANNEL_CNT)
by the way, if you check you adc buffer, you'll probably see those 6 adc data already lying there.
Good Luck!
2017-06-09 03:20 AM
Hi,
as in your second png, dma packet size is half wold, 16bit,
You can't use
ADC1_BUFFER_SIZE_IN_BYTES;
Probably, it's
#define ADC_CHANNEL_CNT 6
status = HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_data, ADC_CHANNEL_CNT)
by the way, if you check you adc buffer, you'll probably see those 6 adc data already lying there.
Good Luck!
2017-06-09 03:29 AM
Brilliant, that did the trick..
Thanks for the answer.
But...
I draw your attention to the Doxygen header for the relevant function :-
/**
* @brief Enable ADC, start conversion of regular group and transfer result through DMA. * @note Interruptions enabled in this function: * overrun (if applicable), DMA half transfer, DMA transfer complete. * Each of these interruptions has its dedicated callback function. * @note Case of multimode enabled (when multimode feature is available): HAL_ADC_Start_DMA() * is designed for single-ADC mode only. For multimode, the dedicated * HAL_ADCEx_MultiModeStart_DMA() function must be used. * @param hadc: ADC handle * @param pData: Destination Buffer address. * @param Length: Length of data to be transferred from ADC peripheral to memory (in bytes) * @retval HAL status. */HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)The Length argument does specifically say 'in BYTES' not 'Number of transfers required'..
Can this be updated sometime soon so others don't fall into the same trap.
Andy
2017-06-09 03:33 AM
* @param Length: Length of data to be transferred from ADC peripheral to memory (
in bytes
)This description is definitely incorrect.
:((
2017-06-14 03:16 AM
Hi
Pevy.Andy
andLiu.Zhitai
,I highlighted internally your feedback about the incorrect description.
Regards
Imen
2017-11-02 07:48 AM
Hi
DAHMEN.IMEN
,I am using the NUCLEO-H743ZI with a project generated by Cube 4.0. TheHAL_ADC_Start_DMA documentation states:
@param Length: Length of data to be transferred from ADC peripheral to memory (in bytes)
Is it still a documentation bug or is it intentional this time?
Thanks,
Evgeny