STM32/STM8技术william hill官网
直播中

胡卫伟

7年用户 285经验值
私信 关注
[问答]

怎么用定时器和外部触发同步在高电平时计数器计数

我使用的单片机STM32F103VC  外部芯片连接到单片机PB9(96脚 可复用为tiM4_CH4),正常情况下,外部芯片输出16.384KHz的时钟,有故障时输出高电平。用定时器如何做。但最好不要用1uS的定时器去检测PB9的电平高低。

自己的初步设想:
想用定时器和外部触发同步,在高电平时计数器计数,低电平是清零,当计数器大于30.5us时(16.384KHz的半个周期时间)触发中断。但一直没试成功。

有更好的方法,请赐教....

回帖(18)

李飞

2019-5-14 12:14:23
受到警告
提示: 作者被禁止或删除 内容自动屏蔽
举报

胡卫伟

2019-5-14 12:44:04
详细点
举报

何秀珍

2019-5-14 12:50:13

楼主在问题中的表达我的理解是楼主想对16.384KHz的时钟进行计数,这样可以用GPIO的外部中断,下降沿到来时触发外部中断,计数器加1.
举报

李家沌

2019-5-14 13:00:39
引用: ctwewer 发表于 2019-5-14 17:01
楼主在问题中的表达我的理解是楼主想对16.384KHz的时钟进行计数,这样可以用GPIO的外部中断,下降沿到来时触发外部中断,计数器加1.

之前在群里有说过这个问题,提出的解决方案如下:
1、采用输入捕获脉冲数,对一段时间内进行统计,如果数量不够,说明这段时间出现故障
2、采用上升沿计时,下降沿停止统计时间的方式实时监测出故障
举报

胡卫伟

2019-5-14 13:15:06
引用: ctwewer 发表于 2019-5-14 17:01
楼主在问题中的表达我的理解是楼主想对16.384KHz的时钟进行计数,这样可以用GPIO的外部中断,下降沿到来时触发外部中断,计数器加1.

不用外部中断 就用Tim4 可以做到吗?
举报

胡卫伟

2019-5-14 13:30:56
不用外部中断,就用TIM4 可以做到吗?
举报

李家沌

2019-5-14 13:48:12
引用: 屠鸡勇士李运好 发表于 2019-5-14 17:41
不用外部中断,就用TIM4 可以做到吗?

输入捕获,不需要外部中断吧!
举报

何秀珍

2019-5-14 14:01:48
引用: testd018 发表于 2019-5-14 17:59
输入捕获,不需要外部中断吧!

我还是没弄明白你是要同步定时器还是要对外部脉冲进行计数?
举报

胡卫伟

2019-5-14 14:12:26
引用: testd018 发表于 2019-5-14 17:59
输入捕获,不需要外部中断吧!

用Tim4 输入捕获,当捕捉到上升沿就清零计数器, 当计数器值大于30.当计数器大于30.5us时(16.384KHz的半个周期时间)就认为有故障 ?  
举报

何秀珍

2019-5-14 14:21:11
如果是定时器输入捕获,有ST官方的例程可参考:
举报

李家沌

2019-5-14 14:27:40
引用: ctwewer 发表于 2019-5-14 18:12
我还是没弄明白你是要同步定时器还是要对外部脉冲进行计数?

都可以啊,上面不是说了吗
举报

李家沌

2019-5-14 14:43:40
引用: 屠鸡勇士李运好 发表于 2019-5-14 18:23
用Tim4 输入捕获,当捕捉到上升沿就清零计数器, 当计数器值大于30.当计数器大于30.5us时(16.384KHz的半个周期时间)就认为有故障 ?  

怎么想的呀,高电平故障不是吗,那就是上升沿开始计数,下降沿复位计数,你可以设置超时中断,只要不超时(16.384Khz的半周期很容易算出来),所以只要超时了不就是有故障了吗,不过频繁中断会对cpu的消耗很大,所以要根据应用场景来看是否需要这么严格,从而设计一个比较宽裕的条件!
最靠谱和比较渐变的方法就是统计脉冲数呀,例如按照你16.384Khz,1s有多少个脉冲数是固定的呀,加入允许点误差,就前后加一点点,如果出现了故障,最后的脉冲数肯定不会是你定义的正常的脉冲数呀.
举报

胡卫伟

