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

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 回答时间:前天 14:17
从你的描述来看,异常是跟ADC1 Ch5的采样结果有关的代码处没什么关系。


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


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


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


再就是重点检查下系统供电,尤其接地方面。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版