你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32f103c8t6 ADC channel 5采样被干扰导致程序卡死重启的可能性

[复制链接]
Flyingdim 提问时间:2025-1-16 11:12 / 未解决
    程序里配置了两个ADC进行采样,ADC1:采集输出电流、输出电压的值;ADC2:采集NTC电压、设置旋钮等电压。一共5个采样通道,ADC1:Channel_4、Channel_5;ADC2:Channel_2、Channel_8、Channel_9。
    ADC1通过TIM2_CC2事件触发单次采样,用DMA搬运完成后在完成中断里处理数据,ADC2在循环中进行采样取值,在板子上都可以正常运行,但是上到整机使用的时候,会在有输出的时候突然卡死被看门狗重启,卡死的时机不定,但都是在带负载有输出的情况下重启的;输出电流是由TIM1的100kHz PWM控制的。
    我在排查过程中,把Channel_5的输出电压采样去掉,再到整机上测试的时候就没有这个现象了。我就把Channel_5采样到的值涉及的程序屏蔽掉,但是Channel_5正常采样,同样运行,还是会重启,再次把Channel_5采样关掉,就没有问题了。我再把ADC1_channel_5换成用ADC2_channel_5,在循环里面采样,还是会出现这个问题。想问一下有大佬遇见过类似的问题吗,这种情况是否是Channel_5被外部干扰了不能正常采样,导致芯片不能正常工作了,有什么解决办法吗?配置如下:
void ADC1_DMA_Config(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    /* DMA channel1 configuration */
    DMA_DeInit(DMA1_Channel1);

    DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;             //ADC地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue; //内存地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = 1;                             //数据长度为5
    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_Circular;                                     //循环传输
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

    DMA_Init(DMA1_Channel1, &DMA_InitStructure);
    DMA_ITConfig (DMA1_Channel1,DMA_IT_TC,ENABLE );
    /* Enable DMA channel1 */
    DMA_Cmd(DMA1_Channel1, ENABLE);

    ADC_DeInit(ADC1);      //复位ADC1,将外设ADC1的所有寄存器重设为缺省值。
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;          //独立ADC模式
    ADC_InitStructure.ADC_ScanConvMode = ENABLE ;                   //扫描模式,扫描模式用于多通道采集
    /* ADC1 configuration */
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;         //开启连续转换模式,即不停地进行ADC转换
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;   //不使用外部触发转换
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  //采集数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1;                                 //要转换的通道数目5
    ADC_Init(ADC1, &ADC_InitStructure);

    /*配置ADC时钟,为PCLK2的6分频,即12MHz*/
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);
    /*配置ADC1的通道6为7.5个采样周期,序列为1 */

//  ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_28Cycles5);//PA5 VOL_OUT
    ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_28Cycles5);//PA4 CUR_OUT

    ADC_ExternalTrigConvCmd(ADC1, ENABLE);  //设置外部触发使能

    /* Enable ADC1 DMA */
    ADC_DMACmd(ADC1, ENABLE);

    /* Enable ADC1 */
    ADC_Cmd(ADC1, ENABLE);

    /*复位校准寄存器 */
    ADC_ResetCalibration(ADC1);
    /*等待校准寄存器复位完成 */
    while(ADC_GetResetCalibrationStatus(ADC1));

    /* ADC校准 */
    ADC_StartCalibration(ADC1);
    /* 等待校准完成*/
    while(ADC_GetCalibrationStatus(ADC1));
}

void ADC2_Config(void)
{
    ADC_InitTypeDef ADC_InitStructure;
    //复位ADC1,将外设ADC1的所有寄存器重设为缺省值?
    RCC_HSICmd(ENABLE);
//  while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);

    ADC_DeInit(ADC2);
    ADC_StructInit(&ADC_InitStructure);
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;          //独立ADC模式
    ADC_InitStructure.ADC_ScanConvMode = DISABLE ;                  //扫描模式,扫描模式用于多通道采集
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;         //开启连续转换模式,即不停地进行ADC转换
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //不使用外部触发转换
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  //采集数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1;                                 //要转换的通道数目5
    ADC_Init(ADC2, &ADC_InitStructure);

    /* Enable ADC1 */
    ADC_Cmd(ADC2, ENABLE);

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);

    /*复位校准寄存器 */
    ADC_ResetCalibration(ADC2);
    /*等待校准寄存器复位完成 */
    while(ADC_GetResetCalibrationStatus(ADC2));

    /* ADC校准 */
    ADC_StartCalibration(ADC2);
    /* 等待校准完成*/
    while(ADC_GetCalibrationStatus(ADC2)) {};
}