2019-5-14 14:56:38
引用: testd018 发表于 2019-5-14 18:54
怎么想的呀,高电平故障不是吗,那就是上升沿开始计数,下降沿复位计数,你可以设置超时中断,只要不超时(16.384Khz的半周期很容易算出来),所以只要超时了不就是有故障了吗,不过频繁中断会对cpu的消耗很大,所以要根据应用场景来看是否需要这么严格,从而设计一个比较宽裕的条件!
最靠谱和比较渐变的方法就是统计脉冲 ...

这样做:
Tim4_Init(void)
{                 GPIO_InitTypeDef GPIO_InitStructure;                TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;               
        TIM_ICInitTypeDef  TIM_ICInitStructure;       
        NVIC_InitTypeDef   NVIC_InitStructure;       

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);               
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(GPIOB,&GPIO_InitStructure);  //Max17830 Alarm
               RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);                       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
        TIM_TimeBaseStructure.TIM_Prescaler = 71;       
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;       
        TIM_TimeBaseStructure.TIM_Period = 49999;       
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;        
        TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure);
        TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;         //选择输入端 IC4映射到TI4上
        TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge;  //上升沿下降沿都捕获
        TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI4上
        TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置输入分频,不分频
        TIM_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
          TIM_ICInit(TIM4, &TIM_ICInitStructure);       
        NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;       
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);       
        TIM_ITConfig(TIM4,TIM_IT_CC4,ENABLE);//允许CC4IE捕获中断               
        TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);//允许更新中断
        TIM_ClearITPendingBit(TIM4,TIM_IT_CC4);       
        TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
        TIM_Cmd(TIM4,ENABLE);
}
中断函数
void TIM4_IRQHandler(void)   
{  
   if(TIM_GetITStatus(TIM4,TIM_IT_CC4) != RESET)
   {
       TIM_SetCounter(TIM4,0);
       TIM_ClearITPendingBit(TIM4,TIM_IT_CC4);
   }

   if (TIM_GetITStatus(TIM4,TIM_IT_Update) != RESET)
   {      
      TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //清除TIMx的中断待处理位:TIM 中断源
   }
}


main函数里判断
if(TIM_GetCounter(TIM4) >= 32)  //   (1/16.384KHz)/2= 30.517578125us
{
           AlarmFlag = 1;  //  故障标志
}



上升沿和下降沿都清零计数器,只要计数器大于32即认为有故障。但开启了溢出中断的话(TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE)),会频繁导致看门狗复位。
举报

李家沌

2019-5-14 15:16:08
引用: 屠鸡勇士李运好 发表于 2019-5-14 19:07
这样做:
Tim4_Init(void)
{                 GPIO_InitTypeDef GPIO_InitStructure;                TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;               

中断太频繁了,对你的系统压力太大~
你用脉冲数统计法吧,这样得话你只需要格一段时间去轮询脉冲数就行了,记住溢出的时候也要处理一下(复位一下继续统计)
举报

胡卫伟

2019-5-14 15:25:14
引用: testd018 发表于 2019-5-14 19:27
中断太频繁了,对你的系统压力太大~
你用脉冲数统计法吧,这样得话你只需要格一段时间去轮询脉冲数就行了,记住溢出的时候也要处理一下(复位一下继续统计)

1.为什么开启了定时器溢出中断,会导致看门狗频繁复位?
2 .脉冲统计法,没办法及时判断出吧,理论上说只要高电平持续的时间超过31us就认为是故障。
举报

李家沌

2019-5-14 15:30:38
引用: 屠鸡勇士李运好 发表于 2019-5-14 19:36
1.为什么开启了定时器溢出中断,会导致看门狗频繁复位?
2 .脉冲统计法,没办法及时判断出吧,理论上说只要高电平持续的时间超过31us就认为是故障。

1、因为中断太频繁了,导致你没有机会运行主循环的代码就又进中断了,31us的中断太急了
2、按理论说是这样的,这个要根据你需求了
举报

人中狼

2019-5-14 15:45:08
外部中断和定时器同时用吧,外部边沿触发外部中断,外部中断所要做的就是上升沿触发中断时启动定时器,和改为下降沿触发外部中断,下降沿触发中断时,清除定时器并改为上升沿触发外部中断。
定时器定时32微秒,如果定时到了,那就是外部故障了,
举报

Arvin1987

2019-5-15 06:46:38
学习下  !!!!!!!!!!!!!!!!!!!!!!!!!
举报

更多回帖

发帖
×
20
完善资料,
赚取积分