历史上的今天
返回首页

历史上的今天

今天是:2024年08月31日(星期六)

2018年08月31日 | STM32实验1:定时器中断同时产生两路不同频率的信号

2018-08-31 来源:eefocus

一、实验目的

使用STM32同时产生两路不同频率的信号,并通过观察开发板两个LED闪烁快慢的现象,以及在MDK5中软件仿真逻辑分析中查看波形,体现两路信号频率的不同。

二、实验原理

通过定时器中断配置,定时器3每600ms中断一次,然后中断服务函数中控制LED实现LED1状态取反(闪烁);定时器4每200ms中断一次,然后中断服务函数中控制LED实现LED0状态取反(闪烁)。

本实验用到的硬件资源有: 
1) 指示灯 LED0 和 LED1 
2) 定时器 TIM3,TIM4 
TIM3,TIM4属于 STM32 的内部资源,只需要软件设置即可正常工作。

1、通用定时器电路框图 
通用定时器电路框图

2、计数器模式 
采用向上计数 
向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。 
这里写图片描述

3、信号周期计算(定时器溢出时间) 
TIM3 的时钟为 72 M,再根据我们设计的 arr 和 psc的值, 就可以计算中断时间了。公式如下: 
Tout= ((arr +1)*(psc+1)) /Tclk; 
其中: 
Tclk :TIM3 的输入时钟频率 (单位为 Mhz)。 
Tout :TIM3 溢出时间(单位为 us)。

4、定时器中断实现步骤 
(1) 能定时器时钟。 
RCC_APB1PeriphClockCmd(); 
(2) 初始化定时器,配置ARR,PSC。 
TIM_TimeBaseInit(); 
(3) 开启定时器中断,配置NVIC。 
void TIM_ITConfig(); 
NVIC_Init(); 
(4) 使能定时器。 
TIM_Cmd(); 
(5) 编写中断服务函数。 
TIMx_IRQHandler();

三、实验代码

timer.c

#include "timer.h"

#include "led.h"

//通用定时器3中断初始化

//这里时钟选择为APB1的2倍,而APB1为36M

//arr:自动重装值。

//psc:时钟预分频数

//这里使用的是定时器3!

void TIM3_Int_Init(u16 arr,u16 psc)

{

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    NVIC_InitTypeDef NVIC_InitStructure;


    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能


    //定时器TIM3初始化

    TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值   

    TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位


    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断


    //中断优先级NVIC设置

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

    NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器



    TIM_Cmd(TIM3, ENABLE);  //使能TIMx                     

}

//定时器3中断服务程序

void TIM3_IRQHandler(void)   //TIM3中断

{

    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否

        {

        TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 

        LED1=!LED1;

        }

}


//这里使用的是定时器4!

void TIM4_Int_Init(u16 arr,u16 psc)

{

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    NVIC_InitTypeDef NVIC_InitStructure;


    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能


    //定时器TIM4初始化

    TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值   

    TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式

    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位


    TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM4中断,允许更新中断


    //中断优先级NVIC设置

    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  //TIM4中断

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

    NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器



    TIM_Cmd(TIM4, ENABLE);  //使能TIMx                     

}

//定时器4中断服务程序

void TIM4_IRQHandler(void)   //TIM4中断

{

    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)  //检查TIM4更新中断发生与否

        {

        TIM_ClearITPendingBit(TIM4, TIM_IT_Update  );  //清除TIMx更新中断标志 

        LED0=!LED0;

        }

}


main.c


#include "led.h"

#include "delay.h"

#include "key.h"

#include "sys.h"

#include "usart.h"

#include "timer.h"


 int main(void)

 {      


    delay_init();            //延时函数初始化    

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级

    uart_init(115200);   //串口初始化为115200

    LED_Init();              //LED端口初始化

    TIM3_Int_Init(5999,7199);//10Khz的计数频率,计数到6000为600ms  

    TIM4_Int_Init(1999,7199);//10Khz的计数频率,计数到2000为200ms 


     while(1)

    {

    }    



}    

四、结果分析

1、MDK5的软件仿真中的逻辑分析

这里写图片描述

波形对应LED说明如下

定时器亮灯引脚周期波形颜色
TIM3LED1(绿色灯)PE5600ms绿色波
TIM4LED0(红色灯)PB5200ms红色波

2、开发板现象 
如图 
LED0红色灯闪的更快,差不多是红色灯闪3次,绿色灯闪1次。 
这与软件仿真相符。

这里写图片描述
3、注意事项 
要确认外部晶振频率为8.0Mhz,不然会计时不准。 
这里写图片描述

这里写图片描述


推荐阅读

史海拾趣

问答坊 | AI 解惑

我的独轮汽车防撞设计方案

我的独轮汽车防撞设计方案 传动轴是与坚硬的圆球外轮内胆作为一体的,并且是该内胆的中心轴,发动机和驾乘着都是垂直悬挂于该轴上且全部在球状轮内,汽车的进退是通过发动机提供能量绕轴旋转改变悬挂的离地高度来实现,转向是通过左右移动悬挂 ...…

查看全部问答>

请问SAA7113的LLC输出的信号是方波还是其他什么波形

SAA7113的LLC应该是每个像素点的同步信号,请问SAA7113的LLC输出的信号是方波还是其他什么波形?我用的时候,出来的波形是锯齿波,感觉不对?有谁用过,帮我确认一下!…

查看全部问答>

头文件 STC12C5A60S2

挺好的  大家快下…

查看全部问答>

新人报道

RT,接下来的日子还请各位前辈多多帮助。O(∩_∩)O哈哈~…

查看全部问答>

symbian开发介绍

Symbian开发内容介绍热线:010-51292078 021-51875830  0755-61280252 传真:021-62450161   010-62475416业务手机:15921673576曙海培训网站:http://www.51qianru.cn曙海培训曙海培训pads培训Cadence培训Allegro培训<a href=\" ...…

查看全部问答>

新人问个程序移植的土问题,送100分

俺要把一个跑在Windows CE(ARM)上的程序移植到Windows CE(MIPS)上去。 现在已经可以编译链接成功了,但是在Windows CE(MIPS)上一执行exe文件就报错,错误是“找不到($俺的程序名)或它的某一个组件。请确认路径和文件名正确并且所需要的库全部可用 ...…

查看全部问答>

想找omnivision的图像传感器,但是代理商都要求很大的批量才行,我只需要几片,该怎么办呀?

在学校,做东西的时候需要几片CMOS图像传感器,现在选定的是omnivision的ov7740,找了很多代理商,但是都要求要一个包装的才能订货,也就是1700片左右,我的天啊,我哪里能承受地起,现在我该怎么办呢? 之前选定的是cypress赛普拉斯的CMOS图像传 ...…

查看全部问答>

求GPS+GPRS ODM或OEM厂商或高手作私活^_^

如题。 具体细节欢迎来电商谈13366178752或Email:niugong@sina.com 谢谢!!^_^…

查看全部问答>

nk.bin大小的问题

wince5.0 nk.bin大于32M不能保存到NANDFLASH,因为进入CE后后面的32M被格式化了(NANDFLASH总共64M),请问怎么才能保存更大的NK.BIN?我想从48M的位置开始格式化,怎么才能做到?…

查看全部问答>

菜鸟问个数据包问题

我手头有个文本文件,内容如下: 0x25, 0x01, 0x01, 0x10, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xd8, 0xcf, 0xc2, 0xa3, 0xb1, 0xb3, 0xac, 0xca, 0xd0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1 ...…

查看全部问答>