AiK 发表于 2024-1-27 17:34:02

STM32H7的输入捕获不能触发ADC转换

1、问题描述

    想使用定时TIM3的通道4捕获信号,然后触发ADC转换,但是ADC没看到一次转换,然后定时器捕获的计数器值是有在更新的,说明捕获已经发生了
2、代码如下
    void Timer3_Init(void)
{
TIM_IC_InitTypeDef sICConfig = {0};
// 打开定时器时钟
__HAL_RCC_TIM3_CLK_ENABLE();

// 恢复到未初始化状态


// 配置定时器
hTrigTimer.Instance = S13131_TRIG_USE_TIMER;
hTrigTimer.Init.Prescaler         = 0; // Fck_cnt = Fck_psc / (PSC +1) = 32MHz 其中Fck_psc = 128MHz
hTrigTimer.Init.Period            = 0xFFFF; // 用Timer3定时器的ADC_EXTERNALTRIG_T3_TRGO触发时改为1
hTrigTimer.Init.ClockDivision   = TIM_CLOCKDIVISION_DIV1; // 确定DTS时钟=定时器时钟CK_INT(128MHz)
hTrigTimer.Init.CounterMode       = TIM_COUNTERMODE_UP;
hTrigTimer.Init.RepetitionCounter = 0;

if(HAL_TIM_IC_Init(&hTrigTimer) != HAL_OK)
{
    Error_Handler();
}

// 配置输入通道
sICConfig.ICPolarity= TIM_ICPOLARITY_RISING; // 捕获Trig信号下降沿
sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;
sICConfig.ICPrescaler = TIM_ICPSC_DIV1; // 一个下降沿捕获一次
sICConfig.ICFilter    = 0x0;   // 配置采样时钟和滤波参数 0x4--采样时钟=fdts/2, N=6 下降沿之后有大概100ns的电平才触发输入捕获
if(HAL_TIM_IC_ConfigChannel(&hTrigTimer, &sICConfig, S13131_TRIG_USE_TIMER_CHANNEL) != HAL_OK)
{
    Error_Handler();
}
}

void ADC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
ADC_ChannelConfTypeDef sConfig = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

// ADC外设时钟配置为72MHz 规格书中ADC3(12bit)最大时钟为75MHz
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInitStruct.PLL2.PLL2M = 1;
PeriphClkInitStruct.PLL2.PLL2N = 36;
PeriphClkInitStruct.PLL2.PLL2P = 4;
PeriphClkInitStruct.PLL2.PLL2Q = 2;
PeriphClkInitStruct.PLL2.PLL2R = 2;
PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
    Error_Handler();
}

// ADC 引脚配置
CMOS_ADC_GPIO_CLK_ENABLE; // 时钟使能
CMOS_ADC_CLK_ENABLE;
CMOS_ADC_DMA_CLK_ENABLE;    // DMA时钟使能
HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC3, SYSCFG_SWITCH_PC3_OPEN); // PC3_C为Direct输入 采样率最快

GPIO_InitStruct.Pin = CMOS_ADC_PIN;   //
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(CMOS_ADC_PORT, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_2;   //
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(CMOS_ADC_PORT, &GPIO_InitStruct);

// DMA配置
hDMA_CmosADC.Instance = DMA1_Stream0;
hDMA_CmosADC.Init.Request = DMA_REQUEST_ADC3;   // DMAMUX选择adc3_dma作为DMA1的请求
hDMA_CmosADC.Init.Direction = DMA_PERIPH_TO_MEMORY;
hDMA_CmosADC.Init.PeriphInc = DMA_PINC_DISABLE;
hDMA_CmosADC.Init.MemInc = DMA_MINC_ENABLE;
hDMA_CmosADC.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;    // ADC设置10位
hDMA_CmosADC.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;       //
hDMA_CmosADC.Init.Mode = DMA_CIRCULAR;    // 双缓存模式
hDMA_CmosADC.Init.Priority = DMA_PRIORITY_HIGH;
hDMA_CmosADC.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

if (HAL_DMA_Init(&hDMA_CmosADC) != HAL_OK)    // 初始化DMA,里面有关于DMAMUX的初始化
{
    Error_Handler();
}

__HAL_LINKDMA(&hCmosADC,DMA_Handle,hDMA_CmosADC);   // 关联 ADC 句柄和 DMA 句柄

// DMA中断配置
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 2, 0);      // 设置DMA中断优先级
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);            // 使能中断

// ADC配置
hCmosADC.Instance = CMOS_USE_ADC;
hCmosADC.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hCmosADC.Init.Resolution = ADC_RESOLUTION_10B;    // 为了满足精度、速率要求,ADC位数暂定为10位
hCmosADC.Init.ScanConvMode = ADC_SCAN_DISABLE;
hCmosADC.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hCmosADC.Init.LowPowerAutoWait = DISABLE;
hCmosADC.Init.ContinuousConvMode = DISABLE;// 禁止自动转换,采用的定时器触发转换
hCmosADC.Init.NbrOfConversion = 1;
hCmosADC.Init.DiscontinuousConvMode = DISABLE;
hCmosADC.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T3_CC4;    // ADC_EXTERNALTRIG_T3_CC4定时器Timer3的捕获事件触发ADC
hCmosADC.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
//hCmosADC.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;    // 定时器Timer2的OC3REF触发TRGO
//hCmosADC.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hCmosADC.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
hCmosADC.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hCmosADC.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;//
hCmosADC.Init.OversamplingMode = DISABLE;
hCmosADC.Init.Oversampling.Ratio = 2; // 相当于两次采样的数据做累加
hCmosADC.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_1;
hCmosADC.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
hCmosADC.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
if (HAL_ADC_Init(&hCmosADC) != HAL_OK)
{
    Error_Handler();
}

