找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4669|回复: 7
打印 上一主题 下一主题
收起左侧

stm32如何通过定时器中断对方波信号进行计数(上升沿或下降沿)

[复制链接]
跳转到指定楼层
楼主
ID:736707 发表于 2020-5-11 21:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我现在用的是stm32f103系列的芯片,需要对一个方波信号的上升沿或下降沿进行计数。我师傅说可以写一个定时器中断来进行计数。但是我不会啊。之前在网上找了一些相关的定时器中断代码,但是都不行。各位大佬有没有什么好的建议啊?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:736707 发表于 2020-5-11 22:44 | 只看该作者
之前的描述可能有点不清楚。下面说具体点:我现在接了一个方波信号在IO上,我要对1s中,方波周期(或下降沿)进行计数,得到的结果,通过串口输出。我的想法是将某一个IO口为输入模式,然后通过定时器中断对1s中的下降沿进行计数。然后保存在某一个变量里面,通过串口输出。是这样吗?如果这样的话应该怎么写呢?直接编一个函数将IO口设为输入,然后通过定时器中断对其进行计数?
回复

使用道具 举报

板凳
ID:344220 发表于 2020-5-11 23:49 | 只看该作者
定时器输入捕获功能了解一下
回复

使用道具 举报

地板
ID:732506 发表于 2020-5-12 06:33 | 只看该作者
定时器配合INT外部中断,方波触发int中断,int计数,定时器计时。
回复

使用道具 举报

5#
ID:94031 发表于 2020-5-12 08:46 | 只看该作者
定时器可以设定成外部引脚中断的计数器,将方波信号接到这个引脚就可以计数。
回复

使用道具 举报

6#
ID:736707 发表于 2020-5-12 15:12 | 只看该作者
xuyaqi 发表于 2020-5-12 08:46
定时器可以设定成外部引脚中断的计数器,将方波信号接到这个引脚就可以计数。

这个定时器初始化函数就是把它设为外部计数模式吗?它设置的引脚是PA0,我直接把方波信号引脚接到PA0之后,然后用定时器中断设置1s对它进行计数,计数用的是我在网上找的if(GPIOA->IDR& GPIO_IDR_IDR0)这个语句。这个可以吗?我试了一下,但是不行。大佬有时间能帮我看一下吗
static  int i = 0 ;
u32 count0=0;u32 count1=0;       
//通用定时器中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器2
void Timer2_Init(u16 arr,u16 psc)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;           //上拉输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度
        GPIO_Init(GPIOA, &GPIO_InitStructure);
   
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
        TIM_DeInit(TIM2);
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         计数到5000为500ms arr
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率                   
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设0置时钟分割:TDTS = Tck_tim           psc
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

        TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0); //设置为外部计数模式
        TIM_SetCounter(TIM2, 0);                                         //计数器清零
        TIM_Cmd(TIM2, ENABLE);  //使能TIMx外设
                                                         
}
void TIM2_IRQHandler()
{
       
        int a = 0;
        if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET) //产生一次中断为1s
        {
                if(GPIOA->IDR& GPIO_IDR_IDR0)//判断PA0是否为高电平
                {
                        i++;
                        printf("i:%d\r\n",i);
                }
                else
                {
                        a++;
                        printf("i:%d\r\n",a);
                }
               
         TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
        }
}

u16 getspeed()
        {
        u16 deta;
        count0=count1;
        delay_ms(50);                                         //deta t=50ms
        count1=TIM2->CNT;
        if(count1<count0)                                //如果溢出
        {
        deta=0xffff-count0+count1;
        }
        else
        deta=count1-count0;
        return deta;
        }
回复

使用道具 举报

7#
ID:736707 发表于 2020-5-12 15:19 | 只看该作者
hotpet 发表于 2020-5-12 06:33
定时器配合INT外部中断,方波触发int中断,int计数,定时器计时。

