本帖最后由 与非网的L先生 于 2018-1-5 17:28 编辑
之前已经实现了使用软件触发的方式,实现基于DMA方式的双ADC常规同步采样,但是这种方式有个问题,基于DMA方式的双ADC常规同步采样在两次采样之间是不存在间隔的,如下图所示:
所以,当我需要调整采样率的时候,就只能去修改ADC时钟、采样周期数,每次调整后,都得重新初始化ADC,而且这样的采样率没法很自由调整。
所以我采样定时器去触发,每次只采样一次(所以不需要用到DMA?),那么通过设置定时器的时间间隔来设定采样率就很自由了,如下图所示:
我的代码如下:
- void ADC_Config(void)
- {
- ADC_MultiModeTypeDef multimode;
- ADC_ChannelConfTypeDef sConfig;
-
- /*##-1- Configuration of ADCx peripheral (ADC master) ######################*/
- AdcHandle_master.Instance = AdcMasterInstance;
-
- AdcHandle_master.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
- AdcHandle_master.Init.Resolution = ADC_RESOLUTION_12B;
- AdcHandle_master.Init.DataAlign = ADC_DATAALIGN_RIGHT;
- AdcHandle_master.Init.ScanConvMode = ADC_SCAN_DISABLE;
- AdcHandle_master.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
- AdcHandle_master.Init.LowPowerAutoWait = DISABLE;
- AdcHandle_master.Init.ContinuousConvMode = DISABLE;
- AdcHandle_master.Init.NbrOfConversion = 1;
- AdcHandle_master.Init.DiscontinuousConvMode = DISABLE;
- AdcHandle_master.Init.NbrOfDiscConversion = 1;
- AdcHandle_master.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
- AdcHandle_master.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
- AdcHandle_master.Init.DMAContinuousRequests = DISABLE;
- AdcHandle_master.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
-
- if (HAL_ADC_Init(&AdcHandle_master) != HAL_OK)
- {
- Error_Handler();
- }
-
- /*##-2- Configuration of ADCy peripheral (ADC slave) #######################*/
- AdcHandle_slave.Instance = AdcSlaveInstance;
-
- /* Configuration of ADCy init structure: ADC parameters and regular group */
- /* Same configuration as ADCx */
- AdcHandle_slave.Init = AdcHandle_master.Init;
-
- if (HAL_ADC_Init(&AdcHandle_slave) != HAL_OK)
- {
- Error_Handler();
- }
-
- /*##-3- Configuration of channel on ADCx regular group on rank 1 ###########*/
- sConfig.Channel = AdcMasterChannel;
- sConfig.Rank = ADC_REGULAR_RANK_1;
- sConfig.SingleDiff = ADC_DIFFERENTIAL_ENDED;
- sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
- sConfig.OffsetNumber = ADC_OFFSET_NONE;
- sConfig.Offset = 0;
- if (HAL_ADC_ConfigChannel(&AdcHandle_master, &sConfig) != HAL_OK)
- {
- Error_Handler();
- }
-
- /*##-4- Configuration of channel on ADCy regular group on rank 1 ###########*/
- sConfig.Channel = AdcSlaveChannel;
- if (HAL_ADC_ConfigChannel(&AdcHandle_slave, &sConfig) != HAL_OK)
- {
- Error_Handler();
- }
-
- /*##-5- Configuration of multimode #########################################*/
- /* Multimode parameters settings and set ADCy (slave) under control of */
- /* ADCx (master). */
- multimode.Mode = ADC_DUALMODE_REGSIMULT;
- multimode.DMAAccessMode = ADC_DMAACCESSMODE_12_10_BITS;
- multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
- if (HAL_ADCEx_MultiModeConfigChannel(&AdcHandle_master, &multimode) != HAL_OK)
- {
- Error_Handler();
- }
-
- /* Run the ADC calibration in differential-ended mode */
- if (HAL_ADCEx_Calibration_Start(&AdcHandle_master, ADC_DIFFERENTIAL_ENDED) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_ADCEx_Calibration_Start(&AdcHandle_slave, ADC_DIFFERENTIAL_ENDED) != HAL_OK)
- {
- Error_Handler();
- }
- }
复制代码- void ADC_Timer_Init(uint32_t uPrescaler,uint32_t uPeriod)
- {
- TIM_ClockConfigTypeDef sClockSourceConfig;
- TIM_MasterConfigTypeDef sMasterConfig;
- hadc_Timer.Instance = ADC_TIMn;
- hadc_Timer.Init.Prescaler = uPrescaler-1;
- hadc_Timer.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数模式
- hadc_Timer.Init.Period = uPeriod;
- hadc_Timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //系统时钟不分频72MHz
- hadc_Timer.Init.RepetitionCounter = 0x00; //发生0+1次updata事件产生中断
- hadc_Timer.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
- if (HAL_TIM_Base_Init(&hadc_Timer) != HAL_OK)
- {
- _Error_Handler(__FILE__, __LINE__);
- }
- sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
- if (HAL_TIM_ConfigClockSource(&hadc_Timer, &sClockSourceConfig) != HAL_OK)
- {
- _Error_Handler(__FILE__, __LINE__);
- }
-
- /* Timer TRGO selection */
- sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; //选择update事件更新为触发源
- sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
- sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
- if (HAL_TIMEx_MasterConfigSynchronization(&hadc_Timer, &sMasterConfig) != HAL_OK)
- {
- _Error_Handler(__FILE__, __LINE__);
- }
- }
复制代码 ADC每次装换完成后做处理,判断是否采样了1024个点:
- void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
- {
- if(Sample_Finish == 0)
- {
- aADCDualConvertedValue[Sample_Index] = HAL_ADC_GetValue(hadc);
- Sample_Index++;
- }
- if(Sample_Index>=1024) //判断完成1024次采样
- {
- Sample_Index = 0;
- HAL_TIM_Base_Stop_IT(&hadc_Timer);
- Sample_Finish = 1;
- }
- }
复制代码 main函数中调用下面这个用户函数:
- void DualRegularADCtest(uint8_t uRange)
- {
- Sample_Index = 0;
- Sample_Finish = 0;
- switch(uRange)
- {
- case 0:
- ADC_Timer_Init(2,36);
- break;
- case 1:
- ADC_Timer_Init(2,35);
- break;
- case 2:
- ADC_Timer_Init(3,73);
- break;
- case 3:
- ADC_Timer_Init(6,73);
- break;
- default:
- ADC_Timer_Init(2,36);
- break;
- }
-
- // 使能ADC,开启定时器,触发双ADC采样
- if (HAL_ADC_Start(&AdcHandle_master) != HAL_OK) //STM例程中给的是使用HAL_ADC_Start_IT函数,试了不行
- {
- Error_Handler();
- }
复制代码 我使用的是定时器3去触发,ADC3通道1和ADC4的通道8.
上面的代码在调试的时候,发现一直停在的了:
能进入定时器3中断里面,而且确定是Update事件触发了,但是Watch窗口观测到Sample_Index 和 Sample_Finish 的值一直为零,这意味着ADC无法采样,之前软件触发基于DMA方式的双ADC采样还是可以,改成定时器触发就不行,也调试了很久,不知道有没有大神能帮我看看原因?
STM32给的例程是定时器触发基于DMA方式的单ADC多通道采样,我想实现定时器触发的双ADC同步采样(不需要用到DMA),有没有人实现过这种方式采样的?
|
不知道为啥 这个代码拷贝进来会出现不对齐和缩进异常问题,刚刚手动调了半天,凑合着看吧...Orz
因为直接用定时器触发的方式不知道为何一直不进采样中断,所以换种方式,直接在定时器中断中启用采样,一步一步调试:
1、软件触发DMA方式的双ADC常规同步采样(一次1024个点)。 OK
2、软件触发DMA方式的双ADC常规同步采样(一次1个点,循环1024次)。 OK
3、定时器中启用采样(即在定时器中断中调用HAL_ADCEx_MultiModeStart_DMA函数去启用采样)。 NG
第三步遇到一个问题,在定时器中调用下面语句:
HAL_ADCEx_MultiModeStart_DMA(&AdcHandle_master, (uint32_t *)(aADCDualConvertedValue+Sample_Index), 1);
Sample_Index++;
传给DMA的目标地址按道理是每次自增的,但是实际结果却每次都填充到aADCDualConvertedValue[0],其余值一直为零,但是观测Sample_Index的确是自增了的。
而且这数组和变量的声明应该也没错:
__IO uint16_t Sample_Index;
__IO uint32_t aADCDualConvertedValue[1024];
而且这种方式在第二步调试的时候是成功的,目前还在调试中。。。
Sample_Index不用判断2次试看看:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if(Sample_Index==1024) //判断完成1024次采样
{
Sample_Index = 0;
HAL_TIM_Base_Stop_IT(&hadc_Timer);
Sample_Finish = 1;
}
else
{
aADCDualConvertedValue[Sample_Index++] = HAL_ADC_GetValue(hadc);
}
}
评分
查看全部评分
对一个疑问已验证,故回复删除
http://blog.csdn.net/xuezhimeng2010/article/details/15157911
http://www.cnblogs.com/longbiao831/p/6688006.html
评分
查看全部评分
评分
查看全部评分