打印

请教一个stm32f101r8偶然死机的问题,急急急急急急

[复制链接]
2715|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
userwrj|  楼主 | 2012-9-11 14:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请教一个stm32f101r8偶然死机的问题

用stm32f101r8一批设备,总是出现不定时死机现象,仅有几台不死机,而且有的死机很频繁,有的不那么频繁,看不出什么规律。
刚开始设计的时候,用了看门狗没发现这个问题,也是很偶然才发现这个问题,虽然用了狗不会死机,但是既然这么多的死机肯定是有问题的。
查了很长时间,没看出问题了,请各位高手帮帮忙。

用扫描的方式ADC采样8路信号 Tim2每0.5ms触发采样一次 dma传输 在Tim2中断中计数20次对采样的数据运算一次。
7路ADC采样端口为
PC0-ADC_IN10
PC1-ADC_IN11
PC2-ADC_IN12
PC3-ADC_IN13
PA0-ADC_IN0
PA1-ADC_IN1
PA2-ADC_IN2
内部参考

程序中去掉了看门狗。
其他ADC的输入通道保持复位时的默认配置时,设备运行正常,几十台设备连续几天没有出现死机现象。
如果PC4-ADC_IN14和PC5_ADC_IN15配置成“推挽输出”时,一小时内有几台出现死机,运行一整天的话,几乎一大半都会死机。

PC4-ADC_IN14和PC5_ADC_IN15配置代码如下:
GPIOC->CRL &= (u32)(~(u32)((0xF<<16)|(0xF<<20)));
GPIOC->CRL |= (u32)((0x1<<16)|(0x1<<20));
如不加上这段代码,不会出现问题,如果加上了这段代码,就会出现问题。


ADC DMA 和 TIM2 的初始化函数,以及tim2中断函数如下。
//ADC初始化
#define ADC        ADC1   
void AdcInit(void)
{
   
    //   PC3-ADC_IN13
    //   PA0-ADC_IN0
    //   PA1-ADC_IN1
    //   PC2-ADC_IN12
    //  PC1-ADC_IN11
    //  PC0-ADC_IN10
    //   PA2-ADC_IN2
    GPIOC->CRL &= (u32)(~(u32)((GPIO_MODE<<GPIO_CR_PIN0)|(GPIO_MODE<<GPIO_CR_PIN1)|(GPIO_MODE<<GPIO_CR_PIN2)|(GPIO_MODE<<GPIO_CR_PIN3)));
    GPIOC->CRL |= (u32)((GPIO_MODE_AIN<<GPIO_CR_PIN0)|(GPIO_MODE_AIN<<GPIO_CR_PIN1)|(GPIO_MODE_AIN<<GPIO_CR_PIN2)|(GPIO_MODE_AIN<<GPIO_CR_PIN3));

    GPIOA->CRL &= (u32)(~(u32)((GPIO_MODE<<GPIO_CR_PIN0)|(GPIO_MODE<<GPIO_CR_PIN1)|(GPIO_MODE<<GPIO_CR_PIN2)));
    GPIOA->CRL |= (u32)((GPIO_MODE_AIN<<GPIO_CR_PIN0)|(GPIO_MODE_AIN<<GPIO_CR_PIN1)|(GPIO_MODE_AIN<<GPIO_CR_PIN2));


    // 禁用模拟看门狗
    // 独立模式
    // 禁止间断模式
    // 使用扫描模式
    // 禁止中断
    ADC->CR1 = ADC_CR1_SCAN;

    // 启用温度传感器和VREFINT
    // 使用外部事件启动转换,
    // 右对齐
    // DMA模式
    ADC->CR2 = ADC_CR2_TSVREFE|ADC_CR2_EXTTRIG|ADC_CR2_EXTSEL_SWSTART|ADC_CR2_DMA|ADC_CR2_ADON;

    // 采样28.5个周期
    ADC->SMPR1 = ADC_SMPR1_SMP17_55D5|ADC_SMPR1_SMP13_55D5|ADC_SMPR1_SMP12_55D5
                |ADC_SMPR1_SMP11_55D5|ADC_SMPR1_SMP10_55D5;
    ADC->SMPR2 = ADC_SMPR2_SMP0_55D5|ADC_SMPR2_SMP1_55D5|ADC_SMPR2_SMP2_55D5;

    // 总共8个通道
    // 调整过顺序,IA和IC换了个顺序
    // 顺序是IN2,IN13,IN10,IN0,IN11,IN1,IN12,IN17
    ADC->SQR3 = (ADC_SQR3_SQ1_1)
                |(ADC_SQR3_SQ2_3|ADC_SQR3_SQ2_2|ADC_SQR3_SQ2_0)
                |(ADC_SQR3_SQ3_3|ADC_SQR3_SQ3_1)            
                |(0)
                |(ADC_SQR3_SQ5_3|ADC_SQR3_SQ5_1|ADC_SQR3_SQ5_0)
                |(ADC_SQR3_SQ6_0);
    ADC->SQR2 = (ADC_SQR2_SQ7_3|ADC_SQR2_SQ7_2)
                |(ADC_SQR2_SQ8_4|ADC_SQR2_SQ8_0);
    ADC->SQR1 = ADC_SQR1_L_2|ADC_SQR1_L_1|ADC_SQR1_L_0;

    // 校准
    ADC->CR2 |= ADC_CR2_RSTCAL;
    while ((ADC->CR2&ADC_CR2_RSTCAL));
    ADC->CR2 |= ADC_CR2_CAL;
    while ((ADC->CR2&ADC_CR2_CAL));
}