大佬,您好。我也想用定时器中断,但是不知道为什么不行,下面是相关代码,您有时间帮我看一下好吗?
这是time.c代码:
#include "timer.h"
static  int i = 0 ;
u32 count0=0;u32 count1=0;       
//通用定时器中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器2
void Timer2_Init(u16 arr,u16 psc)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;           //上拉输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度
        GPIO_Init(GPIOA, &GPIO_InitStructure);
   
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
        TIM_DeInit(TIM2);
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         计数到5000为500ms arr
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率                   
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设0置时钟分割:TDTS = Tck_tim           psc
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

        TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0); //设置为外部计数模式
        TIM_SetCounter(TIM2, 0);                                         //计数器清零
        TIM_Cmd(TIM2, ENABLE);  //使能TIMx外设
                                                         
}
void TIM2_IRQHandler()
{
       
        int a = 0;
        if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET) //产生一次中断为1s
        {
                if(GPIOA->IDR& GPIO_IDR_IDR0)//判断PA0是否为高电平
                {
                        i++;
                        printf("i:%d\r\n",i);
                }
                else
                {
                        a++;
                        printf("i:%d\r\n",a);
                }
               
         TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
        }
}

下面是主函数main.c
int main(void)
{
       
        NVIC_Configuration() ;
        RCC_ClocksTypeDef     RCC_Clocks;
        RCC_Configuration();
  RCC_GetClocksFreq(&RCC_Clocks);

        Timer2_Init(0xffff,0);
        USART1_Init(9600);

        delay_init();
        LED_Init();
        DHT11_Init();
  DS1302_Init();
        DS1302_Write_Time();
        DS1302_Read_Time();
        display1();
        while(1)
        {
//                DS1302_Get_Time(time);
//                display_time(time);
//               
//                DHT11_Read_Data(&temperature,&humidity) ;
//                display_dht11(temperature,humidity);
               
                sprintf((char *)display,"FS: ") ;       
                LCD_Print(1,4,display) ;       
                Speed=getspeed();       

               
回复

使用道具 举报

8#
ID:736707 发表于 2020-5-12 15:21 | 只看该作者
hotpet 发表于 2020-5-12 06:33
定时器配合INT外部中断,方波触发int中断,int计数,定时器计时。

大佬,您好。我也想用定时器中断,但是不知道为什么不行,下面是相关代码,您有时间帮我看一下好吗?
这是time.c代码:
#include "timer.h"
static  int i = 0 ;
u32 count0=0;u32 count1=0;       
//通用定时器中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器2
void Timer2_Init(u16 arr,u16 psc)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;           //上拉输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度
        GPIO_Init(GPIOA, &GPIO_InitStructure);
   
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
        TIM_DeInit(TIM2);
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         计数到5000为500ms arr
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率                   
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设0置时钟分割:TDTS = Tck_tim           psc
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

        TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0); //设置为外部计数模式
        TIM_SetCounter(TIM2, 0);                                         //计数器清零
        TIM_Cmd(TIM2, ENABLE);  //使能TIMx外设
                                                         
}
void TIM2_IRQHandler()
{
       
        int a = 0;
        if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET) //产生一次中断为1s
        {
                if(GPIOA->IDR& GPIO_IDR_IDR0)//判断PA0是否为高电平
                {
                        i++;
                        printf("i:%d\r\n",i);
                }
                else
                {
                        a++;
                        printf("i:%d\r\n",a);
                }
               
         TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
        }
}

下面是主函数main.c
int main(void)
{
       
        NVIC_Configuration() ;
        RCC_ClocksTypeDef     RCC_Clocks;
        RCC_Configuration();
  RCC_GetClocksFreq(&RCC_Clocks);

        Timer2_Init(0xffff,0);
        USART1_Init(9600);

        delay_init();
        LED_Init();
        DHT11_Init();
      DS1302_Init();
        DS1302_Write_Time();
        DS1302_Read_Time();
        display1();
        while(1)
        {       
                sprintf((char *)display,"FS: ") ;       
                LCD_Print(1,4,display) ;       
                Speed=getspeed();       
                 printf("speed:%d",Speed);
         }
}
我在定时器中断里面有串口输出,但是串口没有显示
               
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表