OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4183|回复: 5

一个老问题,已经在论坛里搜索过了,在这里再次向大家探讨一下。。。

[复制链接]

5

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
52
金钱
52
注册时间
2014-7-15
在线时间
0 小时
发表于 2015-1-29 21:38:12 | 显示全部楼层 |阅读模式
5金钱
大家好,困扰了两天的问题了,之前也在论坛里找到过相关的话题,就是说我现在用外部中断和定时器中断来对一个外部引脚的触发脉冲进行计数,想要统计在5秒钟内的触发脉冲的个数,现在有一个问题就是说当我说不定在某一个时刻来了一个外部触发脉冲后,我想要我的定时器立刻在这个时刻进行计数,然后5秒钟后再进入中断统计总的脉冲个数。。。。。。可是我发现现在我的程序当来了一个外部触发脉冲后,定时器有时候是隔1秒钟后进入中断,有时候隔两秒,3秒或者4秒钟后再进入中断,我猜原因应该是定时器的中断是不断在进行的,外部触发脉冲的中断说不定是在定时器的5秒定时时间之内的某一个时刻来临的才会发生这种现象,可是想了好久,总是解决不了,在这里把程序贴出来,求助一下各位。。。。。。


u8 frequency_CH1=0;
u8 frequency_CH2=0;
u8 frequency_CH3=0;
u8 get_frequency_CH1=0;
u8 get_frequency_CH2=0;
u8 get_frequency_CH3=0;
   
int main(void)
{
u8 i=0;
  Stm32_Clock_Init(9); //系统时钟设置
delay_init(72);     //延时初始化
uart_init(72,9600);  //串口初始化 
LED_Init();   //初始化与LED连接的硬件接口
Timerx_Init(50000,7199);//10Khz的计数频率,计数到5000为500ms/////////////////////////////////////////////////////////
EXTIX_Init();  
    while(1)
{
if(get_frequency_CH1!=0)
{
for(i=0;i<get_frequency_CH1;i++)
{
LED0=!LED0;
delay_ms(1000);
//frequency_CH1=0;
}
get_frequency_CH1=0;
}
// LED0=!LED0;
// delay_ms(200);   
}  
}


extern u8 frequency_CH1;
extern u8 frequency_CH2;
extern u8 frequency_CH3;
extern u8 get_frequency_CH1;
extern u8 get_frequency_CH2;  
extern u8 get_frequency_CH3;
//外部中断0服务程序
void EXTI0_IRQHandler(void)
{
delay_ms(10);//消抖
if(KEY2==1) //按键2
{
// LED0=!LED0;
// LED1=!LED1;
frequency_CH3++;
}  
EXTI->R=1<<0;  //清除LINE0上的中断标志位  
}

//外部中断15~10服务程序
void EXTI15_10_IRQHandler(void)
{
delay_ms(10);    //消抖
EXTI->R=1<<13;
EXTI->R=1<<15;  
if(KEY0==0)      //按键0
{
//LED0=!LED0;
frequency_CH1++;
}else if(KEY1==0)//按键1
{
//LED1=!LED1;
frequency_CH2++;
}
//EXTI->R=1<<13;     //清除LINE13上的中断标志位  
//EXTI->R=1<<15;     //清除LINE15上的中断标志位  
}
//外部中断初始化程序
//初始化PA0,PA13,PA15为中断输入.
void EXTIX_Init(void)
{
RCC->APB2ENR|=1<<2;     //使能PORTA时钟
JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG和SWD   

GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入  
GPIOA->CRL|=0X00000008;   
GPIOA->CRH&=0X0F0FFFFF;//PA13,15设置成输入  
GPIOA->CRH|=0X80800000;   
GPIOA->ODR|=1<<13;   //PA13上拉,PA0默认下拉
GPIOA->ODR|=1<<15;   //PA15上拉

Ex_NVIC_Config(GPIO_A,0,RTIR); //上升沿触发
Ex_NVIC_Config(GPIO_A,13,FTIR);//下降沿触发
Ex_NVIC_Config(GPIO_A,15,FTIR);//下降沿触发

MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);    //抢占2,子优先级2,组2
MY_NVIC_Init(2,1,EXTI15_10_IRQChannel,2);//抢占2,子优先级1,组2   
}


extern u8 frequency_CH1;
extern u8 frequency_CH2;
extern u8 frequency_CH3;
extern u8 get_frequency_CH1;
extern u8 get_frequency_CH2;
extern u8 get_frequency_CH3;  
 

//定时器3中断服务程序  
void TIM3_IRQHandler(void)
{          
if(TIM3->SR&0X0001)//溢出中断
{
//LED1=!LED1;
get_frequency_CH1=frequency_CH1;
frequency_CH1=0;
get_frequency_CH2=frequency_CH2;
frequency_CH2=0;
get_frequency_CH3=frequency_CH3;
frequency_CH3=0;              
}   
TIM3->SR&=~(1<<0);//清除中断标志位    
}
//通用定时器中断初始化   
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void Timerx_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<1;//TIM3时钟使能    
  TIM3->ARR=arr;  //设定计数器自动重装值//刚好1ms    
TIM3->SC=psc;  //预分频器7200,得到10Khz的计数时钟
//这两个东东要同时设置才可以使用中断
TIM3->DIER|=1<<0;   //允许更新中断
TIM3->DIER|=1<<6;   //允许触发中断   
TIM3->CR1|=0x01;    //使能定时器3             //我注释的//////////////(2015.01.29)
  MY_NVIC_Init(1,3,TIM3_IRQChannel,2);//抢占1,子优先级3,组2  
}

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
52
金钱
52
注册时间
2014-7-15
在线时间
0 小时
 楼主| 发表于 2015-1-29 21:42:40 | 显示全部楼层