// DMA初始化
#define    DMA        DMA1        
#define    DMA_ADC    DMA1_Channel1
void DmaInit(void)
{
    DMA_ADC->CCR &= ~DMA_CCR_EN;
    // 传输数量
    DMA_ADC->CNDTR = 8*20;

   
    // 外设地址
    DMA_ADC->CPAR = ADC_DR_ADDRESS;
    // 数据存放位置
    // 数组g_AdcViLcItemArr[20]
    DMA_ADC->CMAR = (u32)g_AdcViLcItemArr;

    // 初始化与ADC1相关的DMA
    // 使能DMA通道1
    // 从外设读
    // 存储器宽度和外设宽度为16位
    // 外设地址不变,存储器增加
    // 优先级最高
    DMA_ADC->CCR = DMA_CCR_MSIZE_16BIT|DMA_CCR_PSIZE_16BIT|DMA_CCR_MINC
                        |(DMA_CCR_PL_0|DMA_CCR_PL_1);

    DMA_ADC->CCR |= DMA_CCR_EN;
}

g_AdcViLcItemArr[20]的单元为
typedef struct
{
    vu16 k1;//ADC_IN2
    vu16 k2;//ADC_IN10
    vu16 k3;//ADC_IN1
    vu16 k4;//ADC_IN11
    vu16 k5;//ADC_IN0
    vu16 k6;//ADC_IN12
    vu16 k7;//ADC_IN13
    vu16 Vref;//内部参考电压ADC_IN17
}AdcViLcItem, *pAdcViLcItem;


//采样tim2设置
#define SMPL_TIM        TIM2
void SmplTimInit(void)
{
    // 每0.5ms采样一个点

    //设定计数器自动重装值
    SMPL_TIM->ARR = 1000;

    SMPL_TIM->PSC = 13;

    //允许更新中断,允许触发中断
    SMPL_TIM->DIER |= (u16)(TIM_DIER_UIE|TIM_DIER_TIE);                  
   
    //使能定时器                                      
    SMPL_TIM->CR1 |= (u16)(TIM_CR1_CEN);
   
    NVIC_EnableChannel(SMPL_TIM_IRQn);  
   
    NVIC_SetPriority(SMPL_TIM_IRQn, NVIC_PRIOR_SMPL_TIM);
}