// 执行自动ADC校准
HAL_ADCEx_Calibration_Start(&hCmosADC, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);

// ADC通道配置
sConfig.Channel = LL_ADC_CHANNEL_1;    // 接到PC3-ADC3_INP1 direct输入,采样率最快
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;// ADC3采样时间最小2.5个Clock
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hCmosADC, &sConfig) != HAL_OK)   
{
    Error_Handler();
}

//__HAL_ADC_ENABLE_IT(&hCmosADC, ADC_IT_EOS);
///* ADC3 interrupt Init */
//HAL_NVIC_SetPriority(ADC3_IRQn, 1, 0);
//HAL_NVIC_EnableIRQ(ADC3_IRQn);
}

主函数调用了初始化、开始函数
void S13131_Init(void)
{
S13131_GPIO_Init();   // 初始化与S13131相关的GPIO

ADC_Init();         // ADC3_INP1采集输出的模拟电压
Timer3_Init();      // Timer3 CH4引脚输入Trig触发信号
//Timer5_Init();
//Timer23_Init();       // Timer23 ETR引脚输入Trig触发信号
Timer1_Init();      // Timer1通道1输出ST波形
Timer2_Init();      // Timer2通道3输出CLK波形

}


void S13131_StartWork(void)
{
// 使能DMA双缓冲
//if(HAL_DMAEx_MultiBufferStart(&hDMA_CmosADC, hCmosADC.Instance->DR, (uint32_t)S13131_DataBuff0, (uint32_t)S13131_DataBuff1, S13131_DATA_BUFF_SIZE) != HAL_OK)//   
//{
//    Error_Handler();
//}
//HAL_ADC_Start_DMA_Modify(&hCmosADC, (uint32_t*)S13131_DataBuff0, (uint32_t*)S13131_DataBuff1, S13131_DATA_BUFF_SIZE);   // 开始ADC
    HAL_ADC_Start_DMA(&hCmosADC, (uint32_t*)S13131_DataBuff0, S13131_DATA_BUFF_SIZE);

//if(HAL_TIM_OC_Start(&hTrigTimer, S13131_TRIG_USE_TIMER_CHANNEL) != HAL_OK)
//{
//    Error_Handler();
//}

if(HAL_TIM_IC_Start(&hTrigTimer, S13131_TRIG_USE_TIMER_CHANNEL) != HAL_OK)
{
    Error_Handler();
}

3、要问的问题
    为何TIM_CH4的输入捕获不能触发ADC转换?

eric2013 发表于 2024-1-28 09:03:14

使用有误,这个不是输入捕获,是CC捕获比较来触发,定时器配置周期控制的

需要外部触发,要使用EXTI触发。

AiK 发表于 2024-1-28 10:42:35

eric2013 发表于 2024-1-28 09:03
使用有误,这个不是输入捕获,是CC捕获比较来触发,定时器配置周期控制的

需要外部触发,要使用EXTI触发 ...

ADC配置的hCmosADC.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T3_CC4,是这个定时器3通道4的CC触发,而定时器配置成了输入捕获模式,这样难道是错的?

AiK 发表于 2024-1-28 10:46:42

eric2013 发表于 2024-1-28 09:03
使用有误,这个不是输入捕获,是CC捕获比较来触发,定时器配置周期控制的

需要外部触发,要使用EXTI触发 ...

这个CC触发是输出比较触发?不能输入捕获触发?看ADC_EXTERNALTRIG_T3_CC4的宏定义,描述为:
#define ADC_EXTERNALTRIG_T3_CC4       (LL_ADC_REG_TRIG_EXT_TIM3_CH4)             /*!< ADC group regular conversion trigger from external peripheral: TIM3 channel 4 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */
描述里面提到输入捕获或者输出比较

eric2013 发表于 2024-1-28 11:33:39

AiK 发表于 2024-1-28 10:46
这个CC触发是输出比较触发?不能输入捕获触发?看ADC_EXTERNALTRIG_T3_CC4的宏定义,描述为:
#define A ...
是的,准确的说是OC,不是CC。所以我认为不行。
当然,你也可以试试,也许确实支持呢,我也没测试过捕获触发。


AiK 发表于 2024-1-29 08:50:22

eric2013 发表于 2024-1-28 11:33
是的,准确的说是OC,不是CC。所以我认为不行。
当然,你也可以试试,也许确实支持呢,我也没测试过捕获 ...

试了不行 换成EXTI触发是可以的 应该是OC
页: [1]
查看完整版本: STM32H7的输入捕获不能触发ADC转换