void TIM1_PWM_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    //  TIM_BDTRInitTypeDef  TIM_BDTRInitStructure;
    /* GPIOB clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                            // 复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                            // 复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
    /* 时基结构体初始化 */
    TIM_TimeBaseStructure.TIM_Period =1931;                                  //当定时器从0计数到1931,即为1932次,为一个定时周期
    TIM_TimeBaseStructure.TIM_Prescaler = 0;                                   //设置预分  频:不预分频,即为72MHz
    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;                   //设置时钟分频系数:不分频(这里用不到)
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;  //设置中心对称
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

    /* 输出比较结构体初始化 */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_Pulse =350;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
    TIM_OC2Init(TIM1, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Disable);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_Pulse =1582;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
    TIM_OC3Init(TIM1, &TIM_OCInitStructure);
    TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Disable);

    TIM_ARRPreloadConfig(TIM1, ENABLE);

    TIM_ClearITPendingBit(TIM1, TIM_IT_CC3 | TIM_IT_CC2 );

    TIM_ITConfig(TIM1, TIM_IT_CC3 | TIM_IT_CC2, DISABLE);

    TIM_CtrlPWMOutputs(TIM1, ENABLE);     //使能外设的主输出

}

void TIM2_PWM_Config(){
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
        /* 时基结构体初始化 */
    TIM_TimeBaseStructure.TIM_Period =1931;                                  //当定时器从0计数到1931,即为1932次,为一个定时周期
    TIM_TimeBaseStructure.TIM_Prescaler = 0;                                   //设置预分  频:不预分频,即为72MHz
    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;                   //设置时钟分频系数:不分频(这里用不到)
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;  //设置中心对称
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse =1930 - 54;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
    TIM_OC2Init(TIM2, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);

    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_OC2Ref);

    TIM_ARRPreloadConfig(TIM2, ENABLE);
}
循环里的采样用的是下面几个函数:
uint16_t Read_ADC_data(uint8_t ch)
{
    uint16_t AD_Value;
    ADC_RegularChannelConfig(ADC2, ch, 1, ADC_SampleTime_55Cycles5); //PA5 SET_CUR
    ADC_Cmd(ADC2, ENABLE);
    ADC_SoftwareStartConvCmd(ADC2, ENABLE);
    while(!ADC_GetFlagStatus(ADC2,ADC_FLAG_EOC));
    AD_Value = ADC_GetConversionValue(ADC2);
    ADC_ClearFlag(ADC2, ADC_FLAG_EOC);
    ADC_SoftwareStartConvCmd(ADC2, DISABLE);
    ADC_Cmd(ADC2, DISABLE);
    return AD_Value;
}

uint16_t Read_ADC_data(uint8_t ch)
{

    uint16_t AD_Value;
    ADC_RegularChannelConfig(ADC2, ch, 1, ADC_SampleTime_55Cycles5); //PA5 SET_CUR
    ADC_Cmd(ADC2, ENABLE);
    ADC_SoftwareStartConvCmd(ADC2, ENABLE);
    while(!ADC_GetFlagStatus(ADC2,ADC_FLAG_EOC));
    AD_Value = ADC_GetConversionValue(ADC2);
    ADC_ClearFlag(ADC2, ADC_FLAG_EOC);
    ADC_SoftwareStartConvCmd(ADC2, DISABLE);
    ADC_Cmd(ADC2, DISABLE);
    return AD_Value;
}
收藏 评论1 发布时间:2025-1-16 11:12

举报

1个回答
xmshao 回答时间:2025-1-16 14:17:01
从你的描述来看,异常跟ADC1 Ch5的采样结果有关的代码没什么关系。


因为你只要使能采样通道就有问题,会不会你的采样信号本身有问题?


比方你换个信号源比较下?


另外,可以尝试在采样脚加个小电容.


再就是重点检查下系统供电,尤其接地方面。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版