OpenEdv-开源电子网

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

定时器中断问题。各位网友大家早上好,向大家请教一个定时器中断问题

[复制链接]

12

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-11-5
在线时间
31 小时
发表于 2019-1-24 08:55:49 | 显示全部楼层 |阅读模式
5金钱
最近在做一个两路信号源,用的两片德州仪器的DAC8820,用定时器中断不断的往GPIOD和GPIOE送16位的并行数据。使用的定时器3和定时器4两个定时器。当我两路信号源都要输出的时候,也就是两个定时器都要不停的进入中断,两路信号都输出5KHz信号的时候,两路信号的频率都正常。定时时间我是这样计算的:信号频率小于等于10KHZ的时候,每个周期100个点,以5Khz为例,信号频率为5K,1S中需要5000*100的点,定时器时钟频率为42M,那么计数值就是42000000/(5000*100),以这种方式其中一路信号输出10K的时候,另一路信号的频率就不准了。这是什么情况啊,是优先级的问题还是什么问题啊?

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

使用道具 举报

12

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-11-5
在线时间
31 小时
 楼主| 发表于 2019-1-24 09:09:53 | 显示全部楼层
追加一下代码

void Timer3_Init(u16 arr,u16 psc)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  ///使能TIM3时钟
       
  TIM_TimeBaseInitStructure.TIM_Period = arr-1;         //自动重装载值
        TIM_TimeBaseInitStructure.TIM_Prescaler=psc-1;  //定时器分频
        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
        TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
       
        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
       
        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断
        TIM_Cmd(TIM3,ENABLE); //使能定时器3
       
        NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x2; //抢占优先级1
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x0; //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}

void Timer4_Init(u16 arr,u16 psc)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);  ///使能TIM3时钟
       
  TIM_TimeBaseInitStructure.TIM_Period = arr-1;         //自动重装载值
        TIM_TimeBaseInitStructure.TIM_Prescaler=psc-1;  //定时器分频
        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
        TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
       
        TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);//初始化TIM3
       
        TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //允许定时器3更新中断
        TIM_Cmd(TIM4,ENABLE); //使能定时器3
       
        NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn; //定时器3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x2; //抢占优先级1
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x1; //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}
void Timer4_Init(u16 arr,u16 psc)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);  ///使能TIM3时钟
       
  TIM_TimeBaseInitStructure.TIM_Period = arr-1;         //自动重装载值
        TIM_TimeBaseInitStructure.TIM_Prescaler=psc-1;  //定时器分频
        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
        TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
       
        TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);//初始化TIM3
       
        TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //允许定时器3更新中断
        TIM_Cmd(TIM4,ENABLE); //使能定时器3
       
        NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn; //定时器3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x2; //抢占优先级1
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x1; //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}

void Timer4_Init(u16 arr,u16 psc)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);  ///使能TIM3时钟
       
  TIM_TimeBaseInitStructure.TIM_Period = arr-1;         //自动重装载值
        TIM_TimeBaseInitStructure.TIM_Prescaler=psc-1;  //定时器分频
        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
        TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
       
        TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);//初始化TIM3
       
        TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //允许定时器3更新中断
        TIM_Cmd(TIM4,ENABLE); //使能定时器3
       
        NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn; //定时器3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x2; //抢占优先级1
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x1; //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}


void TIM3_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
        {
                GPIOD->ODR = Wave1_Buffer[cnt1++];
                if(cnt1>=BUFFER1_SIZE)        cnt1=0;       
        }
        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
}

void TIM4_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET) //溢出中断
        {
                GPIOE->ODR = Wave2_Buffer[cnt2++];
                if(cnt2>=BUFFER2_SIZE)        cnt2=0;       
        }
        TIM_ClearITPendingBit(TIM4,TIM_IT_Update);  //清除中断标志位
}