// 定时器中断
#define DMA_ADCOK()    (DMA->ISR&DMA_ISR_TCIF1)
#define DMA_CLRADCOK()      (DMA->IFCR |= DMA_IFCR_CTCIF1)
#define START_ADC_SAMPLE()    ADC1->CR2 |= ADC_CR2_SWSTART
void VILC_SmplTimISR(void)
{
    static u8 index = 0;

    // 先禁止计时器
    SMPL_TIM->CR1 &= ~(u16)(TIM_CR1_CEN);
    SMPL_TIM->SR &= ~(TIM_SR_UIF|TIM_SR_TIF);//清除中断标志位      
   
   
    index++;            

    if (20==index)
    {
        
        // 运算

        // 检测DMA是否完成
        if (DMA_ADCOK())
        {
            DMA_CLRADCOK();
        }

        DmaInit();            
    }

   

    if (index>=20)
    {         
        index = 0;
    }

    // 触发ADC采样
    START_ADC_SAMPLE();

    // 使能计时器
    SMPL_TIM->CR1 |= (u16)(TIM_CR1_CEN);
}
沙发
yinyangdianzi| | 2012-9-11 16:45 | 只看该作者
我down机我骄傲

使用特权

评论回复
板凳
zhaoyu2005| | 2012-9-11 17:06 | 只看该作者
慢慢定位按死到哪里了,然后再分析是什么原因

使用特权

评论回复
地板
IJK| | 2012-9-11 17:27 | 只看该作者
如果PC4-ADC_IN14和PC5_ADC_IN15配置成“推挽输出”时,一小时内有几台出现死机,运行一整天的话,几乎一大半都会死机。

为什么要把这2个引脚配置成“推挽输出” ?

使用特权

评论回复
5
userwrj|  楼主 | 2012-9-11 18:56 | 只看该作者
PC4-ADC_IN14和PC5_ADC_IN15这两个脚我要用做其他用处,用来控制继电器

使用特权

评论回复
6
userwrj|  楼主 | 2012-9-11 19:11 | 只看该作者
3楼:
慢慢定位按死到哪里了,然后再分析是什么原因
----------------------------------
板上有个eeprom,我在HardFault_Handler里会向eeprom中写个信息,在BusFault_Handler,MemManage_Handler等中断中都加上了写信息的操作,有个别两台显示的信息好像是出现在HardFault_Handler,其余的就没有任何信息。
程序中没有其他可以死循环的地方,开启的中断也能保证不会死机。
现在基本确定的是:当PC4-ADC_IN14和PC5_ADC_IN15保持复位时的默认配置时,几十台设备能够正常运行几天,至少现在没有发现死机,也不会重启(我在程序中加入了启动时写一个信息到eeprom中,所以能看到启动的次数以及启动的原因);但是当将PC4-ADC_IN14和PC5_ADC_IN15配置成“推挽输出”时,死机的几率就非常大,半个小时就有好几台死机,一天下来差不多一大半都死掉。

使用特权

评论回复
7
zhaoyu2005| | 2012-9-12 09:24 | 只看该作者
配置成推挽输出模式后:
1.是输出哪个电平死机?
2.是接负载死机还是接不接都死机?

使用特权

评论回复
8
userwrj|  楼主 | 2012-9-12 09:49 | 只看该作者
配置成推挽输出模式后:
1.是输出哪个电平死机?
2.是接负载死机还是接不接都死机?
zhaoyu2005 发表于 2012-9-12 09:24

这两个管脚都通过2k电阻接到npn的基极,只有在一定条件时,才会输出高电平,在老化时,不会出现这些条件,所以都是底电平。
我将操作这两个管脚的程序都去掉,只留下配置这两个管脚的程序,运行一段时间就有死机现象发生

使用特权

评论回复
9
zhaoyu2005| | 2012-9-12 10:08 | 只看该作者
这现象就神奇了,想不通。剩下我能想到的招儿只能是定位死机的位置,然后分析死机的原因了

使用特权

评论回复
10
香水城| | 2012-9-12 10:11 | 只看该作者
还是需要定位死机位置

如果看门狗能正常工作,还是应该掉在FAULT里的

你FAULT里的操作太复杂了,可以简单的先点一个灯,或者把相应的内核寄存器比如LR,PC,PSR值保存到一个可靠的RAM地址中

另外,可以先把负载去掉看看

使用特权

评论回复
11
userwrj|  楼主 | 2012-9-15 16:35 | 只看该作者
谢谢各位,问题找到了,是工频干扰串到单片机里,导致单片机死机。好像端口设为默认的悬空输入比设置为推挽输出的抗干扰性能要好。

使用特权

评论回复
12
yinyangdianzi| | 2012-9-15 18:58 | 只看该作者
LZ,等你的答案

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

23

帖子

0

粉丝