不好意思,刚才贴的程序有注释掉的看着不太方便,我再贴一遍。。。。。。



u8 frequency_CH1=0;
u8 frequency_CH2=0;
u8 frequency_CH3=0;
u8 get_frequency_CH1=0;
u8 get_frequency_CH2=0;
u8 get_frequency_CH3=0;
   
int main(void)

u8 i=0; 
  Stm32_Clock_Init(9); //系统时钟设置
delay_init(72);      //延时初始化
uart_init(72,9600);  //串口初始化 
LED_Init();     //初始化与LED连接的硬件接口
Timerx_Init(50000,7199);//10Khz的计数频率,计数到5000为500ms/////////////////////////////////////////////////////////
EXTIX_Init();  
    while(1)
{
if(get_frequency_CH1!=0)
{
for(i=0;i<get_frequency_CH1;i++)
{
LED0=!LED0;
delay_ms(1000);
}
get_frequency_CH1=0;
}    
}  
}


extern u8 frequency_CH1;
extern u8 frequency_CH2;
extern u8 frequency_CH3;
extern u8 get_frequency_CH1;
extern u8 get_frequency_CH2;  
extern u8 get_frequency_CH3;
//外部中断0服务程序
void EXTI0_IRQHandler(void)
{
delay_ms(10);//消抖
if(KEY2==1)  //按键2
{
frequency_CH3++; 
}   
EXTI->R=1<<0;  //清除LINE0上的中断标志位  
}

//外部中断15~10服务程序
void EXTI15_10_IRQHandler(void)

delay_ms(10);    //消抖
EXTI->R=1<<13;
EXTI->R=1<<15;   
if(KEY0==0)      //按键0
{
frequency_CH1++;
}else if(KEY1==0)//按键1
{
frequency_CH2++;

}
//外部中断初始化程序
//初始化PA0,PA13,PA15为中断输入.
void EXTIX_Init(void)
{
RCC->APB2ENR|=1<<2;     //使能PORTA时钟
JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG和SWD   

GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入   
GPIOA->CRL|=0X00000008;   
GPIOA->CRH&=0X0F0FFFFF;//PA13,15设置成输入   
GPIOA->CRH|=0X80800000;   
GPIOA->ODR|=1<<13;    //PA13上拉,PA0默认下拉
GPIOA->ODR|=1<<15;    //PA15上拉

Ex_NVIC_Config(GPIO_A,0,RTIR); //上升沿触发
Ex_NVIC_Config(GPIO_A,13,FTIR);//下降沿触发
Ex_NVIC_Config(GPIO_A,15,FTIR);//下降沿触发

MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);    //抢占2,子优先级2,组2
MY_NVIC_Init(2,1,EXTI15_10_IRQChannel,2);//抢占2,子优先级1,组2    
}


extern u8 frequency_CH1;
extern u8 frequency_CH2;
extern u8 frequency_CH3;
extern u8 get_frequency_CH1;
extern u8 get_frequency_CH2;
extern u8 get_frequency_CH3;  
 

//定时器3中断服务程序  
void TIM3_IRQHandler(void)
{            
if(TIM3->SR&0X0001)//溢出中断
{
get_frequency_CH1=frequency_CH1;
frequency_CH1=0;
get_frequency_CH2=frequency_CH2;
frequency_CH2=0;
get_frequency_CH3=frequency_CH3;
frequency_CH3=0;                 
}    
TIM3->SR&=~(1<<0);//清除中断标志位    
}
//通用定时器中断初始化    
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void Timerx_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<1;//TIM3时钟使能    
  TIM3->ARR=arr;  //设定计数器自动重装值//刚好1ms    
TIM3->SC=psc;  //预分频器7200,得到10Khz的计数时钟
//这两个东东要同时设置才可以使用中断
TIM3->DIER|=1<<0;   //允许更新中断 
TIM3->DIER|=1<<6;   //允许触发中断    
TIM3->CR1|=0x01;    //使能定时器3             //我注释的//////////////(2015.01.29)
  MY_NVIC_Init(1,3,TIM3_IRQChannel,2);//抢占1,子优先级3,组2   
}
回复

使用道具 举报

39

主题

2026

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2020
金钱
2020
注册时间
2013-5-1
在线时间
87 小时
发表于 2015-1-29 23:05:26 | 显示全部楼层
你这个应该是以5s为单位,一旦开始,就不应该再操作定时器了,等5s以后再做下一步操作
博观而约取,厚积而薄发。
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-1-29 23:21:50 | 显示全部楼层
你用定时器的定时中断来统计脉冲的???
怎么个统计法?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

5

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
52
金钱
52
注册时间
2014-7-15
在线时间
0 小时
 楼主| 发表于 2015-1-30 09:46:22 | 显示全部楼层
回复【4楼】正点原子:
---------------------------------
就是说在按键KEY0的中断服务函数里将变量frequency_CH1++,来了几次KEY0的按键中断,变量frequency_CH1就加几次,当5秒时间到时进入定时器的中断服务函数,在定时器的中断服务函数里将frequency_CH1的值赋给get_frequency_CH1,同时frequency_CH1的值清零,然后再主函数的while(1)循环里面判断get_frequency_CH1的值,若非零就将LED0闪灭,闪灭的值就是get_frequency_CH1的值。。。。。。现在的问题就是说按键KEY0的外部中断来临的时刻正好处在定时器的5秒定时时间内的某一时刻,也就是说我统计的便不是5秒时间的了,而是比5秒时间小的时间单位。。。。。。
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-1-30 23:27:59 | 显示全部楼层
你开始统计的时候,才让定时器工作,不就解决问题了么?
另外你这思路也不太对.
测量频率,最好用定时器的外部计数器模式,不需要频繁中断,而且很准.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-26 06:47

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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