void Setup_Frequency(uint8_t channel,uint16_t counter,uint8_t psc)
{
        switch(channel)
        {
                case CHANNEL1:Timer3_Init(counter,psc);break;
                case CHANNEL2:Timer4_Init(counter,psc);break;
                default:break;
        }
}
需要信号的时候开始初始化定时器及中断
回复

使用道具 举报

1

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
130
金钱
130
注册时间
2017-11-14
在线时间
34 小时
发表于 2019-1-24 11:07:20 | 显示全部楼层
我的理解是5kHz时,每秒要进入timer中断500000次,两次中断间隔2us,10kHz时,两次中断间隔1us,太短了,必须每个周期100个点吗?
可以试一下DMA传输数据
回复

使用道具 举报

12

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-11-5
在线时间
31 小时
 楼主| 发表于 2019-1-24 11:28:44 | 显示全部楼层
cjsyrzy 发表于 2019-1-24 11:07
我的理解是5kHz时,每秒要进入timer中断500000次,两次中断间隔2us,10kHz时,两次中断间隔1us,太短了,必 ...

高于等于10k的信号我就让1秒钟的点数固定,频率越高点数就越少
回复

使用道具 举报

12

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-11-5
在线时间
31 小时
 楼主| 发表于 2019-1-24 11:32:05 | 显示全部楼层
cjsyrzy 发表于 2019-1-24 11:07
我的理解是5kHz时,每秒要进入timer中断500000次,两次中断间隔2us,10kHz时,两次中断间隔1us,太短了,必 ...

这个可以用DMA来传输吗,但是还是会用到定时器啊
回复

使用道具 举报

12

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-11-5
在线时间
31 小时
 楼主| 发表于 2019-1-24 11:32:09 | 显示全部楼层
cjsyrzy 发表于 2019-1-24 11:07
我的理解是5kHz时,每秒要进入timer中断500000次,两次中断间隔2us,10kHz时,两次中断间隔1us,太短了,必 ...

这个可以用DMA来传输吗,但是还是会用到定时器啊
回复

使用道具 举报

12

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-11-5
在线时间
31 小时
 楼主| 发表于 2019-1-24 11:32:14 | 显示全部楼层
cjsyrzy 发表于 2019-1-24 11:07
我的理解是5kHz时,每秒要进入timer中断500000次,两次中断间隔2us,10kHz时,两次中断间隔1us,太短了,必 ...

这个可以用DMA来传输吗,但是还是会用到定时器啊
回复

使用道具 举报

12

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-11-5
在线时间
31 小时
 楼主| 发表于 2019-1-24 11:43:14 | 显示全部楼层
cjsyrzy 发表于 2019-1-24 11:07
我的理解是5kHz时,每秒要进入timer中断500000次,两次中断间隔2us,10kHz时,两次中断间隔1us,太短了,必 ...

这个可以用DMA来传输吗,但是还是会用到定时器啊
回复

使用道具 举报

1

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
130
金钱
130
注册时间
2017-11-14
在线时间
34 小时
发表于 2019-1-24 13:31:04 | 显示全部楼层
用定时器溢出事件触发DMA,数据从Wave1_Buffer到GPIOD->ODR,DMA移动数据比进中断程序处理快
回复

使用道具 举报

12

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-11-5
在线时间
31 小时
 楼主| 发表于 2019-1-24 16:03:28 | 显示全部楼层
cjsyrzy 发表于 2019-1-24 13:31
用定时器溢出事件触发DMA,数据从Wave1_Buffer到GPIOD->ODR,DMA移动数据比进中断程序处理快

这样的话定时器就不用进入中断了是吗
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2019-1-25 02:24:19 | 显示全部楼层
帮顶
回复

使用道具 举报

1

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
130
金钱
130
注册时间
2017-11-14
在线时间
34 小时
发表于 2019-1-25 10:04:28 | 显示全部楼层
不用进中断,只需要在DMA响应前准备好数据存到Wave1_Buffer
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-9 17:30

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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