程序里配置了两个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;
}
因为你只要使能采样通道就有问题,会不会你的采样信号本身有问题?
比方你换个信号源比较下?
另外,可以尝试在采样脚加个小电容.
再就是重点检查下系统供电,尤其接地方面。